nextauthjs/next-auth · critical

TODO: Authorization server did not provide a userinfo endpoi

Error message

TODO: Authorization server did not provide a userinfo endpoint.

What it means

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.

Source

Thrown at packages/core/src/lib/actions/callback/oauth/callback.ts:77

    (!token?.url || token.url.host === "authjs.dev") &&
    (!userinfo?.url || userinfo.url.host === "authjs.dev")
  ) {
    // We assume that issuer is always defined as this has been asserted earlier

    const issuer = new URL(provider.issuer!)
    const discoveryResponse = await o.discoveryRequest(issuer, {
      [o.allowInsecureRequests]: true,
      [o.customFetch]: provider[customFetch],
    })
    as = await o.processDiscoveryResponse(issuer, discoveryResponse)

    if (!as.token_endpoint)
      throw new TypeError(
        "TODO: Authorization server did not provide a token endpoint."
      )

    if (!as.userinfo_endpoint)
      throw new TypeError(
        "TODO: Authorization server did not provide a userinfo endpoint."
      )
  } else {
    as = {
      issuer: provider.issuer ?? "https://authjs.dev", // TODO: review fallback issuer
      token_endpoint: token?.url.toString(),
      userinfo_endpoint: userinfo?.url.toString(),
    }
  }

  const client: o.Client = {
    client_id: provider.clientId,
    ...provider.client,
  }

  let clientAuth: o.ClientAuth

  switch (client.token_endpoint_auth_method) {

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Declare `userinfo` explicitly in the provider config (URL string or { url, params }) so discovery's missing field is bypassed
  2. Confirm the server actually supports OIDC; otherwise set provider type to "oauth" and specify endpoints manually
  3. Validate the discovery document at {issuer}/.well-known/openid-configuration includes userinfo_endpoint
  4. Correct the issuer URL if discovery is being fetched from the wrong host

Example fix

// before
providers: [{ id: "acme", type: "oauth", issuer: "https://sso.acme.com" }]
// after
providers: [{
  id: "acme",
  type: "oauth",
  issuer: "https://sso.acme.com",
  userinfo: "https://sso.acme.com/userinfo",
  authorization: { url: "https://sso.acme.com/authorize" },
  token: "https://sso.acme.com/token"
}]
Defensive patterns

Strategy: validation

Validate before calling

const doc = await fetch(`${issuer}/.well-known/openid-configuration`).then(r => r.json())
if (!doc.userinfo_endpoint) throw new Error(`Issuer ${issuer} has no userinfo_endpoint`)

Type guard

function hasUserinfoEndpoint(as: unknown): as is { userinfo_endpoint: string } {
  return typeof as === "object" && as !== null && typeof (as as any).userinfo_endpoint === "string"
}

Try / catch

try {
  await signIn(providerId)
} catch (e) {
  if ((e as Error).message.includes("did not provide a userinfo endpoint")) {
    // declare `userinfo` explicitly in the provider config
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/a9c6bfa9e43fe11c. Report an issue: GitHub.