toeverything/AFFiNE · error · UnknownOauthProvider

unknown_oauth_provider

unknown_oauth_provider

Error message

Unknown authentication provider ${name}.

What it means

POST /oauth/preflight throws UnknownOauthProvider at the schema-validation branch when the `provider` field itself fails the OAuthProviderSchema enum ('Google', 'GitHub', 'Apple', 'OIDC'). The thrown name is derived by stringifying whatever was sent, so the error message echoes your invalid input. This fires before the provider registry is even consulted.

Source

Thrown at packages/backend/server/src/plugins/oauth/controller.ts:57

  @UseNamedGuard('version')
  @Post('/preflight')
  @HttpCode(HttpStatus.OK)
  async preflight(@Req() req: Request, @Body() body?: unknown) {
    const input = OAuthPreflightBodySchema.safeParse(body);
    if (!input.success) {
      const fields = new Set(input.error.issues.map(issue => issue.path[0]));
      if (fields.has('client_nonce')) {
        throw new MissingOauthQueryParameter({ name: 'client_nonce' });
      }
      if (fields.has('client')) {
        throw new ActionForbidden();
      }
      if (fields.has('provider')) {
        const provider =
          body && typeof body === 'object' && 'provider' in body
            ? String(body.provider)
            : '';
        throw new UnknownOauthProvider({ name: provider });
      }
      throw new MissingOauthQueryParameter({ name: 'provider' });
    }

    const {
      provider: unknownProviderName,
      redirect_uri: redirectUri,
      client,
      client_nonce: clientNonce,
    } = input.data;

    const providerName =
      OAuthProviderName[unknownProviderName as keyof typeof OAuthProviderName];
    const provider = this.providerFactory.get(providerName);

    if (!provider) {
      throw new UnknownOauthProvider({ name: unknownProviderName });
    }

View on GitHub (pinned to 591f874dad)

Solutions

  1. Use an exact enum value with exact casing: 'Google', 'GitHub', 'Apple', or 'OIDC'
  2. For any other IdP (Keycloak, Okta, Azure AD, Casdoor...), configure the server's generic OIDC provider and send provider: 'OIDC'
  3. Check the error's name field — it echoes exactly what you sent, which pinpoints the casing/value bug

Example fix

// before
{ provider: 'google', client: 'web', client_nonce: nonce }

// after
{ provider: 'Google', client: 'web', client_nonce: nonce }
Defensive patterns

Strategy: validation

Validate before calling

const PROVIDERS = ['Google', 'GitHub', 'Apple', 'OIDC'] as const;
if (!PROVIDERS.includes(provider)) {
  throw new Error(`provider must be one of ${PROVIDERS.join(', ')} (case-sensitive); use 'OIDC' for generic providers`);
}

Type guard

type ProviderName = 'Google' | 'GitHub' | 'Apple' | 'OIDC';
function isProviderName(p: unknown): p is ProviderName {
  return typeof p === 'string' && ['Google', 'GitHub', 'Apple', 'OIDC'].includes(p);
}

Try / catch

try { await post('/oauth/preflight', body); } catch (e) {
  if ((e as any).code === 'unknown_oauth_provider') {
    // e.args.name echoes exactly what we sent — compare against the enum to find the typo
    throw new Error(`Unknown provider '${(e as any).args.name}'; expected one of Google|GitHub|Apple|OIDC`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Preflight body with provider outside the enum or wrong casing: 'google', 'github', 'oidc', 'Facebook', 'Microsoft', or provider missing entirely (issue path 'provider'). The name in the message will be String(body.provider) — often 'undefined' when the field is absent.

Common situations: Integrating a provider AFFiNE doesn't support natively (use OIDC generic provider for those); case-sensitive enum catching lowercase names; frontend dropdown storing lowercase keys.

Understand the failure class

Related errors


AI-assisted analysis of toeverything/AFFiNE@591f874dad (2026-08-18). Data as JSON: /api/errors/e9bf7de289ab176e. Report an issue: GitHub.