When attempting to log out of Keycloak, a TypeError occurs in the front-end application stating that it cannot read properties of undefined related to the action of logging out

I've been trying to implement a logout feature in my front-end application using Keycloak, but I'm encountering difficulties. Most of the examples I found online are for older versions of Keycloak and use 'auth' and 'redirectURI'. Can someone please guide me on how to properly logout from Keycloak OAUTH?

The URL structure I'm working with is as follows:

KEYCLOAK_LOGOUT_URL=http://localhost:9080/realms/{myRealmName}/protocol/openid-connect/logout
import Keycloak from "keycloak-js";
const config = useRuntimeConfig();

const initOptions = useState("initOptions", () => ({
  realm: config.public.KEYCLOAK_REALM_NAME,
  clientId: config.public.KEYCLOAK_CLIENT_ID,
  url: config.public.KEYCLOAK_SERVER_URL,
}));

// More code snippets and functions here...

Despite successfully logging into the server using the mentioned method, I am facing an issue with the logout function. When attempting to logout, I get the following error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'logout')
    at Keycloak.kc.logout (keycloak-js.js?v=59798791:988:20)

While I can obtain the token and idToken upon login, the logout process seems to be problematic.

Answer №1

Sharing this solution for future reference as Keycloak has undergone significant changes in recent versions, rendering old answers outdated.

Below is the method that successfully enabled logging in and out of Keycloak using a front-end application built with Vue 3 or Nuxt 3, along with the Keycloak-js library.

import Keycloak from "keycloak-js";
const config = useRuntimeConfig();

const initOptions = useState("initOptions", () => ({
  realm: config.public.KEYCLOAK_REALM_NAME,
  clientId: config.public.KEYCLOAK_CLIENT_ID,
  url: config.public.KEYCLOAK_SERVER_URL,
}));

// Initializing Keycloak constructor
const keycloak = new Keycloak(initOptions.value);

//Function to login to Keycloak and generate token and ID token
export async function keycloakLogin() {
  try {
    // Initialize Keycloak and handle authentication
    const auth = await keycloak.init({
      onLoad: "login-required",
      flow: "implicit",
    });

    // Reload if not authenticated to display login page
    if (!auth) {
      window.location.reload();
    } else {
      console.log("User is authenticated");
    }

    // Store tokens in local storage if present
    if (keycloak.token) {
      window.localStorage.setItem("keycloakToken", keycloak.token);
      window.localStorage.setItem("idToken", keycloak.idToken);
    }

    // Initiating token checking
    setupTokenChecking();
  } catch (error) {
    console.error("Error initializing Keycloak:", error);
  }
}

export async function keycloakLogout() {
  const logoutURL =
    config.public.KEYCLOAK_LOGOUT_URL +
    "?id_token_hint=" +
    localStorage.getItem("idToken") +
    "&post_logout_redirect_uri=" +
    encodeURIComponent(window.location.href);

  keycloak
    .logout({ redirectUri: logoutURL })
    .then((success) => {
      console.log("User logout success ", success);
    })
    .catch((error) => {
      console.log("User logout error ", error);
    });
}


// Initial token check and periodic checks setup
async function setupTokenChecking() {
  await checkAndRenewToken(); 
  const tokenCheckInterval = 5 * 60 * 1000; 
  setInterval(checkAndRenewToken, tokenCheckInterval);
}

// Function to periodically check and renew Keycloak token
export async function checkAndRenewToken() {
  try {
    if (keycloak.isTokenExpired()) {
      console.log("Token is expired. Renewing token...");
      try {
        await keycloak.updateToken(60);
      } catch (error) {
        console.error(
          "Refresh Token Failed : " + JSON.stringify(error, null, 4)
        );
        window.location.reload();
      }
    }
  } catch (error) {
    console.error("Error checking/renewing token:", error);
  }
}

The example URL configuration:

KEYCLOAK_REALM_NAME=myRealm
KEYCLOAK_CLIENT_ID=myClientID
KEYCLOAK_SERVER_URL=http://localhost:9080
KEYCLOAK_LOGOUT_URL=http://localhost:9080/realms/myRealm/protocol/openid-connect/logout

Keycloak no longer requires /auth in the URLs as it did previously.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An Easy Method for Managing Files in a Node.js Directory: Editing and Deleting Made Simple

Greetings! I am currently in the process of developing a basic blog using express.js. To manage the creation, updating, and deletion of posts based on their unique id, I rely on a data.json file. For each action performed, I utilize fs.writeFile to generat ...

JavaScript MP3 player

Could someone kindly point out where I went wrong? I am attempting to create an MP3 player using CSS, HTML, and JavaScript. Currently, the script only functions to start or stop the audio file. However, I keep encountering an error message: TypeError: docu ...

Is there a way in Reactjs Material UI 5 (MUI5) to unselect only the star that was clicked, without affecting the rest of the stars in the

For instance: I selected the 3rd star on the rating component, but when I click on it again, all the previous stars disappear and it shows 0 stars. How can I make it so that if I click on the 3rd star a second time, only the 3rd star is removed, leaving ...

Using Ajax to call a PHP function within a WordPress website

I am looking to trigger a PHP function using AJAX. Below is the code snippet of my form: <form class="woocommerce-form woocommerce-form-login login" method="post"> <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-ro ...

Simple Bootstrap Input Slider Configuration

I am attempting to create a simple setup for a bootstrap-style input slider, but I am facing some difficulties getting it to function properly. Desired Outcome: https://i.sstatic.net/Btfo3.png Actual Outcome: https://i.sstatic.net/0VnNv.png Resource / ...

json How to retrieve the first index value in jQuery

As part of my Ajax loop, I am successfully generating JSON and iterating through the results. My goal is to extract only the first index value of JSON which is name. In jQuery, I have the following code: PHP $jsonRows[] = array( "name" => ...

What is the best way to transfer the value of a slider from jQuery or JavaScript to a Python Flask application

Trying to implement a round slider that displays its value on the client-side webpage. Whenever the user adjusts the slider, the updated value needs to be sent to the server using Python Flask as the backend. I attempted to achieve this using jQuery and Aj ...

Tips for eliminating the gap separating the authentication design from the additional elements within the Laravel, Vue, and Inertia framework

I'm currently working with Laravel and Vue using Inertia. When I log into the system, the authentication layout creates a space at the top of the page. How can I resolve this issue? Here is an image highlighting the space I need to remove, marked wit ...

Trouble implementing array filter in React component is a common issue

Hello everyone! I'm facing an issue with deleting an element from my useState array. I have the index of the element that I want to remove, and I've tried the following code snippet: const updatedArray = myArray.filter((item: any, index: number) ...

Verify the position of the scrollbar without triggering any reflow

Here is a function I have: is_bottom: function() { if (settings.scrollBottomOffset === -1) { return false; } else { var scroll_height, scroll_top, height; scroll_height = ...

"The file upload function is populating the req.body object, but not the req.file

I successfully implemented a file upload API using multer and express, which functions well when accessed through POSTMAN. However, I encountered an issue when trying to utilize the same API with another file upload API: The code I used can be found below ...

Is it possible to obtain a user's public URL using the Facebook API in version 2?

In version 1, it is possible to obtain the user's public link by using the following endpoint: /v1.0/me function testAPI() { console.log('Welcome! Fetching your information....'); FB.api('/me', function(response) { ...

What is the best way to monitor a Vue instance property within a component?

I recently implemented a plugin that introduces a new property to the Vue instance. This property can then be accessed within components using this.$plugin.prop. However, I am encountering difficulty in watching for changes to this property. I need to perf ...

Leveraging a JavaScript variable within a PHP snippet

Similar Question: Sending a PHP string to a JavaScript variable with escaped newlines Retrieving a JavaScript variable from PHP I am trying to work with a Javascript function that accepts one variable, having some PHP code embedded within it. I am ...

What is the best way to target the nth-child() of a slotted element within a web component that utilizes multiple uniquely named slots?

I am struggling to select the second slotted item in a specific slot using slot[name=foo]::slotted(:nth-child(2)){, but it's not behaving as I anticipated. Even though the first foo slot is styled with green, the second one doesn't follow suit. ...

Migrating to Angular Universal for server-side rendering with an external API server

Thank you for taking the time to read my query. I have developed a project using server-side Node.js and client-side Angular 6. The purpose of the app is to provide information on cryptocurrency prices and details. I am now looking to transition my Angu ...

JQuery's addClass function is not functioning properly

Check out the code snippet below: function toggleAccessRequests() { var buttonValue = $("#showAccessRequests").val(); if (buttonValue == "Show") { $(".hideAccessRequest").removeClass("hideAccessRequest"); $("#showAccessRequests").v ...

Managing pagination within the Vuex state management system: a guide

After finding this amazing shopping cart repository on https://github.com/vueschool/learn-vuex, I successfully cloned it and the retrieved data appears like this: ProductList.vue <template> <div> <ul> <li v-for="product ...

Next.js - Anticipated that the server HTML would include a corresponding <div> within <div> tag

For a live demonstration, please click here In my current project, I am experimenting with creating a simple layout that adjusts based on the user's screen size. Specifically, on mobile devices, only the latest posts should be displayed. On desktops, ...

Making a Dialog resizable with jQuery's Resizable Helper

Is there a way to implement the Helper feature from jQuery Resizable, which only shows a frame while resizing the container, in a Dialog? ...