Simply logout from Keycloak

This blog post is about the logout from Keycloak in a Vue.js application using the keycloak-js SDK/javascript-adapter.

As you maybe know we (Niklas, Harald and I) created an example project called Cloud Native Starter that contains example implementations related to Cloud Native applications with Microservices. I will use one of the example implementations in that blog post.

I structured the blog post in following sections.

  • The simplified solution
  • The basics
  • The example implementation in a Vue.js fronted application

The simplified solution

But, if you only want to know the simplified fact, what you need for the logout? You just need a logut url which contains the redirect url to a page you want to be shown, when a user does a logout from your application. In my example it’s the redirect url to the root URL of the frontend Vue.js web application.

Here you see the structure of the logout url. You need to know the KEYCLOAK_URL, the REALM_NAME and theENCODED_REDIRECT_URI.

http://{KEYCLOAK_URL}/auth/realms/{REALM_NAME}/protocol/openid-connect/logout?redirect_uri={ENCODED_REDIRECT_URI}

The basics

When you logout from Keycloak you should be aware of two topics, these are cookies and tokens.

Cookies

Cookies in the browser which are used by Keycloak, these cookies can be used for an automation of the login to Keycloak. As you see in the image below, cookies can be requiredoptional or disabled for the authentication flows of Keycloak.

In the image below you see the cookies which were created by my local Keycloak instance. You can notice these cookies, aren’t accessible by a script (No(HttpOnly)). So, when we manage the logout correctly Keycloak will put the cookies to the right state and we don’t need to take care about the cookies.

Tokens 

You manage the refresh of a token in your application itself. In our example we implemented the frequently update of the token inside an interval (setInterval).

In the image you see the settings you can use to configure the lifespan of a token in Keycloak.

The example implementation in the Vue.js webapplication

Let me start very simply, before you can logout you need to be logged on.

I will use the relevant parts from the main.js file of our Vue.js frontend application to show how it works. That topic is structured in following sections:

In the main.js file we use the Keycloak SDK/javascript-adapter for the implementation to access Keycloak. The source code for that SDK/javascript-adapter you can find here (/keycloak.d.ts).

The logout is a part of an interval used for the update of the tokens in main.js file, the reason for that is I want to reuse the existing instance of the Keycloak javascript-adapter.

Init

In the following code you see the initOptions, which are the parameters for the instantiation of a Keycloak javascript-adapter instance. In order to create an instance, three pieces of information are required. The Keycloak URL, the realm and the client id.

When the login was successful, we get the tokens from Keycloak, which we will save in an Vue store, with is called store in our code.

You can find in detailed description of the values for the Keycloak init in the SDK/javascript-adapter documentation. (example code in GitHub)

...
let initOptions = {
  url: store.state.endpoints.login , realm: 'quarkus', clientId: 'frontend', onLoad: 'login-required'
}

let keycloak = Keycloak(initOptions);

