Open TanyaMykhnevych opened 2 days ago
MSAL.js (@azure/msal-browser)
2.26.0
MSAL Angular (@azure/msal-angular)
2.3.2
Public
I implemented Keep Me Signed In according to Microsoft doc: https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-behavior?pivots=b2c-custom-policy#enable-keep-me-signed-in-kmsi. I have Suppressed SingleSignOn in my custom Azure AD B2C policy. I also have Angular SPA,it uses msal library. But it logs me out after 24 hours. When I change scope to Tenant , it works okay.
Also I noticed that sso cookie does not exist for Suppressed scope.
No response
return new PublicClientApplication({ auth: { authority: b2cPolicies.authorities.signUpSignIn.authority, clientId: environment.msalClientId, knownAuthorities: [environment.authorityName], postLogoutRedirectUri: window.location.origin, redirectUri: `/`, }, cache: { cacheLocation: BrowserCacheLocation.LocalStorage, storeAuthStateInCookie: isIE, // set to true for IE 11 }, });
Custom Azure AD B2C policy Signup_Signin <UserJourneyBehaviors> <SingleSignOn Scope="Suppressed" KeepAliveInDays="30"/> <SessionExpiryType>Absolute</SessionExpiryType> <SessionExpiryInSeconds>1200</SessionExpiryInSeconds> <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="046c8d7d-66fe-493e-9493-cc4f46cf065b" DeveloperMode="true" ClientEnabled="false" ServerEnabled="true" TelemetryVersion="1.0.0" /> <ScriptExecution>Allow</ScriptExecution> </UserJourneyBehaviors> Typescript code: import { HttpErrorResponse } from '@angular/common/http'; import { Inject, Injectable } from '@angular/core'; import { MSAL_GUARD_CONFIG, MsalBroadcastService, MsalGuardConfiguration, MsalService } from '@azure/msal-angular'; import { AccountInfo, AuthenticationResult, InteractionRequiredAuthError, InteractionStatus, RedirectRequest, SilentRequest, } from '@azure/msal-browser'; import { Observable, of, Subject } from 'rxjs'; import { catchError, delay, filter, map, switchMap, take, tap, } from 'rxjs/operators'; import { environment } from '../../../../environments/environment'; import { AzureErrorCodes } from '../../enum'; import { apiConfig } from '../apiconfig'; import { TokenService } from './token.service'; @Injectable() export class AuthService { private _authenticationTokenSubject$: Subject<void> = new Subject<void>(); constructor( @Inject(MSAL_GUARD_CONFIG) private _msalGuardConfig: MsalGuardConfiguration, private _tokenService: TokenService, private _msalService: MsalService, private _msalBroadcastService: MsalBroadcastService, ) { this._msalBroadcastService.inProgress$.pipe( filter((status: InteractionStatus) => status === InteractionStatus.None), switchMap(() => this.getAuthenticationToken()), ).subscribe(); } public isAuthenticated(): boolean { return Boolean(this._msalService.instance.getActiveAccount()); } public loginRedirect(): Observable<void> { if (this._msalGuardConfig.authRequest) { return this._msalService.loginRedirect({ ...this._msalGuardConfig.authRequest } as RedirectRequest); } return this._msalService.loginRedirect(); } public logout(): void { this._logout().subscribe(); } public unauthorize(): void { this._msalService.logout(); this._tokenService.clearToken(); } public getAuthenticationToken(): Observable<string> { this.checkAndSetActiveAccount(); const params: SilentRequest = { account: this._msalService.instance.getActiveAccount(), scopes: apiConfig.b2cScopes, }; return this._msalService.acquireTokenSilent(params).pipe( switchMap((response: AuthenticationResult) => { if (new Date(response.expiresOn) > new Date()) { this._tokenService.token = response.accessToken; this._authenticationTokenSubject$.next(); return response.accessToken; } throw new Error('Token is expired'); }), catchError((error: HttpErrorResponse) => { if (error instanceof InteractionRequiredAuthError) { if (error.errorMessage.includes(AzureErrorCodes.SessionNotExist)) { return this._logout().pipe(map(() => '')); } if (error.errorMessage.includes('interaction_required')) { return this._msalService.acquireTokenRedirect(params).pipe(map(() => '')); } if (error.errorCode !== 'block_token_requests' && error.errorCode !== 'user_cancelled' && error.errorCode !== 'login_progress_error') { throw error; } } else if (error.message === 'Token is expired') { return this.loginRedirect().pipe(map(() => '')); } else { return this._msalService.acquireTokenRedirect(params).pipe(map(() => '')); } return of(''); }), ); } public checkAndSetActiveAccount(): void { const account = this._msalService.instance.getAllAccounts().find( (item: AccountInfo) => item.environment === environment.authorityName, ); if (account) { this._msalService.instance.setActiveAccount(account); } } public waitForAuthenticationToken(): Observable<void> { return this._authenticationTokenSubject$.asObservable().pipe(take(1)); } private _logout(): Observable<void> { const delayTime = 2000; return this._msalService.logout().pipe( tap(() => this._tokenService.clearToken()), delay(delayTime), switchMap(() => this.loginRedirect()), ); } }
User is not prompted to login for 30 days.
Azure B2C Custom Policy
Chrome, Firefox, Edge
External (Customer)
Core Library
MSAL.js (@azure/msal-browser)
Core Library Version
2.26.0
Wrapper Library
MSAL Angular (@azure/msal-angular)
Wrapper Library Version
2.3.2
Public or Confidential Client?
Public
Description
I implemented Keep Me Signed In according to Microsoft doc: https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-behavior?pivots=b2c-custom-policy#enable-keep-me-signed-in-kmsi. I have Suppressed SingleSignOn in my custom Azure AD B2C policy. I also have Angular SPA,it uses msal library. But it logs me out after 24 hours. When I change scope to Tenant , it works okay.
Also I noticed that sso cookie does not exist for Suppressed scope.
Error Message
No response
MSAL Logs
No response
Network Trace (Preferrably Fiddler)
MSAL Configuration
Relevant Code Snippets
Reproduction Steps
Expected Behavior
User is not prompted to login for 30 days.
Identity Provider
Azure B2C Custom Policy
Browsers Affected (Select all that apply)
Chrome, Firefox, Edge
Regression
No response
Source
External (Customer)