hashicorp/nomad · error

failed to retrieve the ID token claims: %v

Error message

failed to retrieve the ID token claims: %v

What it means

Thrown when oidcToken.IDToken().Claims(&idTokenClaims) fails to JSON-decode the ID token payload into map[string]any. This means the token came back but its ID-token claims could not be parsed — typically a malformed or unexpectedly-encoded ID token from the provider.

Source

Thrown at nomad/acl_endpoint.go:2808

	}

	// 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 {
		return fmt.Errorf("failed to retrieve the ID token claims: %v", err)
	}

	var userClaims map[string]any
	if !authMethod.Config.OIDCDisableUserInfo {
		if userTokenSource := oidcToken.StaticTokenSource(); userTokenSource != nil {
			if err := oidcProvider.UserInfo(ctx, userTokenSource, idTokenClaims["sub"].(string), &userClaims); err != nil {
				return fmt.Errorf("failed to retrieve the user info claims: %v", err)
			}
		}
	}

	// Generate the data used by the go-bexpr selector that is an internal
	// representation of the claims that can be understood by Nomad.
	oidcInternalClaims, err := auth.SelectorData(authMethod, idTokenClaims, userClaims)
	if err != nil {
		return err
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the raw ID token (jwt.io) returned by the provider for a non-standard claims payload.
  2. Upgrade Nomad / the cap library — parsing bugs are fixed upstream.
  3. Check for a reverse proxy or security appliance mangling the token response body.
  4. Switch to a standards-compliant provider configuration or open an issue with the provider vendor.
Defensive patterns

Strategy: try-catch

Validate before calling

// decode the ID token client-side first to sanity-check claims
parts := strings.Split(rawIDToken, ".")
if len(parts) != 3 { return errors.New("not a JWT") }
payload, _ := base64.RawURLEncoding.DecodeString(parts[1])
var claims map[string]any
if err := json.Unmarshal(payload, &claims); err != nil { return err }
if _, ok := claims["sub"]; !ok { return errors.New("missing sub") }

Try / catch

if err := oidcToken.IDToken().Claims(&idTokenClaims); err != nil {
    return fmt.Errorf("failed to retrieve the ID token claims: %v", err)
}

Prevention

When it happens

Trigger: OIDCCompleteAuth calls IDToken().Claims() on the token returned by Exchange and the cap library returns a decode error (malformed JWT payload, non-object claims).

Common situations: Misbehaving or non-standard IdP returning an ID token whose claims are not a JSON object, corrupted token from a proxy, provider returning an opaque token where an ID token is expected.

Related errors


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