OAuth start: connect keeps admitting identity providers, as Bifrost uses it
The first gate refused connect for a provider outside managedConnectionProviders, which broke Bifrost's existing Discord connect. sign_in and link still take identityProviders only, so a managed-only provider (Joystick) can never sign anyone in or link; connect takes either list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b15bf33b21
commit
c1fbc1261a
3 changed files with 12 additions and 7 deletions
|
|
@ -42,7 +42,7 @@ In the service-first Heimdall version, the most likely reusable slice is:
|
|||
|
||||
- provider OAuth authority
|
||||
- identity-linking authority
|
||||
- managed Twitch/YouTube/Joystick credential custody for creator connections (Joystick is a managed connection only, not a viewer sign-in provider: `startOAuthFlow` admits `sign_in` and `link` only for `identityProviders` and `connect` only for `managedConnectionProviders`, and refuses anything else before any redirect)
|
||||
- managed Twitch/YouTube/Joystick credential custody for creator connections (Joystick is a managed connection only, not a viewer sign-in provider: `startOAuthFlow` admits `sign_in` and `link` only for `identityProviders` and `connect` only for `managedConnectionProviders` or `identityProviders`, and refuses anything else before any redirect)
|
||||
- entitlement refresh
|
||||
- shared claim semantics
|
||||
|
||||
|
|
|
|||
|
|
@ -225,13 +225,15 @@ export function serializeAppProfile(profile: AppProfile): Record<string, unknown
|
|||
/**
|
||||
* Whether the profile admits this provider for this mode. The role lists
|
||||
* decide: `sign_in` and `link` mint viewer identity, so they take only
|
||||
* `identityProviders`; `connect` takes custody of a creator credential, so it
|
||||
* takes only `managedConnectionProviders`. A provider in neither list for the
|
||||
* mode is refused before any redirect.
|
||||
* `identityProviders`; a provider that is only a managed connection (Joystick)
|
||||
* can never sign anyone in or link. `connect` takes either list:
|
||||
* `managedConnectionProviders` for creator credentials, and
|
||||
* `identityProviders` because Bifrost and its siblings already connect their
|
||||
* identity providers. A provider in neither list is refused before any redirect.
|
||||
*/
|
||||
export function admitsProviderForMode(profile: AppProfile, provider: Provider, mode: OAuthMode): boolean {
|
||||
return mode === "connect"
|
||||
? profile.managedConnectionProviders.includes(provider)
|
||||
? profile.managedConnectionProviders.includes(provider) || profile.identityProviders.includes(provider)
|
||||
: profile.identityProviders.includes(provider);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2023,7 +2023,7 @@ describe("OAuth start admits a provider by the profile's role for the mode", ()
|
|||
const allProviders = ["discord", "patreon", "github", "twitch", "youtube", "spotify", "joystick"] as const;
|
||||
const modes = ["sign_in", "link", "connect"] as const;
|
||||
|
||||
it("sign_in and link take identityProviders only; connect takes managedConnectionProviders only, for every profile", async () => {
|
||||
it("sign_in and link take identityProviders only; connect takes managedConnectionProviders or identityProviders, for every profile", async () => {
|
||||
const app = await buildApp({ config: createTestConfig() });
|
||||
try {
|
||||
for (const profile of Object.values(builtInAppProfiles)) {
|
||||
|
|
@ -2034,7 +2034,10 @@ describe("OAuth start admits a provider by the profile's role for the mode", ()
|
|||
url: `/v1/oauth/${provider}/start`,
|
||||
payload: { appSlug: profile.slug, mode, returnTo: `${profile.allowedReturnOrigins[0]}/x` },
|
||||
});
|
||||
const roleList = mode === "connect" ? profile.managedConnectionProviders : profile.identityProviders;
|
||||
const roleList =
|
||||
mode === "connect"
|
||||
? [...profile.managedConnectionProviders, ...profile.identityProviders]
|
||||
: profile.identityProviders;
|
||||
const refused = start.json().error === "provider_not_supported_for_app";
|
||||
expect([profile.slug, provider, mode, refused]).toEqual([profile.slug, provider, mode, !roleList.includes(provider)]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue