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

23 thoughts on “Simply logout from Keycloak

Add yours

  1. 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

    1. 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. 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

    1. Hi LT, ok.

      Case 1: Works

      Case 2: Problems with logout.

      Do you use the right ENCODED_REDIRECT_URI in your source code, you must create two ENCODED_REDIRECT_URIs, one for the first and one for the second realm. Did you do that?

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

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

      Maybe you should also check the usage of the cookies. Maybe that helps.

      Greetings,

      Thomas

      Like

  3. ..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

    1. 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. 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

    1. 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:

      https://suedbroecker.net/2020/08/04/how-to-create-a-new-realm-with-the-keycloak-rest-api/

      Greetings,

      Thomas

      Like

  5. simply code but its not working
    if(keycloak.authenticated) {
    keycloak.logout().then((success) => {
    alert(“Success”)
    }).catch((error) => {
    alert(“Fail”)
    });
    }

    Like

    1. I would say the redirectUri is missing in your code:

      var logoutOptions = { redirectUri : urls.cns };
      console.log(“–> log: logoutOptions “, logoutOptions );

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

      Like

    1. If you take a lock at my first words in my blog post and you see how you logout with the REST API from keycloak.

      “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}”

      Keycloak documentation: “https://www.keycloak.org/docs/latest/securing_apps/index.html#logout”

      But, if you don’t provide the uri, which page should be invoked after the logout?

      When I use my implementation it works fine for me, it took me some time to figure what the format was for that simply

      “redirect_uri”

      using the javascript SDK.

      Like

  6. Okay, after giving redirect url, still its not working, My redirect url is http://localhost:3000/logout

    i.e https://{KEYCLOAK_URL}/auth/realms/{{REALM_NAME}/protocol/openid-connect/logout?redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Flogout

    i feel, its because my redirect using http protocol where as keycloak url is https. Is it this issue ?

    Like

  7. const url=encodeURIComponent(“http://localhost:3000/logout”);
    const backurl=”https://{{KEYCLOAK_URL}/auth/realms/{REALM_NAME}//protocol/openid-connect/logout?redirect_uri=”+url;
    keycloak.logout(backurl).then((success) => {
    alert(“Success”)
    }).catch((error) => {
    alert(“Fail”)
    });

    Like

  8. keycloakStore.keycloak.logout({
    redirectUri: ‘http://localhost:3000/home’,
    }).then(res => {
    console.log(“退出成功”, res);
    }).catch(res => {
    console.log(“退出失败”, res);
    })
    above is my code,but give me a hint “Invalid redirect uri”

    Like

Leave a comment

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

Blog at WordPress.com.

Up ↑