angularazure-ad-msalsession-timeoutmsal.js

Lack of Session Expiration with Azure Active Directory


Currently, I am working on a project (Angular, Spring Boot) where a security team made some penetration tests.

We have a problem solving a problem regarding the session expiration. Specifically, the application does not invalidate the users’ sessions after a given amount of idle time and the user stays logged in.

We authenticate our users with azure active directory using the msal library in angular and we retrieve the id token. I can see that the id token expires after 1 hour but it seems that msal silent reauthenticates and gets a new token if it is expired.

Is there a way to force to login again after this id token is expired?


Solution

  • This image taken from Azure B2C documentation on "Token lifetime behavior" is pretty illustrative on how token works:

    Token renewal in Azure B2C

    That means that the token auto-refresh during "Refresh token lifetime" (1 to 90 days, defaults to 14 days). That means that it will get silently renewed within at least 1 day.

    So even if the token expired hours ago, but it is still inside the "Refresh token lifetime", it will get a new valid token for another 1h (or the token set lifetime, from 5min to 24h).

    A way to force login after token expired that I found is intercept, in your AppComponent, the token acquisition, and logout if the token expired.

    import { MsalService, MsalBroadcastService } from '@azure/msal-angular';
    
    ...
    
    export class AppComponent implements OnInit {
      constructor(
        private readonly authService: MsalService,
        private readonly msalBroadcastService: MsalBroadcastService,
      ) {}
    
      ngOnInit() {
        this.msalBroadcastService.msalSubject$
         .pipe(filter((msalSubject: EventMessage) => msalSubject.eventType === EventType.ACQUIRE_TOKEN_START))
         .subscribe(() => {
            const activeAccount = this.getActiveAccoun;
            // You can check other claims https://authts.github.io/oidc-client-ts/interfaces/IdTokenClaims.html
            if (activeAccount?.idTokenClaims?.exp && activeAccount?.idTokenClaims?.exp > new Date().getTime() / 1000) {
               // Logout
               this.authService.logoutRedirect({
                  // Your options here
               });
            }
          });
      }
    
      getActiveAccount(): AccountInfo {
        const activeAccount = this.authService.instance.getActiveAccount();
        return activeAccount || (this.getAllAccounts().length ? this.getAllAccounts()[0] : null);
      }
    }