Ways to determine if a user has been logged out of the identity server using a Javascript application

My setup includes an Identity server 4 application, several asp .net core applications, and a Javascript application. I've enabled back channel logout on the asp .net core applications to ensure that when one application logs out, they are all logged out almost instantly.

The problem arises with the JavaScript application, which needs to constantly poll the identity server every minute to check if the user is still logged in. This becomes crucial in financial applications where users need to be logged out of all platforms when they leave their desk.

Imagine a scenario where a user is logged into Asp .net core app 1, Asp .net core app 2, and the Javascript app via tokens from the identity server. When the user logs out of Asp .net core app 1 triggering the back channel logout, it also logs out of Asp .net core app 2. However, the JavaScript app needs manual intervention to sign out the user, which involves continuous polling of the identity server for authentication status.

JavaScript timer

To accomplish this, I have set up a timer that runs every second to call the identity server.

setInterval(myTimer, 1000);
function myTimer() {
    mgr.getUser().then(function (user) {

        var url = config.authority + "/api/user/LoggedIn";
        var xhttp = new XMLHttpRequest();

        xhttp.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {
                alert(this.responseText);
            }
        };


        xhttp.open("GET", url);
        xhttp.setRequestHeader("Authorization", "Bearer " + user.access_token);
        xhttp.send();
    });

}

Identity server endpoint

I've created an API endpoint on the identity server to verify user authorization.

