{"record":{"id":"d86163c7ebc864a0","repo":"different-ai/openwork","slug":"oidc-discovery-document-is-missing-required-endpoi","errorCode":null,"errorMessage":"OIDC discovery document is missing required endpoints.","messagePattern":"OIDC discovery document is missing required endpoints\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/sso.ts","lineNumber":127,"sourceCode":"      authorizationEndpoint: input.authorizationEndpoint,\n      tokenEndpoint: input.tokenEndpoint,\n      jwksEndpoint: input.jwksEndpoint,\n      userInfoEndpoint: input.userInfoEndpoint ?? undefined,\n      tokenEndpointAuthentication: input.tokenEndpointAuthentication ?? undefined,\n    }\n  }\n\n  const response = await fetch(getOidcDiscoveryUrl(input.issuer), {\n    headers: { accept: \"application/json\" },\n    signal: AbortSignal.timeout(10_000),\n  })\n  if (!response.ok) {\n    throw new Error(`OIDC discovery failed with ${response.status}. Enter manual OIDC endpoints or enable skip discovery.`)\n  }\n\n  const parsed = oidcDiscoverySchema.safeParse(await response.json())\n  if (!parsed.success) {\n    throw new Error(\"OIDC discovery document is missing required endpoints.\")\n  }\n  if (normalizeIssuer(parsed.data.issuer) !== normalizeIssuer(input.issuer)) {\n    throw new Error(\"OIDC discovery issuer does not match the configured issuer.\")\n  }\n\n  return {\n    skipDiscovery: true,\n    authorizationEndpoint: parsed.data.authorization_endpoint,\n    tokenEndpoint: parsed.data.token_endpoint,\n    jwksEndpoint: parsed.data.jwks_uri,\n    userInfoEndpoint: parsed.data.userinfo_endpoint,\n    tokenEndpointAuthentication: input.tokenEndpointAuthentication ?? undefined,\n  }\n}\n\nasync function getSsoProviderByProviderId(providerId: string) {\n  const rows = await db\n    .select()","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/sso.ts#L109-L145","documentation":"After fetching the discovery document, the response body is parsed with oidcDiscoverySchema. If the JSON lacks the required endpoint fields (or has wrong types), safeParse fails and this Error is thrown, meaning the document exists but is not a usable OIDC discovery payload.","triggerScenarios":"Discovery endpoint returns 200 with JSON missing authorization_endpoint, token_endpoint, or jwks_uri fields, or returning a non-JSON body (HTML error page, OAuth 2.0-only metadata).","commonSituations":"Plain OAuth2 server without OpenID Connect discovery fields; IdP serving an HTML login/error page with 200; truncated or proxied response; wrong URL returning some other JSON API's output.","solutions":["Confirm the IdP supports OpenID Connect discovery and its document includes authorization_endpoint, token_endpoint, and jwks_uri","If it is plain OAuth2, enter the endpoints manually with skipDiscovery: true","curl the discovery URL and inspect the JSON body for a proxy or error page"],"exampleFix":"// before\n// discovery returns { issuer: '...', authorization_endpoint: '...' } // missing token/jwks\n// after\n{ 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' }","handlingStrategy":"validation","validationCode":"const res = await fetch(getOidcDiscoveryUrl(issuer), { headers: { accept: 'application/json' } })\nconst body = await res.json()\nconst required = ['authorization_endpoint', 'token_endpoint', 'jwks_uri'] as const\nconst missing = required.filter((k) => typeof body?.[k] !== 'string' || !body[k])\nif (missing.length) throw new Error(`Discovery document missing: ${missing.join(', ')}`)","typeGuard":"function isOidcDiscoveryDocument(v: unknown): v is { authorization_endpoint: string; token_endpoint: string; jwks_uri: string } {\n  const d = v as Record<string, unknown>\n  return typeof d.authorization_endpoint === 'string' && typeof d.token_endpoint === 'string' && typeof d.jwks_uri === 'string'\n}","tryCatchPattern":"try {\n  await resolveOidcEndpoints(input)\n} catch (e) {\n  if (e instanceof Error && e.message === 'OIDC discovery document is missing required endpoints.') {\n    // provider lacks OIDC metadata; switch to manual endpoints\n  } else throw e\n}","preventionTips":["Confirm the provider is OpenID Connect (not plain OAuth2) before relying on discovery","curl the discovery URL and eyeball required fields when onboarding a new IdP","Prefer manual endpoint configuration for non-standard providers"],"tags":["oidc","sso","schema-validation","discovery"],"backgroundTag":"schema-validation-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}