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

  1. Restart the login flow: call OIDCAuthURL again after the leader has stabilized to mint a fresh nonce, then complete auth with that new nonce.
  2. Ensure OIDCAuthURL and OIDCCompleteAuth target the same Nomad cluster/address so the nonce lands in the same cache.
  3. Do not reuse a callback: complete the flow exactly once per nonce and generate a new nonce on retry.
  4. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/18f5a582a2b3b2a8. Report an issue: GitHub.