Kazooie
Kazooie

Reputation: 565

Obtain ID token from Keycloak on Ruby on Rails with Omniauth to implement logout

I've been struggling to implement logout to my Ruby on Rails app. I'm running Keycloak v19.0.2 locally on port 8081. Therefore the logout url for realm test-realm is http://localhost:8081/realms/test-realm/protocol/openid-connect/logout.

According to the documentation here. I should redirect user to this url and provide query parameters with it. However I want to implement the logout without the prompt and redirect user back to the app with post_logout_redirect_uri. To do that I need to provide id_token_hint parameter, but what is this token and how to get it? My Keycloak authentication does only return access token and refresh token, not id token. I have tried to use both on this parameter and it does not work. And what I have searched online, it seems ID token is different from access token.

I have implemented the authentication to my Rails app with omniauth and omniauth-keycloak gems. For example I define keycloak_openid provider following way

provider(:keycloak_openid,
         Secrets.keycloak_client_id,
         Secrets.keycloak_client_secret,
         name: "keycloak",
         client_options: {
             base_url: "", site: "http://localhost:8081", realm: "test-realm"
         })

And I have defined a callback in my routes that will be called correctly for me where I can get access token and refresh token.

What I'm missing?

Upvotes: 1

Views: 1199

Answers (1)

Kazooie
Kazooie

Reputation: 565

Okay it seems I was missing scope parameter from the authentication query to the token api. So when requesting the token I need to provide scope=openid paremeter to the Keycloak. This makes the Keycloak return ID token alongside with access and refresh tokens.

The key bit of information I got from here. Then by reading the omniauth-keycloak source code. It depends on omniauth-oauth2 gem. After reading that source, I found out that you can provide scope parameter when initializing the provider. So the provided should be initialized like this

provider(:keycloak_openid,
         Secrets.keycloak_client_id,
         Secrets.keycloak_client_secret,
         name: "keycloak",
         scope: "openid",
         client_options: {
             base_url: "", site: "http://localhost:8081", realm: "test-realm"
         })

Now the the ID token is returned by the Keycloak and can be provided for the logout id_token_hint parameter. With this the user is able logout without the prompt.

Upvotes: 0

Related Questions