'Angular routing with Msal Azure AD integration

I am on Angular 13, integrated with Azure AD using MSAL. My issue is as soon as the user successfully logs in , the logincomponent is not displayed. But when I do a page refresh then the login component displays. How do I get login component to display as soon as the user signs in.

On debugging realized, on signing in when AuthGaurd kicks in , this this.msalsvc.instance.getActiveAccount() returns a null even though sign in was successful

This is my app routing,

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth-guard.guard';
import { LoginComponent } from './components/login/login/login.component';
import { TestComponent } from './components/test/test.component';
import { RoleGuard } from './route-guard.guard';


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

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

This is my app.component.html

<app-header></app-header>

  <div *ngIf="IsLoggedIn()">
    <h3>Welcome {{userName}}</h3>
    <h3>Your Assigned role: {{userRole}}</h3>
  </div>
  <div *ngIf="!IsLoggedIn()">
    <h3>You are NOT logged in</h3>
  </div>

<router-outlet></router-outlet>
<app-footer></app-footer>

This is the code for Auth Guard

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot, UrlTree } from '@angular/router';
import { MsalService } from '@azure/msal-angular';
import { map, Observable, Subscription } from 'rxjs';
import { CommonService } from './services/common-service.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate{
 
  constructor(private msalsvc : MsalService){
  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
      console.log('Hi there, ');
 
    if(this.msalsvc.instance.getActiveAccount() == null){
      return false;
    }
    return true;
  }

  
}

This is the common service where the method for login is added

import { Injectable } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
import { AuthenticationResult } from '@azure/msal-browser';
import { observable, Observable, Subject,of} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CommonService {

  //private loggedIn : boolean = false;
   private subject = new Subject<any>();
  constructor(private authService: MsalService) {
    console.info('Common service is created');
   }
   
   login() {
    this.authService.loginPopup()
      .subscribe((response: AuthenticationResult) => {
        this.authService.instance.setActiveAccount(response.account);
        this.updateLoginNotification(true);
      });
  }

  isLoggedIn(): boolean {
    return this.authService.instance.getActiveAccount() != null
  }

  isAsyncLoggedIn():Observable<boolean>{
    return of(this.authService.instance.getActiveAccount() !=null);
  }
  
  onLoginCheck(): Observable<boolean>{
     return this.subject.asObservable();
   }
  
   getName():any{
    this.getRole();
    return this.authService.instance.getActiveAccount()?.name;
  }
   getRole():any{
     return (this.authService.instance.getActiveAccount()?.idTokenClaims as any).roles;
   }
   updateLoginNotification(item: any) { 
    this.subject.next(item);
}

}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source