simple user
simple user

Reputation: 383

Log out issue from second tab when log out from first tab in Angular

I am using sessionStorage to hold accessToken. My steps are as follows:-

Actually it is not logging me out from another tab.

I added below code but it is not working as expected.

@HostListener('window:storage', ['$event'])
    onStorageChange(sv:StorageEvent) {       
      if(sv.storageArea == sessionStorage) 
      {
        let token = sessionStorage.getItem('accessToken');
        if(token == null || token == undefined)
            this.router.navigate(['/login']);
      }
    }

Please let me know if I am doing any mistake. I am currently using this code in home page. Is it the right location?

Upvotes: 6

Views: 5732

Answers (3)

Usama nadeem
Usama nadeem

Reputation: 431

Implement AuthGuard on your routes that require sign in. In the Auth Guard add your login check logic and if user is not logged in then redirect to sign in page.

auth.guard.ts

import { Injectable } from '@angular/core';
import {Router,CanActivate,ActivatedRouteSnapshot,RouterStateSnapshot} 
from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    let token = sessionStorage.getItem('accessToken');
    if(!token)
        this.router.navigate(['/login']);
        return false
    }
    return true;
  }
}

Your Routing file

const routes: Routes = [
  {
    path: '',
    component: YourComponent,
    canActivate: [AuthGuard],
}]

I hope this works for you or anyone who's looking for the same solution. Thank you

Upvotes: 1

David
David

Reputation: 34445

To communicate between tabs, you can make use of localStorage and still keep sessionStorage to store your sensitive data.

Here is a small implementation of an authentication service which uses:

  • sessionStorage to store your user data (token or whatever)
  • localStorage to communicate with other opened tabs.
  • rxjs to trigger events from the service

The idea is that your application listens for storage events. Then when you sign out, it sets a flag in localStorage, which other opened tabs can capture.

import { Injectable } from "@angular/core";
import { Subject, Observable } from "rxjs";

@Injectable({providedIn:'root'})

export class AuthenticationService{

  private eventSubject: Subject<boolean> = new Subject<boolean>();

  public readonly statusChanged$: Observable<boolean> = this.eventSubject.asObservable();

  private loggedIn = false;

  constructor()
  {
    window.onstorage = () => { //
    {
      let loggedIn = sessionStorage.getItem('accessToken') !== null;

      if(localStorage.getItem('signOut'))
      {
          loggedIn = false;
      }

      if(this.loggedIn !== loggedIn)//Don't trigger event if no change
      {
        this.loggedIn = loggedIn;
        this.eventSubject.next(loggedIn);
      }
    };
  }
}

  public logIn()
  {
    //Do your business to login and obtain a token before here...
    localStorage.removeItem('signOut');//clear flag in local storage
    sessionStorage.setItem('accessToken', 'token');//save token in session storage
  }

  public logOut()
  {
    localStorage.setItem('signOut', 'true'); //trigger flag
    sessionStorage.removeItem('accessToken'); //Remove token from session
  }
  public isLoggedIn()
  {
    return this.loggedIn;
  }
}

You can just use that service in your components

constructor(private authSvc:AuthenticationService)
{
    this.authSvc.statusChanged$.subscribe(isLoggedIn=>
    {
      //Do whatever you want

    });
}

Here is a stackblitz demo.

Upvotes: 8

Pratyush Swain
Pratyush Swain

Reputation: 154

First of all you have to place this code in the app.component.ts file

secondly write a window event

 window.addEventListener('storage', (event) => {
            if (event.storageArea == localStorage) {
                let token = localStorage.getItem('accessToken');
                if (token == undefined) {
                    // Perform logout
                    //Navigate to login/home
                    this.router.navigate(['/login']);
                }
            }
        });

I believe it should work fine

Upvotes: 1

Related Questions