[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{

    [HttpGet("LoggedIn")]
    public IActionResult LoggedIn()
    {
        return Ok(new { IsLoggedIn = User.Identity.IsAuthenticated });
    }
}

However, the issue lies in the fact that this API endpoint fails to correctly load user identity information, showing User.Identity.IsAuthenticated as false even when the user is logged in on the identity server.

How can I accurately determine if the user is still authenticated on the identity server? Is there a more effective endpoint that already provides this information? The userinfo endpoint returns true regardless of the user's actual status. Is there no direct way to check the auth session on the identity server itself from JavaScript?

Answer №1

OpenID Connect includes a unique feature designed for this specific purpose:

This functionality is readily available through the oidc-client-js library. Take note of the monitorSession property within the UserManagerSettings.

In essence, it actively monitors your identity server from the client side by using an iframe linked to the check_session_iframe URL and communicating via postMessage. The IDP stores a cookie with the session ID accessible to client scripts and responds based on the status of the expected session. If it returns a response of changed (indicating a different session than anticipated), your application can take action like attempting silent reauthentication. If unsuccessful, you have the flexibility to sign out the user and present a customized user experience.

For example:

var mgr = new Oidc.UserManager(config);
mgr.events.addUserSignedOut(function () {
    console.log("user signed out");
    log("user signed out");
});

See it in action:

https://i.sstatic.net/dMAkm.png

Answer №2

To enhance your response, you can format it and include a cookie:

    HttpResponseMessage customizedResponse = Request.CreateResponse<CustomResponse>(
        HttpStatusCode.OK,
        new CustomResponse() { IsLoggedIn = User.Identity.IsAuthenticated }
    );

    // create and add cookie to the response
    var cookie = new CookieHeaderValue("IsLoggedIn", User.Identity.IsAuthenticated);
    cookie.Expires = DateTimeOffset.Now.AddDays(1);
    cookie.Domain = Request.RequestUri.Host;
    cookie.Path = "/";
    cookie.HttpOnly = true;
    customizedResponse.Headers.CacheControl = new CacheControlHeaderValue()
    {
        MaxAge = TimeSpan.FromMinutes(20)
    };
    customizedResponse.Headers.AddCookies(new CookieHeaderValue[] { cookie });

    return customizedResponse;

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

Implementing position sticky on a div depending on its content text - step by step guide

If the text inside the .newsDate matches the previous or next .newsDate, I want to make its position sticky when scrolling, until it reaches the next .newsMiddleCont div. What I'm trying to achieve: The same date on multiple news items should s ...

Error detected in d3.js Stacked chart transformation

I have developed an application for creating stacked chart animations and updates. However, I am encountering some NaN values being passed into the y and height variables. I am unsure about what is causing this issue. When toggling the data, the charts eve ...

Error: The value "'827'" cannot be assigned to "Course_Content.course_outline_id" as it must be a valid instance of "Course_Outline"

While working on my django view, I encountered an error stating: ValueError: Cannot assign '827': 'Course_Content.course_outline_id' must be a 'Course_Outline' instance. I attempted to convert it to an int but it still didn&ap ...

Expanding form fields dynamically with AngularJS

I am currently working on a form that allows users to click a '+' sign in order to add new lines. I've set up a function to be called when the button is clicked, which should push a new line into the array. However, for some reason the new l ...

Is there a way to retrieve the $state object from ui router in the console?

I attempted to modify the route from the console by using this method to access the $state object: $inject = angular.injector(['ng', 'ui.router']); $inject.get('$state').go Unfortunately, I encountered an error: Uncaught Er ...

Troubleshooting the Width Problem in Bootstrap 5 Dropdowns

I am currently working on a new project and encountering an issue with the width of a Bootstrap 5 dropdown. The problem lies in the discrepancy between the button width and the menu width. Although it may seem simple, I am having trouble resolving it as I ...

What is the best method for implementing Datepicker translations in Angular?

I am looking to incorporate the DatePicker component in Angular, enabling users to select a date that can be translated based on their browser's settings. Any suggestions on how to achieve this? <mat-form-field appearance="fill"> ...

Reverse the order of jQuery toggle animations

Looking for something specific: How can I create a button that triggers a script and then, when the script is done, reverses the action (toggles)? (I am currently learning javascript/jquery, so I am a beginner in this field) Here's an example: ...

Vue select component not refreshing the selected option when the v-model value is updated

Trying to incorporate a select element into a Vue custom component using the v-model pattern outlined in the documentation. The issue at hand is encountering an error message for the custom select component: [Vue warn]: Avoid directly mutating a prop as i ...

Aggregating MongoDB: Calculating unique values within an array

Looking to find the distinct tags count on all records within a mongodb query, utilizing JS. Data structure of the record: { "_id": { "$oid": "62e593aed8fd9808777225e8" }, "title": "“The world as ...

Having trouble retrieving POST data in NodeJS from Angular application

I'm struggling to retrieve the parameters from a POST method implemented in an Angular application. Despite searching for solutions and even attempting examples found online, I have not been successful. Below is the Node.js code snippet: var express ...

methods for transforming a string into an object

let styleValues = "{ "background-color": "#4a90e2", "padding": 10px }"; JSON.parse(styleValues); The code snippet above triggers the error below: Uncaught SyntaxError: Unexpected token p in JSON at position 46 ...

Encountering a "Element is not defined" error in Nuxt when trying to render Editor.js and receiving

I've been working on creating an editor using Editor.js within my Nuxt project, but it seems like the editor isn't initializing properly when I render the page. import EditorJS from '@editorjs/editorjs'; interface IEditor { editor: E ...

Controlling the behavior of React components in response to updates

I'm currently learning ReactJs and utilizing the ExtReact framework for my project. I have successfully implemented a grid with pagination, which is functioning well. I customized the spinner that appears during data loading and it works as expected ...

choose a unique jQuery id without any duplicates

Trying to implement a simple system comment feature similar to Facebook, but struggling with selecting the right ID for submission. The issue I'm facing is that the first form works correctly, but for subsequent forms, I always retrieve the data-id fr ...

When performing web scraping with Puppeteer, employing a single selector to target various types of data

As a budding web developer, I have recently delved into coding. My current knowledge is limited to HTML, CSS, JS, and NODE. Currently, I am working on a project involving page scraping and utilizing puppeteer. CHALLENGE - In scenarios like the o ...

What is the best way to prevent users from entering a zero in the first position of a text box using JavaScript

Although I am aware this may be a duplicate issue, the existing solution does not seem to work for me. The field should accept values like: valid - 123,33.00, 100,897,99, 8000 10334 9800,564,88.36 invalid - 001, 0 ...

Fetch information from DataObject's CSV file using JavaScript

After reading a csv file with the following code: var x="dema.csv"; loadCSV(x); function loadCSV(file) { if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari var request = new XMLHttpRequest(); } else { // ...

jQuery-powered Ajax file upload progress bar

Although I don't rely on jQuery for everything, I do find it useful for tasks such as AJAX. But currently, I'm facing some challenges with it. Here is a piece of code that should update my upload progress bar while the upload process is ongoing. ...

Nested checkbox table toggle/Select-Deselect

I have created a page that includes a nested table with checkboxes for selecting all the table cells <td>, as well as checkboxes for each individual table cell <td>. My goal is to: CheckAll checkbox should be able to check/uncheck all the pa ...