nextauthjs/next-auth · error

Discovery request responded with an invalid issuer. expected

Error message

Discovery request responded with an invalid issuer. expected: ${issuer}

What it means

During OIDC discovery, the openid-client library validates that the issuer returned in the discovery document exactly matches the configured issuer URL. Auth.js catches the 'Invalid URL' TypeError from that validation and rethrows it with the expected issuer, meaning the provider's well-known endpoint returned a different issuer value.

Source

Thrown at packages/core/src/lib/actions/signin/authorization-url.ts:38

  let as: o.AuthorizationServer | undefined

  // Falls back to authjs.dev if the user only passed params
  if (!url || url.host === "authjs.dev") {
    // If url is undefined, we assume that issuer is always defined
    // We check this in assert.ts

    const issuer = new URL(provider.issuer!)
    const discoveryResponse = await o.discoveryRequest(issuer, {
      [o.customFetch]: provider[customFetch],
      // TODO: move away from allowing insecure HTTP requests
      [o.allowInsecureRequests]: true,
    })
    const as = await o
      .processDiscoveryResponse(issuer, discoveryResponse)
      .catch((error) => {
        if (!(error instanceof TypeError) || error.message !== "Invalid URL")
          throw error
        throw new TypeError(
          `Discovery request responded with an invalid issuer. expected: ${issuer}`
        )
      })

    if (!as.authorization_endpoint) {
      throw new TypeError(
        "Authorization server did not provide an authorization endpoint."
      )
    }

    url = new URL(as.authorization_endpoint)
  }

  const authParams = url.searchParams

  let redirect_uri: string = provider.callbackUrl
  let data: string | undefined
  if (!options.isOnRedirectProxy && provider.redirectProxyUrl) {

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Compare the 'issuer' field in {provider.issuer}/.well-known/openid-configuration with your configured issuer and make them byte-identical (scheme, host, port, path, no trailing slash)
  2. Pin wellKnown/authorization/token endpoints manually (skip discovery) if the provider cannot return a matching issuer: set authorization: { url }, token, userinfo, jwks_endpoint directly
  3. Check for proxy/gateway rewriting and use the issuer exactly as the provider advertises it
  4. For Azure AD, use https://login.microsoftonline.com/{tenant}/v2.0 as issuer (matching the discovery document), not the sts.windows.net legacy issuer

Example fix

// before
issuer: "https://accounts.example.com", // discovery returns https://accounts.example.com/oidc
// after
issuer: "https://accounts.example.com/oidc"; // matches the issuer claim exactly
Defensive patterns

Strategy: validation

Validate before calling

const doc = await fetch(`${issuer}/.well-known/openid-configuration`).then(r => r.json());
if (doc.issuer !== issuer) throw new Error(`Issuer mismatch: configured ${issuer}, provider returns ${doc.issuer}`);

Type guard

function matchesIssuer(doc: { issuer?: string }, issuer: string): doc is { issuer: string } {
  return doc.issuer === issuer;
}

Try / catch

try {
  await signIn('oidc');
} catch (e) {
  if (/invalid issuer/.test(String(e))) {
    // compare discovery doc issuer with configured issuer; adjust issuer or set endpoints manually
  }
}

Prevention

When it happens

Trigger: Configuring provider.issuer with a URL whose scheme/host/port/path differs (even a trailing slash) from the 'issuer' claim in the provider's /.well-known/openid-configuration response; discovery document served from a mirror or proxy that rewrites the issuer.

Common situations: Issuer mismatch like http vs https, missing/extra trailing slash, localhost vs 127.0.0.1; providers behind API gateways that return an internal URL as issuer; Keycloak realms where the realm name in the issuer differs from the discovery URL; Azure AD vs Azure AD Graph issuer casing (login.microsoftonline.com vs sts.windows.net).

Related errors


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