quarkusio/quarkus · error · SpiffeConnectionException

JWT-SVID 'aud' claim contains unexpected extra audiences; re

Error message

JWT-SVID 'aud' claim contains unexpected extra audiences; requested: ${requestedAudiences}, received: ${audience}

What it means

If the token's aud set strictly contains all requested audiences but also has extra entries, the client treats the token as over-scoped and rejects it (audience.size() != requestedAudiences.size()). This enforces exact audience matching between request and issued JWT-SVID.

Source

Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeClientImpl.java:262

                    audience.add(audienceAsString);
                } else {
                    throw new SpiffeConnectionException(
                            "JWT-SVID 'aud' array element at index " + i + " is not a string:" + audienceAsArray.getValue(i));
                }
            }
        } else if (aud instanceof String audienceAsString) {
            audience = Set.of(audienceAsString);
        } else {
            throw new SpiffeConnectionException(
                    "JWT-SVID 'aud' claim is not a string or array of strings");
        }
        if (!audience.containsAll(requestedAudiences)) {
            throw new SpiffeConnectionException(
                    "JWT-SVID 'aud' claim does not contain the requested audiences; requested: "
                            + requestedAudiences + ", received: " + audience);
        }
        if (audience.size() != requestedAudiences.size()) {
            throw new SpiffeConnectionException(
                    "JWT-SVID 'aud' claim contains unexpected extra audiences; requested: "
                            + requestedAudiences + ", received: " + audience);
        }

        Long exp = payload.getLong("exp");
        if (exp == null) {
            throw new SpiffeConnectionException("JWT-SVID from SPIRE agent is missing the required 'exp' claim");
        }
        Instant expiry = Instant.ofEpochSecond(exp);
        if (expiry.isBefore(Instant.now())) {
            throw new SpiffeConnectionException("JWT-SVID from SPIRE agent is already expired");
        }

        record WorkloadJsonWebTokenImpl(String token, String subject, Set<String> audience,
                Instant expiry) implements WorkloadJsonWebToken {
        }
        return new WorkloadJsonWebTokenImpl(token, sub, Set.copyOf(audience), expiry);
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Narrow the SPIRE registration entry so issued tokens contain exactly the required audiences
  2. Request the full audience set that the entry grants, or update config to match the token contents
  3. Create separate SPIRE entries per service pairing to keep scopes minimal

Example fix

// before (entry grants a+b, request asks only a)
spiffeClient.getWorkloadJsonWebToken(Set.of("a"));
// after
spiffeClient.getWorkloadJsonWebToken(Set.of("a", "b")); // or narrow the SPIRE entry
Defensive patterns

Strategy: validation

Validate before calling

// request exactly the audience set the SPIRE entry grants
Set<String> entryGranted = Set.of("https://api.example.com");
// call with the full set, or narrow the entry with spire-server entry update

Try / catch

try {
    return spiffeClient.getWorkloadJsonWebToken(requested).await().indefinitely();
} catch (SpiffeConnectionException e) {
    if (e.getMessage().contains("unexpected extra audiences")) {
        // narrow the SPIRE entry or request all granted audiences
    }
    throw e;
}

Prevention

When it happens

Trigger: SPIRE entry issues tokens with multiple audiences while the client requested only a subset, e.g. requesting {"a"} but receiving aud ["a","b"].

Common situations: Broad SPIRE registration entries granting many audiences; shared workload entries reused by several services; tightening audiences in app config without narrowing the SPIRE entry (or vice versa).

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/beae742553a98180. Report an issue: GitHub.