different-ai/openwork · error

Manual OIDC configuration requires authorization, token, and

Error message

Manual OIDC configuration requires authorization, token, and JWKS endpoints.

What it means

resolveOidcEndpoints supports manual OIDC configuration when discovery is skipped. In skipDiscovery mode all three endpoints — authorizationEndpoint, tokenEndpoint, and jwksEndpoint — are mandatory; any missing one throws this Error.

Source

Thrown at ee/apps/den-api/src/sso.ts:104

    const url = new URL(issuer)
    return url.hostname === "127.0.0.1" || url.hostname === "localhost"
  } catch {
    return false
  }
}

function getOidcDiscoveryUrl(issuer: string) {
  return `${issuer.replace(/\/$/, "")}/.well-known/openid-configuration`
}

function normalizeIssuer(value: string) {
  return value.replace(/\/$/, "")
}

async function resolveOidcEndpoints(input: OidcRegistrationInput) {
  if (input.skipDiscovery) {
    if (!input.authorizationEndpoint || !input.tokenEndpoint || !input.jwksEndpoint) {
      throw new Error("Manual OIDC configuration requires authorization, token, and JWKS endpoints.")
    }

    return {
      skipDiscovery: true,
      authorizationEndpoint: input.authorizationEndpoint,
      tokenEndpoint: input.tokenEndpoint,
      jwksEndpoint: input.jwksEndpoint,
      userInfoEndpoint: input.userInfoEndpoint ?? undefined,
      tokenEndpointAuthentication: input.tokenEndpointAuthentication ?? undefined,
    }
  }

  const response = await fetch(getOidcDiscoveryUrl(input.issuer), {
    headers: { accept: "application/json" },
    signal: AbortSignal.timeout(10_000),
  })
  if (!response.ok) {
    throw new Error(`OIDC discovery failed with ${response.status}. Enter manual OIDC endpoints or enable skip discovery.`)

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Provide all three endpoints (authorization, token, JWKS) in the manual OIDC configuration
  2. If your provider exposes /.well-known/openid-configuration, set skipDiscovery: false and supply only the issuer instead
  3. Verify each endpoint URL is absolute and correct for your IdP (Auth0, Okta, Entra ID, Keycloak)

Example fix

// before
{ issuer: 'https://idp.example.com', skipDiscovery: true, authorizationEndpoint: 'https://idp.example.com/authorize' }
// after
{ issuer: 'https://idp.example.com', skipDiscovery: true, authorizationEndpoint: 'https://idp.example.com/authorize', tokenEndpoint: 'https://idp.example.com/token', jwksEndpoint: 'https://idp.example.com/.well-known/jwks.json' }
Defensive patterns

Strategy: validation

Validate before calling

const missing = [
  input.authorizationEndpoint ? null : 'authorizationEndpoint',
  input.tokenEndpoint ? null : 'tokenEndpoint',
  input.jwksEndpoint ? null : 'jwksEndpoint',
].filter(Boolean)
if (input.skipDiscovery && missing.length > 0) throw new Error(`Manual OIDC configuration missing: ${missing.join(', ')}`)

Type guard

function isCompleteManualOidcConfig(i: Partial<OidcRegistrationInput> & { skipDiscovery?: boolean }): i is OidcRegistrationInput {
  return !i.skipDiscovery || Boolean(i.authorizationEndpoint && i.tokenEndpoint && i.jwksEndpoint)
}

Try / catch

try {
  await resolveOidcEndpoints(input)
} catch (e) {
  if (e instanceof Error && e.message.includes('Manual OIDC configuration requires')) {
    // return 400 with which endpoints are missing
  } else throw e
}

Prevention

When it happens

Trigger: Registering an OIDC SSO connection with skipDiscovery: true while omitting one or more of authorizationEndpoint, tokenEndpoint, or jwksEndpoint in OidcRegistrationInput.

Common situations: Admin pasted only the issuer and authorization URL assuming discovery; JWKS URL forgotten; provider docs give discovery only and admin toggled skipDiscovery unnecessarily; partial copy/paste of endpoint config.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/c3c59b065430761a. Report an issue: GitHub.