PKCE Authorization Code Returns “invalid_grant: Code not valid” When Exchanging Token via Public Client

Hello Keycloak Support Team,

I’m facing an issue with PKCE + Google Identity Provider (OIDC) login flow in Keycloak.
The authorization step succeeds, and I receive the code parameter from the redirect URI, but when I attempt to exchange this code for tokens using the /token endpoint, Keycloak responds with:

{
  "error": "invalid_grant",
  "error_description": "Code not valid"
}

Environment Details

  • Keycloak Version: [specify your version, e.g., 24.0.5]

  • Realm: MyScanApp

  • Client ID: myscan-mobile-v2

  • Client Type: Public

  • PKCE Enforced: true

  • Identity Provider: Google

  • Redirect URIs:

    com.myscan.app:/callback*
    https://oauth.pstmn.io/v1/callback
    
    
  • Flow: Standard Authorization Code + PKCE (S256)

What I’ve Verified

  • PKCE code_verifier and code_challenge are correct (verified SHA256 hash manually).

  • Redirect URI matches exactly in Keycloak and in token exchange request.

  • Code is exchanged within 10–20 seconds of login (so it’s not expired).

  • The client is configured as Public with PKCE Required, Standard Flow Enabled, and Direct Access Grants Enabled.

Example Token Request

POST https://keycloak-dev.bloxbytes.com/realms/MyScanApp/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
client_id=myscan-mobile-v2
redirect_uri=https://oauth.pstmn.io/v1/callback
code=<authorization_code>
code_verifier=<verifier_used_to_generate_challenge>

Expected Result

Keycloak should return a valid token response:

{
  "access_token": "...",
  "refresh_token": "...",
  "id_token": "...",
  "expires_in": 300,
  "token_type": "Bearer"
}

Actual Result

Keycloak returns:

{"error":"invalid_grant","error_description":"Code not valid"}

Could this be related to timing, session binding between the Google broker and the Keycloak authorization code, or a restriction with Postman’s redirect URI (https://oauth.pstmn.io/v1/callback)?
Any guidance on how to debug why Keycloak invalidates the authorization code immediately would be appreciated.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.