netbirdio/netbird · error
required token field audience is absent
Error message
required token field audience is absent
What it means
The token was a structurally valid JWT and its payload parsed as JSON, but the aud claim is absent (claims.Audience == nil). The check requires an audience because the whole point is confirming the token targets this deployment; an aud-less token cannot be matched against the configured Audience or the ClientID fallback.
Source
Thrown at client/internal/auth/util.go:54
parts := strings.Split(token, ".")
if len(parts) != 3 {
return fmt.Errorf("token is not a well-formed JWT")
}
claimsString, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return err
}
claims := Claims{}
err = json.Unmarshal(claimsString, &claims)
if err != nil {
return err
}
if claims.Audience == nil {
return fmt.Errorf("required token field audience is absent")
}
// Audience claim of JWT can be a string or an array of strings
switch aud := claims.Audience.(type) {
case string:
if aud == audience {
return nil
}
case []interface{}:
for _, audItem := range aud {
if audStr, ok := audItem.(string); ok && audStr == audience {
return nil
}
}
}
return fmt.Errorf("invalid JWT token audience field")
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Configure the IdP to include the audience: add an audience mapper/claim (Keycloak), set the API identifier as audience (Auth0), or expose an API/scope so the token carries the resource aud (Azure AD).
- Ensure the audience parameter NetBird sends in the authorization request matches an audience the IdP actually supports - the flow passes it via oauth2.SetAuthURLParam("audience", ...).
- Re-login after fixing the IdP so a freshly minted token is checked.
- If the provider truly cannot add aud, switch to a provider configuration that supports JWT audience validation.
Defensive patterns
Strategy: validation
Validate before calling
// assert a decoded token carries an aud claim before it reaches validation
func hasAudienceClaim(token string) bool {
parts := strings.Split(token, ".")
if len(parts) != 3 {
return false
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return false
}
var claims map[string]json.RawMessage
return json.Unmarshal(payload, &claims) == nil && claims["aud"] != nil
} Try / catch
if err := validateTokenAudience(token, audience); err != nil {
if strings.Contains(err.Error(), "audience is absent") {
// add an audience mapper / API identifier in the IdP; the flow must
// re-issue a token, so re-login after the fix
}
} Prevention
- Configure audience mappers (Keycloak) or API identifiers (Auth0/Azure AD) at app registration time.
- Pass the audience parameter in the authorization request - the flow already does; make sure the IdP honors it.
- Verify a sample token includes aud before pointing production clients at it.
When it happens
Trigger: The IdP mints tokens without an aud claim: the authorization request carried no audience/resource parameter, the API registration in the IdP has no identifier configured, or a custom claims policy strips aud.
Common situations: Keycloak client config with no audience mapper in the client scope; Auth0 API identifier not passed as the audience parameter; Azure AD app registration missing the API/exposed scope so tokens come out without the resource audience.
Related errors
- validate access token failed with error: %v
- authentication failed: invalid access token - %w
- token received is empty
- token is not a well-formed JWT
- Run `netbird profile list --show-id` to see IDs, then selec
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/8e8d55a2b69602a2.
Report an issue: GitHub.