dgraph-io/dgraph · error

jwt token cannot be validated because verification algorithm

Error message

jwt token cannot be validated because verification algorithm is not set

What it means

When no JWKUrls are configured, the library falls back to verifying the JWT with a locally configured algorithm (a.Algo) and verification key. If a.Algo is empty, there is no way to know which signing algorithm to enforce, so validation is refused before parsing. It indicates the AuthMeta was configured for static-key verification but the algorithm field was never set.

Source

Thrown at graphql/authorization/auth.go:385

			},
		)

		if err == nil {
			return token, nil
		}
	}
	return nil, err
}

func (a *AuthMeta) validateJWTCustomClaims(jwtStr string) (*CustomClaims, error) {
	var token *jwt.Token
	var err error
	// Verification through JWKUrl
	if len(a.JWKUrls) != 0 {
		token, err = a.validateThroughJWKUrl(jwtStr)
	} else {
		if a.Algo == "" {
			return nil, fmt.Errorf(
				"jwt token cannot be validated because verification algorithm is not set")
		}

		// The JWT library supports comparison of `aud` in JWT against a single string. Hence, we
		// disable the `aud` claim verification at the library end using `WithoutAudienceValidation` and
		// use our custom validation function `validateAudience`.
		token, err =
			jwt.ParseWithClaims(jwtStr, &CustomClaims{authMeta: a}, func(token *jwt.Token) (interface{}, error) {
				algo, _ := token.Header["alg"].(string)
				if algo != a.Algo {
					return nil, errors.Errorf("unexpected signing method: Expected %s Found %s",
						a.Algo, algo)
				}

				switch a.SigningMethod.(type) {
				case *jwt.SigningMethodHMAC:
					return []byte(a.VerificationKey), nil
				case *jwt.SigningMethodRSA:

View on GitHub (pinned to 759e242be6)

Solutions

  1. Set Algo in your AuthOptions (e.g. "RS256" or "HS256") to match the token issuer.
  2. Ensure the config/env value feeding Algo is present and non-empty at startup.
  3. Fail fast: validate configuration at boot and reject AuthMeta with empty Algo when JWKUrls is empty.
  4. If you meant JWK-based verification, populate JWKUrls and call FetchJWKs at startup instead.
  5. Log the effective AuthMeta (sans secrets) at startup to catch empty Algo early.

Example fix

// before
auth := &authorization.AuthOptions{ VerificationKey: key }
claims, err := auth.ExtractCustomClaims(ctx, tokenStr)
// after
auth := &authorization.AuthOptions{ Algo: "RS256", VerificationKey: key }
claims, err := auth.ExtractCustomClaims(ctx, tokenStr)
Defensive patterns

Strategy: validation

Validate before calling

func (a *AuthMeta) validateConfig() error {
    if len(a.JWKUrls) == 0 && a.Algo == "" {
        return errors.New("auth misconfigured: set JWKUrls or Algo+VerificationKey")
    }
    return nil
}

Try / catch

if err := authCfg.validateConfig(); err != nil {
    log.Fatalf("invalid auth configuration: %v", err) // fail at startup, not per-request
}

Prevention

When it happens

Trigger: validateJWTCustomClaims (via ExtractCustomClaims) is called with len(a.JWKUrls)==0 and a.Algo == "" — i.e. AuthOptions neither set JWKUrls nor Algo.

Common situations: AuthOptions built programmatically and Algo forgotten; config file key for algorithm missing/typo so it binds as empty string; code path switched from JWK-based auth to static keys without updating Algo; environment variable not set.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/dda2b7e0883a0c9a. Report an issue: GitHub.