hashicorp/nomad · error
no OIDC request found for client nonce
Error message
no OIDC request found for client nonce
What it means
OIDCCompleteAuth looks up the pending OIDC request that OIDCAuthURL stored in a server-side cache keyed by ClientNonce. If LoadAndDelete finds no entry, the login flow cannot continue and this error is returned. The cache is per-leader in-memory state, so any event that wipes it (leader failover, expiry, restart) or a mismatched nonce triggers the error.
Source
Thrown at nomad/acl_endpoint.go:2789
// validated
providerMetadata := struct {
AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported"`
}{}
if err := oidcProvider.Claims(&providerMetadata); err != nil {
return fmt.Errorf("failed to retrieve OIDC provider metadata: %w", err)
}
if providerMetadata.AuthorizationResponseIssParameterSupported {
if args.Iss == "" || args.Iss != authMethod.Config.OIDCDiscoveryURL {
return errors.New("invalid or missing issuer parameter in callback")
}
}
// Retrieve the request generated in OIDCAuthURL()
oidcReq := a.oidcRequestCache.LoadAndDelete(args.ClientNonce) // I am so done with this NONCENSE
if oidcReq == nil {
// note: this may happen if there is a leader election between getting
// the auth url and completing the login flow here.
return errors.New("no OIDC request found for client nonce")
}
// Generate a context with a deadline. This is passed to the OIDC provider
// and used when making remote HTTP requests.
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(aclOIDCCallbackRequestExpiryTime))
defer cancel()
// Exchange the state and code for an OIDC provider token.
oidcToken, err := oidcProvider.Exchange(ctx, oidcReq, args.State, args.Code)
if err != nil {
return fmt.Errorf("failed to exchange token with provider: %v", err)
}
if !oidcToken.Valid() {
return errors.New("exchanged token is not valid; potentially expired or empty")
}
var idTokenClaims map[string]any
if err := oidcToken.IDToken().Claims(&idTokenClaims); err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Restart the login flow: call OIDCAuthURL again after the leader has stabilized to mint a fresh nonce, then complete auth with that new nonce.
- Ensure OIDCAuthURL and OIDCCompleteAuth target the same Nomad cluster/address so the nonce lands in the same cache.
- Do not reuse a callback: complete the flow exactly once per nonce and generate a new nonce on retry.
- Check for frequent leader elections (server instability) if this recurs for multiple users.
Example fix
// before: reuse stale nonce after leader change
resp, err := acl.OIDCCompleteAuth(ctx, &api.ACLAuthCompleteArgs{ClientNonce: oldNonce, State: state, Code: code})
// after: restart flow to get a fresh nonce
authURL, nonce, err := acl.GetOIDCAuthURL(ctx, req)
// redirect user to authURL, then complete with the same `nonce` Defensive patterns
Strategy: retry
Validate before calling
// caller cannot inspect the server cache; validate inputs and freshness instead
if nonce == "" || time.Since(nonceIssuedAt) > 10*time.Minute {
// nonce stale or missing: re-run OIDCAuthURL before completing
} Try / catch
err := acl.OIDCCompleteAuth(ctx, args)
if err != nil && strings.Contains(err.Error(), "no OIDC request found for client nonce") {
// restart login: fetch a fresh auth URL + nonce and retry once
} Prevention
- Complete the OIDC callback immediately after obtaining the auth URL.
- Never reuse a nonce or callback URL; generate a new one per login attempt.
- Pin the login flow to one cluster and avoid it during known maintenance/leader elections.
When it happens
Trigger: Calling ACL.OIDCCompleteAuth with a ClientNonce that was never issued by OIDCAuthURL, a nonce already consumed by a prior OIDCCompleteAuth call, or a nonce whose cache entry was lost when the Nomad server leader changed between OIDCAuthURL and OIDCCompleteAuth.
Common situations: Leader election during an interactive OIDC login; user double-submitting the callback (nonce deleted on first use); starting login against one cluster and completing against another; replaying an old callback URL after cache entry TTL expiry.
Related errors
- missing client nonce
- nonce reuse detected
- exchanged token is not valid; potentially expired or empty
- missing OIDCDiscoveryURL
- missing OIDCClientID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/18f5a582a2b3b2a8.
Report an issue: GitHub.