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

  1. Read the appended IdP error description (e.g. 'invalid_grant', 'invalid_client') — it names the exact cause.
  2. For 'invalid_grant': ensure the callback redirect_uri exactly matches buildAuthorizationUrl's redirectUri argument and the code is fresh (single-use).
  3. For 'invalid_client': verify client-id and client-secret in the OIDC config match the IdP registration.
  4. Resync server clocks if code-expiry errors appear with valid timing.
  5. 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

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


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/e4711f8450c23de0. Report an issue: GitHub.