hashicorp/nomad · error

failed to retrieve the user info claims: %v

Error message

failed to retrieve the user info claims: %v

What it means

Thrown when oidcProvider.UserInfo(ctx, userTokenSource, sub, &userClaims) fails while fetching the provider's userinfo endpoint using the exchanged token. The wrapped error carries the IdP's response (401/403, network, or decode failure).

Source

Thrown at nomad/acl_endpoint.go:2815

	// 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
	}

	// No need to do all this marshaling if VerboseLogging is disabled
	if authMethod.Config.VerboseLogging {
		idTokenClaimBytes, err := json.MarshalIndent(idTokenClaims, "", " ")
		if err != nil {
			vlog.Debug("failed to marshal ID token claims")
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the wrapped cause: 401/403 usually means missing scopes or audience — update BoundAudiences/RequestedScopes in the auth method config.
  2. If the ID token already carries all needed claims, set OIDCDisableUserInfo = true in the auth method config to skip this call entirely.
  3. Verify the IdP's userinfo endpoint is reachable from Nomad servers (network, proxy, DNS).
  4. Confirm the 'sub' claim is present in the ID token and is a string (JSON number sub values break UserInfo lookups).

Example fix

// before (nomad auth-method config)
{ "OIDCClientID": "nomad", "BoundAudiences": ["nomad"] }
// after: skip userinfo if ID token has all claims
{ "OIDCClientID": "nomad", "BoundAudiences": ["nomad"], "OIDCDisableUserInfo": true }
Defensive patterns

Strategy: validation

Validate before calling

// ensure requested scopes cover userinfo requirements and sub exists
required := map[string]bool{"openid": true, "profile": true}
for _, s := range method.Config.OIDCScopes { delete(required, s) }
if len(required) > 0 { return fmt.Errorf("missing scopes: %v", required) }

Type guard

func subIsString(idTokenClaims map[string]any) bool {
  v, ok := idTokenClaims["sub"]
  return ok && isString(v)
}
func isString(v any) bool { _, ok := v.(string); return ok }

Try / catch

if err := oidcProvider.UserInfo(ctx, src, sub, &userClaims); err != nil {
    return fmt.Errorf("failed to retrieve the user info claims: %v", err)
}
// on 401/403 → add scopes/audiences; on network error → check egress from servers

Prevention

When it happens

Trigger: OIDCDisableUserInfo is false (default), the token has a StaticTokenSource, and UserInfo() errors: the access token is rejected by the /userinfo endpoint, the sub claim is missing/typed unexpectedly, or the endpoint is unreachable.

Common situations: IdP userinfo endpoint requires scopes not requested (e.g. missing 'profile'/'email' scope), token audience does not include userinfo, corporate proxy blocks the call from Nomad servers, IdP sub claim type mismatch (numeric vs string causing the idTokenClaims["sub"].(string) assertion context).

Related errors


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