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

Logout does not work with Application Single sign-on configuration #7345

Open
2 tasks
TanyaMykhnevych opened this issue Sep 26, 2024 · 1 comment
Open
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 Needs: Attention 👋 Awaiting response from the MSAL.js team 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 have Application SingleSignOn session behavior in my custom Azure AD B2C policy.
I also have Angular SPA, it uses msal library. I can not logout. When I press logout, user is redirected to main page, after that it is redirected to login page and automatic sign in is performed.
When I change scope to Tenant or Suppressed , it works okay.

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="Application" 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="Application" in Azure AD B2C Signup_Signin custom policy;
  2. Implement authorization in Angular App using msal.js with code provided;
  3. Log In;
  4. Log Out;

Expected Behavior

User is logged out, session is ended. Log In page is displayed.

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
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label 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
@TanyaMykhnevych
Copy link
Author

I noticed, that when I remove sso cookie by hands before pressing "Logout", it successfully logs me out.
image

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 Needs: Attention 👋 Awaiting response from the MSAL.js team 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