6

I'm currently trying to retrieve a user token from the keycloak token endpoint using a POST request (instead of using one of the designated adapters). I have set up a keycloak realm and added my own machine as a client. In the documentation the Token Endpoint is described as:

/realms/{realm-name}/protocol/openid-connect/token

As far as I have read in the openid specification, I will need to set the body parameter grant_type=authorization_code as well as the parameters code and redirect_uri. I will also need to set the Authorization header, for which I will need a Basic Token.

So far I will get the response:

"error": "unauthorized_client",
"error_description": "INVALID_CREDENTIALS: Invalid client credentials"

Where do I get the Basic Authorization Token from? I expected that I need to provide a username and a password, since the JWT token is what I'm trying to recieve as response. Do I need to set the redirect_url if I just want to request a token?

T A
  • 1,677
  • 4
  • 21
  • 29
  • Did you achieve to get the given answer work? – Aritz Feb 26 '19 at 08:27
  • I'm currently using a workaround using the client id & secret (which is working fine for now) but I have yet to adapt your solution with the complete auth flow. I will update as soon as I have checked and implemented your solution and will of course also accept your answer (which I already upvoted as it already helped me a lot) as soon as I get to test it and get it to work. – T A Feb 26 '19 at 10:17
  • Okay!! Glad to know it helped ;-) – Aritz Feb 26 '19 at 10:26

1 Answers1

3

Keycloak offers more than one way to retrieve a user access token, following the OpenId Connect spec. Here you have the steps to do it for Authorization code flow (the one recommended for web applications) according to the openid connect spec: https://rograce.github.io/openid-connect-documentation/explore_auth_code_flow

Basically, if you're not using any adapter, when detecting a request to some protected resource you should:

Perform a redirection to the keycloak login page (keep in mind keycloak uses the REALM entity, so you'll need to specify it too):

HTTP/1.1 302 Found
  Location: https://mykeycloakinstance.org/auth/realms/demo/protocol/openid-connect/auth?
    response_type=code
    &scope=openid
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

You'll need to keep the state value in the client, as it needs to survive the redirection process:

It is recommended that client’s use this parameter to maintain state between the request and the callback. Typically, Cross-Site Request Forgery (CSRF, XSRF) mitigation is done by cryptographically binding the value of this parameter with a browser cookie.

You don't interact with username/passwords. The keycloak authentication page does. Once the login is successful, it will redirect to your page with a valid code:

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
  code=SplxlOBeZQQYbYS6WxSbIA
  &state=af0ifjsldkj

Here you'll need to either check that the state is the one you originally sent (you may need to track it through web session, using cookies) and also to obtain the token using that code. You do a POST to the authorization endpoint with this code:

POST /auth/realms/demo/protocol/openid-connect/auth HTTP/1.1
Host: https://mykeycloakinstance.org
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

This is the flow in summary, I haven't tested the code myself, so use it as an example and don't hesitate to fix it if you consider ;-)

See also:

Aritz
  • 30,971
  • 16
  • 136
  • 217
  • 2
    Accoring to section "3.1.3.1." of OIDC spec, you must only specify Authorization header if you client is confidential. If it's public, then it's not required. Keycloak however fails to process public clients, as this simply doesn't work (and probably the reason for the OP's issue). – Yog Sothoth Sep 10 '19 at 14:27