DEV Community

Cover image for Keycloak 19.0.1 and Setting the id_token_hint
Austin Cunningham
Austin Cunningham

Posted on

Keycloak 19.0.1 and Setting the id_token_hint

Created a blog some time ago setting up keycloak express and OIDC client and it happily worked fine with keycloak-17.0.0 and still does. On keycloak-19.0.2 same code completely falls over. (Note to self always set prerequisites on dependencies in blogs).

First issue I needed to enable Standard flow for the client in keycloak as I was seeing the following error in the logs

2022-09-16 11:56:37,512 WARN  [org.keycloak.events] (executor-thread-0) type=LOGIN_ERROR, realmId=78ae1441-0616-4745-b021-5ca93fc9f779, clientId=null, userId=null, ipAddress=127.0.0.1, error=invalid_code
2022-09-16 11:58:56,673 ERROR [org.keycloak.services] (executor-thread-3) KC-SERVICES0095: Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client.
Enter fullscreen mode Exit fullscreen mode

It's in the Clients\Capability config section
screenshot of keycloak ui clients capability

Secondly I was using localhost for my uri's in keycloak and in my code base and keycloak-19 did not play well with it. Changed everything to 127.0.0.1 and most routes started working again. With the exception of logout. I was hitting the following issue.
keycloak logout id_token_hint error screenshot
The keycloak logs had a similar error with more details.

2022-09-16 13:00:28,208 WARN  [org.keycloak.events] (executor-thread-57) type=LOGOUT_ERROR, realmId=1bfc6eb7-ffa8-497f-96cc-69840b6c3f39, clientId=null, userId=null, ipAddress=127.0.0.1, error=invalid_request
2022-09-16 13:11:48,730 WARN  [org.keycloak.protocol.oidc.endpoints.LogoutEndpoint] (executor-thread-75) Either the parameter 'client_id' or the parameter 'id_token_hint' is required when 'post_logout_redirect_uri' is used.
Enter fullscreen mode Exit fullscreen mode

So because I was using post_logout_redirect_uri I need to use either client_id or id_token_hint parameter. So I had three options

  • stop using post_logout_rediret_uri
  • add a client_id parameter to post_logout_redirect_uri
  • add a id_token_hint parameter to post_logout_redirect_uri

Stop using post_logout_redirect_uri

Remove it from the keycloakeIssuer.Client

const keycloakIssuer = await Issuer.discover("http://127.0.0.1:8080/realms/keycloak-express")
// I just comment out the line in the client 
const client = new keycloakIssuer.Client({
    client_id: 'keycloak-express',
    client_secret: 'long_secret-here',
    redirect_uris: ['http://127.0.0.1:3000/auth/callback'],
    //post_logout_redirect_uris: ['http://127.0.0.1:3000/logout/callback'],
    response_types: ['code'],
  });
Enter fullscreen mode Exit fullscreen mode

Looks like this it prompts for a logout and leaves you at a keycloak logged out screen.
screen grab of logout without post_logout_redirect_uri

Add client_id parameter

We have set the client_id in the keycloakeIssuer.Client so it just a matter of setting it in the logout as a parameter

// start logout request
app.get('/logout', (req, res) => {
    res.redirect(client.endSessionUrl({
        client_id: "keycloak-express"
    }
    ));
});
Enter fullscreen mode Exit fullscreen mode

Looks like this as you can see it ask for another confirmation before redirecting to the app.
screen grab of logout with client_id parameter set

Add id_token_hint parameter

What is id_token_hint and how do I populate it?
Me I am terrible at reading/comprehending documentation and much prefer a good example. In this case I didn't find any examples. I found the following documentation referencing id_token_hint

There is a tokenSet object that is created as part of the passportjs strategy login flow. I inspected this object and found that it has a id_token and I made this id_token_hint = id_token and my issue was solved.

So I was using passwordjs and node-openid-client

var TokenSet
passport.use('oidc', new Strategy({client}, (tokenSet, userinfo, done)=>{
        TokenSet = tokenSet;
        return done(null, tokenSet.claims());
    })
)
//And on logout we can set the id_token_hint parameter
app.get('/logout', (req, res) => {
    res.redirect(client.endSessionUrl({
        id_token_hint: TokenSet.id_token
    }
    ));
});
Enter fullscreen mode Exit fullscreen mode

Looks like this and is a much better user experience
screen grab of logout with id_token_hint parameter set
Code lives here

Top comments (2)

Collapse
 
lirik90 profile image
Kirill Zimnikov

Hi. It's amazing example. Thanks for it.
But it's not working for two+ users at time. It will secure to send id_token to user for store it in web browser? Or we should store it in database?

Collapse
 
austincunningham profile image
Austin Cunningham • Edited

To be honest I have never tried it with 2 users. There is a warning about using MemoryStore

Warning The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.

from npmjs.com/package/express-session that could be the source of the issue.