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...
- 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
Create realm, user, and client following steps here, changing the client "Root URL" to
http://localhost:9000/.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...?)
In terminal, start
nc -l 9000In 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.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
- 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_urifield 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