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
- 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)
- Pin wellKnown/authorization/token endpoints manually (skip discovery) if the provider cannot return a matching issuer: set authorization: { url }, token, userinfo, jwks_endpoint directly
- Check for proxy/gateway rewriting and use the issuer exactly as the provider advertises it
- 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
- Copy the issuer verbatim from the provider's well-known document (watch trailing slashes, http vs https)
- For Azure AD use https://login.microsoftonline.com/{tenant}/v2.0, not legacy sts.windows.net
- Pin explicit endpoints (authorization/token/userinfo) when a proxy rewrites the issuer
- Test discovery with curl during setup before wiring the provider
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
- TODO: Authorization server did not provide a token endpoint.
- Authorization server did not provide an authorization endpoi
- TODO: Authorization server did not provide a userinfo endpoi
- unsupported client authentication method
- No userinfo endpoint configured
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/ffbacf913d799b9c.
Report an issue: GitHub.