Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Remember Me' does not work with Suppressed Single sign-on configuration #7344

Closed
2 tasks
TanyaMykhnevych opened this issue Sep 26, 2024 · 1 comment
Closed
2 tasks
Labels
b2c Related to Azure B2C library-specific issues bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.

Comments

@TanyaMykhnevych
Copy link

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)

  • Sent
  • Pending

MSAL Configuration

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
        },
    });

Relevant Code Snippets

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()),
        );
    }
}

Reproduction Steps

  1. Set SingleSignOn Scope="Suppressed" in Azure AD B2C Signup_Signin custom policy;
  2. Enable 'Remember Me' in Azure AD B2C custom policy;
  3. Implement authorization in Angular App using msal.js with code provieded;
  4. Select 'Remember Me' during Sign In.

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)

@TanyaMykhnevych TanyaMykhnevych added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels Sep 26, 2024
@github-actions github-actions bot added b2c Related to Azure B2C library-specific issues msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications labels Sep 26, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label Sep 26, 2024
@TanyaMykhnevych
Copy link
Author

I asked Azure Microsoft Suuport. They said that if you are using SingleSignOn Scope='Suppressed' it will not modify or generate an SSO cookie, this is by design as it will not use one in this situation as it is intended to prompt for authentication when switching journeys https://learn.microsoft.com/en-us/azure/active-directory-b2c/relyingparty#singlesignon.

@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs: Attention 👋 Awaiting response from the MSAL.js team label Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
b2c Related to Azure B2C library-specific issues bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-angular Related to @azure/msal-angular package msal-browser Related to msal-browser package public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests

1 participant