Home > Software engineering >  Keycloak error: code already used for userSession
Keycloak error: code already used for userSession

Time:05-20

I am trying to get a handle on the OIDC (standard) authentication flow using Keycloak. Using the Keycloak docker image quay.io/keycloak/keycloak:latest (18.0.0) started up with no extra configuration (no database or anything). What I want is to go through exactly the steps in this post; I have gotten as far as navigating to my local Keycloak /auth endpoint in a browser, logging in, and getting a code sent to the redirect url I specified in my client setup (http://localhost:9000/). However, at the "Exchanging Authorization Code for Access Token" step, I keep getting a response from Keycloak that reads {"error":"invalid_grant","error_description":"Code not valid"}. Keycloak server logs output:

2022-05-18 01:22:35,906 WARN  [org.keycloak.protocol.oidc.utils.OAuth2CodeParser] (executor-thread-48) Code '193bfcc4-6e24-45f9-bc36-222ee3f0839b' already used for userSession '2b17e705-3821-42cb-819d-204245e38527' and client '282cfa97-627d-48ac-9656-8e0a2aaa198a'.
2022-05-18 01:22:35,906 WARN  [org.keycloak.events] (executor-thread-48) type=CODE_TO_TOKEN_ERROR, realmId=myrealm, clientId=myclient, userId=null, ipAddress=172.17.0.1, error=invalid_code, grant_type=authorization_code, code_id=2b17e705-3821-42cb-819d-204245e38527, client_auth_method=client-secret

Googling landed me on this post, which looks to be exactly the same problem I am encountering. However, trying different variations on this poster's solution have been to no avail.

NB: I am able to POST a payload to Keycloak's /token endpoint with a grant_type=password type, but this is not what I want. I need to be able to replicate the grant_type=authorization_code flow. Also, for reasons, I don't want to use an implicit flow -- I need to walk through the standard flow.

Is there anyone who can see what's going on and point me towards a solution? Many thanks in advance.

Edit: In response to Jan Garaj's comment, I am adding as much detail about the steps I've taken as I can...

  1. start Keycloak from a Docker image:

$ docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev

  1. Create realm, user, and client following steps here, changing the client "Root URL" to http://localhost:9000/.

  2. Change "Access Type" of client to confidential. All other settings were left as default. (I don't know what exactly is relevant, but the following settings seem so ...???)

  • client protocol: openid-connect
  • access type: confidential
  • standard flow enabled: true
  • implicit flow enabled: false
  • direct access grants enabled: true
  • authentication flow overrides: unmodified

(anything else...?)

  1. In terminal, start nc -l 9000

  2. In browser, navigate to http://localhost:8080/realms/myrealm/protocol/openid-connect/auth?client_id=myclient&response_type=code&state=fj8o3n7bdy1op5; log in with username and password.

  3. In terminal, see (attempted) redirect from Keycloak with an auth code.

GET /?state=fj8o3n7bdy1op5&session_state=5216ae35-89f6-4a42-a39a-b5545ff05c37&code=2ed44e9c-dc71-4ac1-9953-0e6e86f2a82d.5216ae35-89f6-4a42-a39a-b5545ff05c37.650fb336-8b0f-4e13-b2d8-725e188eea39

  1. In another terminal:
curl -v --location -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'client_id=myclient' \
-d 'client_secret=b0B430pRlfAs1rFurAqUKEmxkPTBptnh' \
-d 'code=2ed44e9c-dc71-4ac1-9953-0e6e86f2a82d.5216ae35-89f6-4a42-a39a-b5545ff05c37.650fb336-8b0f-4e13-b2d8-725e188eea39' \
-d 'redirect_uri=http://localhost:9000/' \
http://localhost:8080/realms/myrealm/protocol/openid-connect/token

where client_secret is taken from the Credentials view of my client. This results in the error response and log output pasted above.

Variations I've tried:

  • manually url-encoding the redirect uri
  • removing the redirect_uri field from the payload to /token
  • all of the above using Keycloak v15.0.2 (same version as in link above)
  • using httpbin.org instead of localhost:9000

CodePudding user response:

https://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation

Ensure that the redirect_uri parameter value is identical to the redirect_uri parameter value that was included in the initial Authorization Request. If the redirect_uri parameter value is not present when there is only one registered redirect_uri value, the Authorization Server MAY return an error (since the Client should have included the parameter) or MAY proceed without an error (since OAuth 2.0 permits the parameter to be omitted in this case).

You auth request doesn't specify redirect URI, but your token request does, so in this case Authorization Server (Keycloak in this prarticular case) returned an error.

Solution: specify redirect_uri parameter with correct value in the auth request.

CodePudding user response:

Well, it seems that the source of my problem was simply time. When going through the steps posted in the original question, I was doing so by typing out curl commands, copy-pasting codes, etc... I since built a small web server that executes the same steps described in the question and the process works just fine! So, I guess they weren't kidding when they said that the duration of validity of a temporary code is "very short-lived" (Section "Authorization Code Flow" #2)!!! Either that, or I'm an even slower typist than I thought! On this note, I'm wondering aloud if there is a way to adjust this duration in Keycloak (?).

Thanks so much to @JanGaraj for taking time to suggest fixes.

  • Related