How can you display a session timeout warning that is smart enough to handle multiple open browsers or tabs
Asked Answered
A

4

17

I have implemented a session timeout warning using javascript that simply asks the user if they want to extend their session or logout. The problem is that this is for an intranet portal where power users will often have several browser windows or tabs open at the same time to the application. Currently, they will be prompted that they are about to be logged out from every browser window. How can I make the code smarter to detect that they are actively using another browser session?

Accentuation answered 12/12, 2008 at 19:14 Comment(7)
This is an interesting question and very practical. I will watch for response to this as I don't have an immediate answer :)Pronunciamento
No idea why this was down-voted.Woolpack
Yeah, I was also surprised. I voted it up, Also since Joel is new to SO, he hasn't done anything wrong to discourage him by voting down :)Pronunciamento
Joel, I'm looking for a solution that you already have. I do want all browsers to get the warning and logout. Do you mind sharing your code and method on how you did it?Hayden
warning: i wrote this back in my dark ages of programming. dl.dropbox.com/u/203098/sessiontimeout.jsAccentuation
The closest I've seen to handle this is a JS-based solution where only the current tab is taken into account, and the warning is displayed after the session times out even if the session has been continued in other tabs. Sure would be nice to have an elegant solution (using cookies or otherwise) to this scenario, nearly four years after the question was asked...Benjamin
@Accentuation your link is dead (and understandably so since it has been more than 7 years since you posted it). Can you update the link please? I have a similar requirement.Arachne
I
2

You'd have to check the session state on the server using Ajax and keep track of all the open sessions/windows the user has. You'd then be able to target only one of the available sessions with the log out warning.

In response to your comment:

Don't use the built-in session mechanism, devise your own using an server-side presistent array or a database log.

No, nothing in the HTTP request tells you how many browsers are open, but you can assign your own sessionID cookie as the user opens each browser window. Make an Ajax call to the server, see if the user has timed-out, and if you're the lowest (or last) entry in the session log then you're the browser that gets the warning.

Intrauterine answered 12/12, 2008 at 19:19 Comment(3)
2 thoughts: 1) how to you check the session state of a .NET app without actually extending the session? 2) is there actually a way to tell how many browser windows a user has? Nothing in the http request tells you thisAccentuation
Have the function to update session called when the user performs an action, don't call the function when you are checking session status. You could detect how many browsers are open based on agent string, don't think you can detect windows/tabs of each.Schaefer
I don't understand how that would work. Also, if they are using separate browsers (like IE and FF) or even separate instances of the same browser then they have different sessions so this isn't an issue.Accentuation
Y
2

You can't count on all tabs/windows to be part of the same Session, because they could be spawned and contained within separate processes and you don't have much control over that.

But if your code references a Javascript cookie, you can check your pseudo-session state via a postback (synchronous or asynchronous AJAX). But then you're depending on cookies being enabled on the user's browser.

Yachtsman answered 12/12, 2008 at 20:49 Comment(0)
A
1

Would this work?

Store a Javascript cookie and check that to determine if the session has been extended in another tab?

looks like this does work...

Accentuation answered 12/12, 2008 at 20:11 Comment(1)
After 4 years this still looks like the right answer, for ASP.NET at least. The problem is that you need a combination of client-side and server-side approaches, and I think you can't get it server-side (because you can track login/out or session start/end, but not client-side activity of which the server is unaware). I think therefore you need precisely what you're suggesting here. I'll post it when I've made it work.Adenitis
T
0

Install @ng-idle @ng-idle is available via NPM. Install it by running:

npm install --save @ng-idle/core @ng-idle/keepalive angular2-moment

Set up your application module Open src/app/app.module.ts and import the Ng2IdleModule using

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { NgIdleKeepaliveModule } from '@ng-idle/keepalive'; // this includes the core NgIdleModule but includes keepalive providers for easy wireup

import { MomentModule } from 'angular2-moment'; // optional, provides moment-style pipes for date formatting

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MomentModule,
    NgIdleKeepaliveModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

then in component.ts

import { Component } from '@angular/core';

import {Idle, DEFAULT_INTERRUPTSOURCES} from '@ng-idle/core';
import {Keepalive} from '@ng-idle/keepalive';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

    currentPath: String;

    idleState = 'Not started.';
    timedOut = false;
    lastPing?: Date = null;

    constructor(private idle: Idle, private keepalive: Keepalive, location: Location, router: Router) {

        // sets an idle timeout of 5 seconds, for testing purposes.
        idle.setIdle(5);

        // sets a timeout period of 5 seconds. after 10 seconds of inactivity, the user will be considered timed out.
        idle.setTimeout(5);

        // sets the default interrupts, in this case, things like clicks, scrolls, touches to the document
        idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);

        idle.onIdleEnd.subscribe(() => this.idleState = 'No longer idle.');

        idle.onTimeout.subscribe(() => {
            this.idleState = 'Timed out!';
            this.timedOut = true;
        });

        idle.onIdleStart.subscribe(() => this.idleState = 'You\'ve gone idle!');
        idle.onTimeoutWarning.subscribe((countdown) => this.idleState = 'You will time out in ' + countdown + ' seconds!');

        // Sets the ping interval to 15 seconds
        keepalive.interval(15);

        keepalive.onPing.subscribe(() => this.lastPing = new Date());

        // Lets check the path everytime the route changes, stop or start the idle check as appropriate.
        router.events.subscribe((val) => {

            this.currentPath = location.path();
            if(this.currentPath.search(/authentication\/login/gi) == -1)
                idle.watch();
            else
                idle.stop();

        });
    }

    reset() {
        this.idle.watch();
        this.idleState = 'Started.';
        this.timedOut = false;
    }
}
Tractile answered 25/9, 2019 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.