cloudflare/cloudflared · error
metadata JWT aud is empty
Error message
metadata JWT aud is empty
What it means
GetAppInfo validates the cloudflared access metadata JWT that must be attached to a request before it can resolve app information. After verifying the signature, hostname and type, it rejects the token if the AUD claim is empty, since the audience is required to identify the Access application.
Source
Thrown at token/token.go:456
if err != nil {
return nil, fmt.Errorf("metadata JWT auth_domain validation failed: %w", err)
}
// Verify the JWT signature against the JWKS (with disk cache + retry).
claims, err := verifyMetadataWithRetry(rawJWT, authDomain)
if err != nil {
return nil, fmt.Errorf("metadata JWT verification failed: %w", err)
}
// Verify the hostname in the JWT matches the URL we actually requested.
if !strings.EqualFold(claims.Hostname, reqURL.Hostname()) {
return nil, fmt.Errorf("metadata JWT hostname %q does not match request host %q", claims.Hostname, reqURL.Hostname())
}
if claims.Type != metadataMatchType {
return nil, fmt.Errorf("metadata JWT type %q is not match", claims.Type)
}
if claims.AUD == "" {
return nil, errors.New("metadata JWT aud is empty")
}
if err := validateMetadataIssuedAt(claims.IAT, time.Now()); err != nil {
return nil, err
}
appHostname := claims.AppHostname
if appHostname == "" {
// For retro-compatibility with CF access older releases, this will cause wildcard apps to store one local token
// per requested hostname, which is less optimized but also works.
appHostname = claims.Hostname
}
return &AppInfo{
AuthDomain: authDomain.Hostname(),
AppAUD: claims.AUD,
AppHostname: appHostname,
}, nil
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Ensure the request carries the Access metadata JWT header populated by a successful Access login before calling GetAppInfo.
- Configure the Access application's audience (AUD) tag in the Cloudflare dashboard so issued tokens include a non-empty aud claim.
- Re-authenticate to regenerate a token if an old one predates the app's audience configuration.
- Check intermediate proxies/load balancers are not stripping the metadata JWT header.
Example fix
// before: request sent without Access token headers req, _ := http.NewRequestWithContext(ctx, "GET", originURL, nil) // after: inject metadata JWT from Access login req.Header.Set(cfAccessJWTHeader, metadataJWT)
Defensive patterns
Strategy: try-catch
Validate before calling
claims, err := decodeUnverifiedClaims(metadataJWT) // base64-decode payload JSON
if err != nil || claims.AUD == "" {
return fmt.Errorf("metadata JWT missing or has empty aud; re-run Access login")
} Type guard
func hasAudience(claims *metadataClaims) bool {
return claims != nil && claims.AUD != ""
} Try / catch
appInfo, err := GetAppInfo(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "aud is empty") {
// trigger re-authentication / token refresh flow
return reauthenticateAndRetry(ctx, req)
}
return fmt.Errorf("resolving app info: %w", err)
} Prevention
- Always run the Access login flow and attach its metadata JWT header before calling GetAppInfo.
- Configure the app's audience tag in the Cloudflare dashboard so minted tokens carry a non-empty aud.
- Check proxies for header stripping of the Access metadata JWT.
- Refresh tokens after app/audience configuration changes.
When it happens
Trigger: Calling GetAppInfo with a request whose metadata JWT has an empty or missing aud claim; also hit by tests like TestGetAppInfo_RejectsNoMetadataHeader exercising the no/empty metadata path via createWebsocketStream, login, curl, generateToken, or sshGen.
Common situations: Requests to an Access-protected origin that bypass the Access login flow (no token injected), tokens minted without an audience configured for the app in the Cloudflare dashboard, or a header-stripping proxy removing the metadata JWT or its aud.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- aud array contains non-string elements
- aud field is not a string or an array of strings
- invalid token
- metadata JWT iat is missing or invalid
- failed to determine if token is FED: %w
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/c3ef848c3a975599.
Report an issue: GitHub.