immich-app/immich · critical · InternalServerErrorException

Error in OAuth discovery: ${error}

Error message

Error in OAuth discovery: ${error}

What it means

`getClient` performs OIDC discovery against the provider's well-known configuration using openid-client and wraps any failure in an InternalServerErrorException('Error in OAuth discovery: ...'). The original error (which may be an AggregateError from multiple discovery endpoints) is attached as `cause`. This means the server could not obtain/validate the provider's OIDC metadata.

Source

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

    try {
      return await discovery(
        new URL(issuerUrl),
        clientId,
        {
          client_secret: clientSecret,
          response_types: ['code'],
          userinfo_signed_response_alg: profileSigningAlgorithm === 'none' ? undefined : profileSigningAlgorithm,
          id_token_signed_response_alg: signingAlgorithm,
        },
        this.getTokenAuthMethod(tokenEndpointAuthMethod, clientSecret),
        {
          execute: allowInsecureRequests ? [allowInsecureRequestsExecute] : [],
          timeout,
        },
      );
    } catch (error: any | AggregateError) {
      this.logger.error('Error in OAuth discovery', error);
      throw new InternalServerErrorException(`Error in OAuth discovery: ${error}`, { cause: error });
    }
  }

  private getTokenAuthMethod(tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod, clientSecret?: string) {
    if (!clientSecret) {
      return None();
    }

    switch (tokenEndpointAuthMethod) {
      case OAuthTokenEndpointAuthMethod.ClientSecretPost: {
        return ClientSecretPost(clientSecret);
      }

      case OAuthTokenEndpointAuthMethod.ClientSecretBasic: {
        return ClientSecretBasic(clientSecret);
      }

      default: {

View on GitHub (pinned to 5666d57f15)

Solutions

  1. Read `error.cause` (and server logs — the original error is logged) to see the underlying failure: DNS, TLS, or HTTP status.
  2. Open `<issuer>/.well-known/openid-configuration` from the server (curl inside the container) and verify it returns valid JSON with matching issuer.
  3. Fix the issuer URL in OAuth settings — it must exactly match the `issuer` claim in the discovery document.
  4. For self-signed/internal CAs, install the CA cert in the server's trust store or set NODE_EXTRA_CA_CERTS.
  5. For plain-HTTP internal providers, enable insecure request allowance (allowInsecureRequests) — only on trusted internal networks.

Example fix

// before
issuerUrl: 'https://keycloak:8080/realms/myrealm' // server can't reach 'keycloak'
// after
issuerUrl: 'https://keycloak.internal:8080/realms/myrealm' // resolvable from server
// or curl from inside the container first to verify discovery JSON
Defensive patterns

Strategy: validation

Validate before calling

// verify discovery before configuring/using the client
const res = await fetch(`${issuerUrl}/.well-known/openid-configuration`);
if (!res.ok) throw new Error(`discovery HTTP ${res.status}`);
const doc = await res.json();
if (doc.issuer !== issuerUrl) throw new Error('issuer mismatch');

Type guard

function isInternalServerError(e: unknown): e is { status: number; response: string } {
  return typeof e === 'object' && e !== null && 'status' in e && (e as any).status === 500;
}

Try / catch

try {
  const client = await getClient(issuerUrl, clientId, clientSecret);
} catch (e) {
  // cause holds the original discovery error (may be AggregateError)
  console.error('discovery failed:', (e as any).cause ?? e);
  throw new ServiceUnavailable('OAuth provider unreachable');
}

Prevention

When it happens

Trigger: The issuer URL is wrong or lacks a valid `/.well-known/openid-configuration`; the provider is unreachable from the server (DNS, firewall, Docker network); the provider uses plain HTTP while secure fetch is enforced (allowInsecureRequests not enabled); TLS certificate errors (self-signed certs); discovery document missing required fields (issuer mismatch, no supported algorithms).

Common situations: Misconfigured issuer URL in server settings (trailing path mistakes, http vs https); self-hosted Keycloak/Authentik not reachable from the server container; self-signed or internal CA certificates; provider behind mTLS or an auth-gated proxy.

Related errors


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