hashicorp/nomad · error

auth method specifies BoundIssuers but the provided token do

Error message

auth method specifies BoundIssuers but the provided token does not contain issuer information

What it means

The auth method has BoundIssuer configured, but the validated JWT contains no iss claim at all. Issuer checking is done manually (to support arrays of acceptable issuers), so a token without iss cannot be matched and is rejected.

Source

Thrown at lib/auth/jwt/validator.go:75

		NotBeforeLeeway:   methodConf.NotBeforeLeeway,
		ExpirationLeeway:  methodConf.ExpirationLeeway,
		ClockSkewLeeway:   methodConf.ClockSkewLeeway,
	}

	validator, err := jwt.NewValidator(keySet)
	if err != nil {
		return nil, err
	}

	claims, err := validator.Validate(ctx, token, expected)
	if err != nil {
		return nil, fmt.Errorf("unable to verify signature of JWT token: %v", err)
	}

	// validate issuer manually, because we allow users to specify an array
	if len(methodConf.BoundIssuer) > 0 {
		if _, ok := claims["iss"]; !ok {
			return nil, fmt.Errorf(
				"auth method specifies BoundIssuers but the provided token does not contain issuer information",
			)
		}
		if iss, ok := claims["iss"].(string); !ok {
			return nil, fmt.Errorf("unable to read iss property of provided token")
		} else if !slices.Contains(methodConf.BoundIssuer, iss) {
			return nil, fmt.Errorf("invalid JWT issuer: %v", claims["iss"])
		}
	}

	return claims, nil
}

func usingStaticKeys(keys []string) (jwt.KeySet, error) {
	var parsedKeys []crypto.PublicKey
	for _, v := range keys {
		key, err := jwt.ParsePublicKeyPEM([]byte(v))
		parsedKeys = append(parsedKeys, key)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Use the ID token (which carries iss) rather than the access token
  2. Configure the IdP to include the iss claim in issued tokens
  3. If issuer enforcement isn't required, clear BoundIssuer on the auth method

Example fix

// before: access token without iss
resp, err := client.Login(idp.AccessToken)
// after: ID token
resp, err := client.Login(idp.IDToken)
Defensive patterns

Strategy: validation

Validate before calling

payload := decodeJWTPayload(rawToken) // base64 decode middle segment
if _, ok := payload["iss"]; !ok && authMethodUsesBoundIssuer {
    return errors.New("token has no iss claim but auth method requires BoundIssuer match")
}

Type guard

func hasStringIss(claims map[string]interface{}) bool {
    iss, ok := claims["iss"]
    if !ok { return false }
    _, isStr := iss.(string)
    return isStr
}

Try / catch

if err != nil && strings.Contains(err.Error(), "does not contain issuer information") {
    return fmt.Errorf("use the ID token (contains iss), not the access token: %w", err)
}

Prevention

When it happens

Trigger: Login where methodConf.BoundIssuer is non-empty but claims lacks the "iss" key — typically an opaque/access token or a token type that omits iss.

Common situations: Sending an access token instead of an ID token; IdP configured without issuer in token; using a token from a different provider that doesn't set iss.

Related errors


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