microsoft-authentication-library-for-js: Initial login failing with state mismatch error

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Other... Please describe:

Browser:

  • Chrome version latest
  • Firefox version latest
  • IE version latest
  • Edge version latest
  • Safari version XX

Library version


Library version: msal-angular v0.1.4

Current behavior

On the initial load, a user is redirected to the login page, and after a successful login they are redirected back to the app, which throws a Error State Mismatch.Expected State: null,Actual State: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX error, and then are redirected back to the login page. After logging in again, the app works as expected.

The MSAL module is initialized in an AuthModule with the following config:



export const protectedResourceMap: [string, string[]][] = [
  [environment.apiUri, [environment.azureB2C.apiScope]],
  ['https://graph.microsoft.com/v1.0/me', ['user.read']]];

const isInternetExplorerOrEdge = window.navigator.userAgent.indexOf('MSIE') > -1
                              || window.navigator.userAgent.indexOf('Trident/') > -1
                              || window.navigator.userAgent.indexOf('Edge') > -1;

@NgModule({
  ...
  imports: [
    ...
    MsalModule.forRoot({
      loadFrameTimeout: 10000,
      clientID: environment.azureB2C.clientId,
      protectedResourceMap: protectedResourceMap,
      authority: environment.azureB2C.signInAuthority,
      consentScopes: [environment.azureB2C.uiScope],
      validateAuthority: false,
      cacheLocation: 'sessionStorage',
      redirectUri: environment.azureB2C.redirectUri,
      navigateToLoginRequestUrl: false,
      storeAuthStateInCookie: isInternetExplorerOrEdge,
      logger: loggerCallback
    })
  ]
})
export class AuthModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: AuthModule,
      providers: [
        AuthService,
        AuthGuard,
        { provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true }
      ],
    };
  }
}

The signInAuthority here is an Azure B2C Sign in v2 user flow.

I’m using the provided MsalInterceptor and MsalGuard, and I have the MsalGuard on each route in the app. All other auth handling is in an Auth Service file:


@Injectable()
export class AuthService extends BaseService implements OnDestroy {
   constructor(protected http: HttpClient,
              protected router: Router,
              protected ngZone: NgZone,
              protected snackbar: ZomSnackbarService,
              private msalService: MsalService,
              private broadcastService: BroadcastService,
              protected logger: NGXLogger,
              private store: Store,
              private appInsightsService: AppInsightsService) {
    super(http, snackbar, logger, ngZone, router);

    this.subscription = this.broadcastService.subscribe('msal:loginFailure', (payload) => {
      this.logger.debug(`AuthService: msal:loginFailure`, payload);
      if (payload._errorDesc === 'User login is required') {
        this.redirectToLogin();
      }
      if (payload._errorDesc && payload.errorDesc.indexOf('AADB2C90118') === 0) {
        this.msalService.authority = environment.azureB2C.passwordResetAuthority;
        this.redirectToLogin();
      }
    });

    this.subscription.add(this.broadcastService.subscribe('msal:loginSuccess', (payload) => {
      this.logger.debug(`AuthService: msal:loginSuccess`, payload);
      this.store.dispatch(new LoginAction());
    }));

    this.subscription.add(this.broadcastService.subscribe('msal:acquireTokenSuccess', (payload) => 
    {
      this.logger.debug(`AuthService: msal:acquireTokenSuccess`, payload);
    }));

    this.subscription.add(this.broadcastService.subscribe('msal:acquireTokenFailure', (payload) => {
      this.logger.debug(`AuthService: msal:acquireTokenFailure`, payload);
      this.snackbar.info('Your session has expired. Please log in again.');
      this.redirectToLogin();
    }));

    this.subscription.add(this.broadcastService.subscribe('msal:stateMismatch', (payload) => {
      this.logger.error(`AuthService: msal:stateMismatch`, payload);
      this.redirectIfNoUser();
    }));
  }

  getAuthenticatedUserEmail(): string {
    const user = this.msalService.getUser();
    if (user && user.idToken && user.idToken['emails'] && user.idToken['emails'].length) {
      return user.idToken['emails'][0];
    }
    this.redirectToLogin();
    return null;
  }

  redirectIfNoUser() {
    if (!this.msalService.getUser() && !this.msalService.loginInProgress()) {
      this.msalService.loginRedirect([environment.azureB2C.uiScope]);
    }
  }

  redirectToLogin() {
    if (!this.msalService.loginInProgress()) {
      this.msalService.loginRedirect([environment.azureB2C.uiScope]);
    }
  }
  ...
}

Any help would be appreciated!

Expected behavior

Login credentials should only have to be entered once.

Minimal reproduction of the problem with instructions

  1. Clear browser cache or open a private session
  2. Navigate to the app
  3. Enter credentials after redirect to login page
  4. Observe that you are redirected to the app and immediately returned to the login page with the State Mismatch error in the console.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 27 (11 by maintainers)

Most upvoted comments

@jarodsmk Can you please try msal@1.3.0-beta.1 and let us know if you still have that error?

Session state is not persisted resulting in a mismatch.

@ryandegruyter Can you clarify what you mean by that? Not persisting in local storage? And which version of Edge? And are they using InPrivate by chance?

Seems to be good for me too, I upgraded to msal@1.3.0-beta.1 and msal-angular@1.0.0-beta.4 from the suggestions above 😎 I’ll test it out on our different environments in the upcoming weeks and see if there’s any changes.

I noticed that when bumping to the newer 1.0.0-beta.5 the imports for BroadcastService and MsalService couldn’t be resolved anymore, I created a seperate ticket to track it through.

https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1502

Thanks @jasonnutter !

@jasonnutter we updated to 1.0.0beta4, seems to resolve the issue.

Update package to msal@1.3.0-beta.1 fixed the issue, thanks.