keycloak.init({ onLoad: initOptions.onLoad }).then((auth) => {
...
  if ((keycloak.token && keycloak.idToken) != '') {
    store.commit("login", payload);
    payload = {
      name: keycloak.tokenParsed.preferred_username
    };
    store.commit("setName", payload);
  }
  else {
    payloadRefreshedTokens = {
      idToken: "",
      accessToken: ""
    }
    store.commit("login", payloadRefreshedTokens);
    store.commit("logout");
  }
...

Token update

In the following interval implementation, you see that the status of the authentication will be frequently verified and when the authentication status in the fronted application is still valid, the token will be updated and saved in the Vue store. (example code in GitHub)

You can find in detailed description for the updateToken() in Keycloak SDK/javascript-adapter documentation.

setInterval(() => {
    keycloak.updateToken().then((refreshed) => {
      if (store.state.user.isAuthenticated != false ) {
        if (refreshed) {       
          let payloadRefreshedTokens = {
            idToken: keycloak.idToken,
            accessToken: keycloak.token
          }
          if ((keycloak.token && keycloak.idToken) != '') {
            store.commit("login", payloadRefreshedTokens);
          }
          else {
            payloadRefreshedTokens = {
              idToken: "",
              accessToken: ""
            }
            store.commit("login", payloadRefreshedTokens);
            store.commit("logout");
          }
        }
      } 
      ...

Logout

Finally, we come to the logout implementation, which is also a part of the interval implementation (so the logout takes bit) to take the advantage of the existing Keycloak javascript-adapter instance in the example.

The documentation of the logout() for the Keycloak SDK/javascript-adapter isn’t as detailed as for the init and token update.

I figured out that we need to create a logout URL as you can verify in the documentation for a logout. The given logout documentation of the javascript-adapter doesn’t contain the needed format for the parameter options. But finally, I found the options in the source code of the javascript-adapter in the keycloak.d.ts file.

The Keycloak logout URL must contain the valid redirect URL, in this example the URL is http://localhost:8080/, the same URL as for the redirect of the login to the Vue.js frontend application.

My finding resulted in the following simple definition:

logoutOptions = { redirectUri : "http://localhost:8080/" }

When you know that the logout is very simple as you see in the following source code. (example code in GitHub)

...
    var logoutOptions = { redirectUri : urls.cns };

    keycloak.logout(logoutOptions).then((success) => {
            console.log("--> log: logout success ", success );
    }).catch((error) => {
            console.log("--> log: logout error ", error );
    });
    store.commit("logout");
...

The gif below shows the working logout.

Summary

At the end the implementation of the logout is very simple, but it wasn’t so easy to find the parameter for the logout of the javascript-adapter. It’s awesome that you can dig into the source code, because Keycloak is open-source, when you miss a tiny little detail in the documentation ;-).



I hope this was useful for you and let’s see what’s next?

Greetings,

Thomas

#vue, #keycloak, #logout, #javascript, #cloudnativestarter

11 thoughts on “Simply logout from Keycloak

  1. Leonidas Theodoridis says:

    Hi,
    I am trying to logout from the Keycloak.
    When I log in I use another realm, othen than the one that I am using in the login options/arguments.
    But when I logout it seems, that Keycloak remains in the original/initial realm.
    Is there any way in the logout to specify the realm from which I want to make the logout?

    Like

    • thomassuedbroecker says:

      Hi Leonidas, as far as I understand from your question. I don‘t understand your sequence?

      1. Logon Realm 1 (how ?)
      2. Logon Realm 2 (using parameters?)
      3. Logout Ream 1 or 2 …

      Do you mean you are logged on at two realms concurrently?

      Regards Thomas

      Like

  2. LT says:

    Hi Thomas,

    the sequence is the following:

    in the initOptions I set the initial realm #1.
    Then when I am forwarded in the Keycloak console, instead of logging in the existing #1 realm, I select another realm and enter my credentials.
    Then I am logged in.
    When I try to logout from the application we have 2 cases:
    Case #1: I am logged in using my credentials from the realm #1. The logout is successful. If I try to access the app, it asks me again for username and pass.
    Case #2: I am logged in from the realm #2. (In the log in screen of Keycloak, I select the second realm and I log in. When I log out of the app and try to log in again, I am logged in without being asked for my credentials. I have seen that the session is not destroyed…

    It is a case similar to this one:
    https://stackoverflow.com/questions/54413022/is-keycloak-destroy-user-session-if-browser-closes-but-not-log-out

    Like

  3. LT says:

    ..thanks Thomas.
    I use keycloak.logout(logoutOptions) and in the logoutOptions is the redirectUri.
    1. A post request cannot be avoided, right? (the keycloak.logout() function works for one
    realm.)
    2.Concerning the REALM_NAME, how can I extract the REALM_NAME for the second realm?
    In the initialLogin I give the name of the first realm.

    Like

    • thomassuedbroecker says:

      Hi LT,

      you should know the realm_name, right?

      Because, how did you logon at the second realm, when you don‘t know the realm name?

      Ensure your are doing exactly the same steps as you did for the first realm and ensure you know the auth configuration for both realms.

      You need to ensure in your source code that initOptions/logoutOptions where cleared before you change the realm.

      I would say, if all this is correct it should work.

      I hope this helps.

      Greetings,

      Thomas

      Like

  4. LT says:

    Exactly that is the point:
    I login from the GUI interface of Keycloak.
    How can I get the realm when I am in the javascript file of my app? Is there an API to call based on the user or the access token of the realm?

    Like

    • thomassuedbroecker says:

      Hi LT,

      when you take a look in the section „init“ of my blog post you can inspect example code „https://github.com/thomassuedbroecker/ce-cns/blob/master/code/web-app/src/main.js“ I made.

      Someone of your teaM should provide you the realm information, if you haven’t done the Keycloak configuration by your self.

      Normally the Web Application routes to the Keycloak login.

      Maybe these videos can help to understand the example code:

      Or take a look in this blog post:

      How to create a new realm with the Keycloak REST API?

      Greetings,

      Thomas

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.