quarkusio/quarkus · error · SpiffeConnectionException
JWT-SVID from SPIRE agent is already expired
Error message
JWT-SVID from SPIRE agent is already expired
What it means
The Quarkus SPIFFE client fetches JWT-SVIDs from a SPIRE Workload API agent. After parsing the token payload, it checks the 'exp' claim and rejects any token whose expiry is already in the past. This prevents callers from using a token that cannot possibly be valid for authentication.
Source
Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeClientImpl.java:273
}
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);
}
private static WorkloadCertificateDocument toWorkloadCertificate(X509SVIDResponse response)
throws SpiffeConnectionException {
List<X509SVID> svids = response.getSvidsList();
if (svids.isEmpty()) {
throw new SpiffeConnectionException("X.509-SVID response from SPIRE agent contains no SVIDs");
}
X509SVID svid = svids.get(0);
String protoSpiffeId = svid.getSpiffeId();
SpiffeValidator.validateSpiffeId(protoSpiffeId);View on GitHub (pinned to e1c734241f)
Solutions
- Synchronize clocks between the application and the SPIRE agent/server (NTP, kubelet clock settings).
- Increase the JWT-SVID TTL in the SPIRE server entry (ttl_seconds) or re-request tokens just before use instead of caching them.
- Retry the fetch; a fresh token should have a future exp if clocks agree.
- Check the SPIRE agent logs/health for stale or cached SVIDs and restart the agent if it serves expired tokens.
Example fix
// before: token fetched once at startup and reused
WorkloadJsonWebToken jwt = client.fetchWorkloadJsonWebTokens(...);
// after: re-fetch when close to expiry
WorkloadJsonWebToken jwt = expiry.isBefore(Instant.now().plusSeconds(60))
? client.fetchWorkloadJsonWebTokens(...)
: cached; Defensive patterns
Strategy: retry
Validate before calling
byte[] token = fetchTokenRaw();
long exp = parseClaim(token, "exp");
if (Instant.ofEpochSecond(exp).isBefore(Instant.now().plusSeconds(30))) {
// refresh before use
}
Try / catch
try {
jwt = client.fetchWorkloadJsonWebTokens(aud);
} catch (SpiffeConnectionException e) {
if (e.getMessage().contains("already expired")) {
jwt = retryWithBackoff(() -> client.fetchWorkloadJsonWebTokens(aud));
} else throw e;
} Prevention
- Fetch SVIDs just-in-time rather than caching at startup
- Keep NTP/clock sync enabled in all containers
- Refresh when within a safety margin (e.g. 60s) of expiry
- Set adequate JWT-SVID TTL in SPIRE registration entries
When it happens
Trigger: Calling fetchWorkloadJsonWebTokens (via WorkloadApiClient) when the SPIRE agent returns a JWT-SVID whose parsed 'exp' claim epoch-second value is before Instant.now().
Common situations: SPIRE agent clock skew with the application container; a SPIRE server issuing short-lived SVIDs (e.g. 5 min TTL) that expired between signing and delivery; NTP drift in Kubernetes pods; agent returning cached/stale tokens.
Related errors
- JWT-SVID from SPIRE agent has no token
- 'credentials.jwt.source' is set to 'spiffe-jwt', but no audi
- JWT-SVID from SPIRE agent is not a valid JWS Compact Seriali
- JWT-SVID proto SPIFFE ID does not match the 'sub' claim; pro
- JWT-SVID from SPIRE agent is missing the required 'aud' clai
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/eb8e6bcd2d238b68.
Report an issue: GitHub.