immich-app/immich · error · Error

OAuth login failed

Error message

OAuth login failed

What it means

`getProfileAndOAuthSid` exchanges the OAuth code (or verifies the token) with the provider and fetches the user profile. Any failure in that flow — token exchange, profile fetch, network errors, provider rejections — is caught, logged, and rethrown as a generic Error('OAuth login failed') with the underlying error as `cause`. The generic message hides details, so the `cause` (and server logs) must be inspected to find the real reason.

Source

Thrown at server/src/repositories/oauth.repository.ts:128

        if (typeof claims?.sid === 'string') {
          sid = claims.sid;
        }
      }

      return { profile, sid, idToken: tokens.id_token };
    } catch (error: Error | any) {
      if (error.message.includes('unexpected JWT alg received')) {
        this.logger.warn(
          [
            'Algorithm mismatch. Make sure the signing algorithm is set correctly in the OAuth settings.',
            'Or, that you have specified a signing key in your OAuth provider.',
          ].join(' '),
        );
      }

      this.logger.error('OAuth login failed', error);

      throw new Error('OAuth login failed', { cause: error });
    }
  }

  async getProfilePicture(url: string) {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`Failed to fetch picture: ${response.statusText}`);
    }

    return response.arrayBuffer();
  }

  private jwksClients: Map<string, JWTVerifyGetKey> = new Map(); // useful for caching and performnce
  async validateLogoutToken(config: OAuthConfig, logoutToken: string): Promise<{ sub?: string; sid?: string } | null> {
    const client = await this.getClient(config);
    const algorithm = client.clientMetadata().id_token_signed_response_alg ?? 'RS256';
    let keyOrGetter: Uint8Array | JWTVerifyGetKey;

View on GitHub (pinned to 5666d57f15)

Solutions

  1. Log/inspect `error.cause` (also check server logs — this.logger.error already logs the original error) to see the real provider failure.
  2. Verify the OAuth provider config: client_id, client_secret, issuer URL, and redirect URI exactly match the provider app registration.
  3. Test connectivity from the server to the provider's token/userinfo endpoints (curl the discovery URL) — self-hosted providers often fail due to Docker DNS/network isolation.
  4. Ensure the authorization code is single-use and recent: don't replay callback URLs or reuse codes.
  5. Check server clock sync (NTP) if tokens are rejected as expired.

Example fix

try {
  await loginWithOAuth(code);
} catch (e) {
  console.error('root cause:', (e as Error).cause); // see real provider error
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify provider discovery is reachable and config is set
const cfg = await fetch(`${issuerUrl}/.well-known/openid-configuration`).then(r => r.json());
if (!cfg.token_endpoint || !cfg.userinfo_endpoint) throw new Error('provider config incomplete');

Type guard

function hasCause(e: unknown): e is Error & { cause: unknown } {
  return e instanceof Error && 'cause' in e;
}

Try / catch

try {
  const profile = await getProfileAndOAuthSid(code);
} catch (e) {
  if (hasCause(e)) console.error('OAuth failure root cause:', e.cause);
  // redirect user to login with a generic error; never expose provider details
}

Prevention

When it happens

Trigger: Calling the OAuth login endpoint with an invalid/expired/already-used authorization `code`; mismatched client_id/client_secret or redirect_uri vs. what the provider expects; the provider's token or userinfo endpoint being unreachable or returning 4xx/5xx; malformed id_token/access_token (wrong issuer, audience, expired); network failures to the provider.

Common situations: Incorrect OAuth client configuration in server settings (wrong client secret, redirect URI not registered); user taking too long and the code expiring; replaying a callback URL; provider outage or self-hosted provider (e.g. Authentik/Keycloak) behind DNS that the server can't resolve; clock skew invalidating tokens.

Related errors


AI-assisted analysis of immich-app/immich@5666d57f15 (2026-09-01). Data as JSON: /api/errors/a9f9b5db52e5d39b. Report an issue: GitHub.