{"record":{"id":"a9c6bfa9e43fe11c","repo":"nextauthjs/next-auth","slug":"todo-authorization-server-did-not-provide-a-useri","errorCode":null,"errorMessage":"TODO: Authorization server did not provide a userinfo endpoint.","messagePattern":"TODO: Authorization server did not provide a userinfo endpoint\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/core/src/lib/actions/callback/oauth/callback.ts","lineNumber":77,"sourceCode":"    (!token?.url || token.url.host === \"authjs.dev\") &&\n    (!userinfo?.url || userinfo.url.host === \"authjs.dev\")\n  ) {\n    // We assume that issuer is always defined as this has been asserted earlier\n\n    const issuer = new URL(provider.issuer!)\n    const discoveryResponse = await o.discoveryRequest(issuer, {\n      [o.allowInsecureRequests]: true,\n      [o.customFetch]: provider[customFetch],\n    })\n    as = await o.processDiscoveryResponse(issuer, discoveryResponse)\n\n    if (!as.token_endpoint)\n      throw new TypeError(\n        \"TODO: Authorization server did not provide a token endpoint.\"\n      )\n\n    if (!as.userinfo_endpoint)\n      throw new TypeError(\n        \"TODO: Authorization server did not provide a userinfo endpoint.\"\n      )\n  } else {\n    as = {\n      issuer: provider.issuer ?? \"https://authjs.dev\", // TODO: review fallback issuer\n      token_endpoint: token?.url.toString(),\n      userinfo_endpoint: userinfo?.url.toString(),\n    }\n  }\n\n  const client: o.Client = {\n    client_id: provider.clientId,\n    ...provider.client,\n  }\n\n  let clientAuth: o.ClientAuth\n\n  switch (client.token_endpoint_auth_method) {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/actions/callback/oauth/callback.ts#L59-L95","documentation":"After discovery succeeds, Auth.js requires a userinfo_endpoint to fetch the user profile with the access token. If the discovery document omits userinfo_endpoint, a TypeError with this placeholder message is thrown. Like the token-endpoint check, it signals incomplete or unexpected provider metadata.","triggerScenarios":"Discovery response from the configured issuer lacks userinfo_endpoint — typical for bare OAuth 2.0 servers (no OIDC profile support) or metadata documents served by an incorrectly pointed issuer.","commonSituations":"Using a pure OAuth2 authorization server that never publishes userinfo; issuer URL typo returning another service's discovery doc; provider type set to \"oidc\" against a non-OIDC server; custom wellKnown pointing at an endpoint that omits userinfo.","solutions":["Declare `userinfo` explicitly in the provider config (URL string or { url, params }) so discovery's missing field is bypassed","Confirm the server actually supports OIDC; otherwise set provider type to \"oauth\" and specify endpoints manually","Validate the discovery document at {issuer}/.well-known/openid-configuration includes userinfo_endpoint","Correct the issuer URL if discovery is being fetched from the wrong host"],"exampleFix":"// before\nproviders: [{ id: \"acme\", type: \"oauth\", issuer: \"https://sso.acme.com\" }]\n// after\nproviders: [{\n  id: \"acme\",\n  type: \"oauth\",\n  issuer: \"https://sso.acme.com\",\n  userinfo: \"https://sso.acme.com/userinfo\",\n  authorization: { url: \"https://sso.acme.com/authorize\" },\n  token: \"https://sso.acme.com/token\"\n}]","handlingStrategy":"validation","validationCode":"const doc = await fetch(`${issuer}/.well-known/openid-configuration`).then(r => r.json())\nif (!doc.userinfo_endpoint) throw new Error(`Issuer ${issuer} has no userinfo_endpoint`)","typeGuard":"function hasUserinfoEndpoint(as: unknown): as is { userinfo_endpoint: string } {\n  return typeof as === \"object\" && as !== null && typeof (as as any).userinfo_endpoint === \"string\"\n}","tryCatchPattern":"try {\n  await signIn(providerId)\n} catch (e) {\n  if ((e as Error).message.includes(\"did not provide a userinfo endpoint\")) {\n    // declare `userinfo` explicitly in the provider config\n  }\n}","preventionTips":["Declare `userinfo` manually for OAuth2 servers without OIDC profile support","Verify the discovery document contains userinfo_endpoint before wiring the provider","Use provider type \"oauth\" (not \"oidc\") for non-OIDC servers","Confirm the issuer URL resolves to the intended auth server"],"tags":["oauth","oidc","discovery","userinfo"],"backgroundTag":"oauth-discovery-incomplete","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}