alibaba/nacos · error · AccessException
Token exchange failed:
Error message
Token exchange failed:
What it means
Thrown when the IdP's token endpoint returned a non-success (error) response to the authorization-code exchange. The IdP's own error description is appended to the message. This is the IdP rejecting the code-for-token exchange, not a Nacos-side validation.
Source
Thrown at plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/authenticate/AuthorizationCodeHandler.java:242
// Client authentication
ClientAuthentication clientAuth = new ClientSecretBasic(
new ClientID(config.getClientId()),
new Secret(config.getClientSecret()));
// Send token request
TokenRequest tokenRequest = new TokenRequest(
URI.create(tokenEndpoint),
clientAuth,
grant);
TokenResponse tokenResponse =
OIDCTokenResponseParser.parse(tokenRequest.toHTTPRequest().send());
if (!tokenResponse.indicatesSuccess()) {
String error = tokenResponse.toErrorResponse().getErrorObject().getDescription();
LOGGER.error("Token exchange failed: {}", error);
throw new AccessException("Token exchange failed: " + error);
}
OIDCTokenResponse oidcResponse = (OIDCTokenResponse) tokenResponse.toSuccessResponse();
return oidcResponse.getOIDCTokens();
}
/**
* Generate a secure random token for state/nonce.
*
* @return base64-encoded random token
*/
private String generateSecureToken() {
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
/**View on GitHub (pinned to 9b989acdf1)
Solutions
- Read the appended IdP error description (e.g. 'invalid_grant', 'invalid_client') — it names the exact cause.
- For 'invalid_grant': ensure the callback redirect_uri exactly matches buildAuthorizationUrl's redirectUri argument and the code is fresh (single-use).
- For 'invalid_client': verify client-id and client-secret in the OIDC config match the IdP registration.
- Resync server clocks if code-expiry errors appear with valid timing.
- Avoid retrying the same authorization code — generate a new login.
Example fix
// before: redirect URI mismatch between auth request and callback
String authUrl = handler.buildAuthorizationUrl("https://nacos/callback");
// ... user returns to a different path ...
handler.exchangeCodeForUser(code, state, "https://nacos/oidc/callback");
// after: use the identical redirect URI for both steps
String redirect = "https://nacos.example.com/oidc/callback";
String authUrl = handler.buildAuthorizationUrl(redirect);
handler.exchangeCodeForUser(code, state, redirect); Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the redirect URI used for exchange matches the one used to build the auth URL
if (!redirectUri.equals(originalRedirectUri)) {
throw new IllegalArgumentException("redirect_uri mismatch will be rejected by IdP");
} Try / catch
try {
handler.exchangeCodeForUser(code, state, redirectUri);
} catch (AccessException e) {
String msg = e.getMessage();
if (msg.startsWith("Token exchange failed: ")) {
// Do NOT retry the same authorization code — it is single-use
log.warn("IdP rejected code exchange: {}", msg);
redirectUserToLogin(); // start a fresh authorization-code flow
} else {
throw e;
}
} Prevention
- Pin the exact redirect URI in a constant and reuse it for both buildAuthorizationUrl and exchangeCodeForUser.
- Never retry an authorization-code exchange after a failure — request a fresh code.
- Keep client-id/client-secret in sync with the IdP registration.
When it happens
Trigger: Calling exchangeCodeForUser after the IdP callback when the authorization code is expired/already-used, the redirect_uri does not exactly match the one sent in the authorization request, the client_id/client_secret are wrong, or the code was issued for a different client.
Common situations: Clock skew causing code expiry; redirect URI mismatch between the authorization request and the callback handler; rotated client secret not updated in Nacos config; replaying a code after a retry; IdP behind a proxy rewriting redirect URIs.
Related errors
- Token endpoint not configured
- Failed to sign payload
- Client secret is required for state signing
- Failed to discover OIDC configuration, status:
- Failed to fetch JWKS, status:
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/e4711f8450c23de0.
Report an issue: GitHub.