DEV Community

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

Posted on

24

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

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

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.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up