7

There is a problem with login.live.com that prevents acquiring access tokens with MSAL.js for Azure AD B2C with the Identity Provider Microsoft Account.

When the iframe (msalRenewFrame…) tries to authenticate at https://login.live.com/oauth20_authorize.srf, https://login.live.com/oauth20_authorize.srf attempts to ‘framebust’ (navigate the parent of the iframe which is the main site). Chrome shows this warning:

Frame with URL 'https://login.live.com/oauth20_authorize.srf?client_id=… attempted to navigate its top-level window with URL 'http://localhost:4200/#/dashboard'. Navigating the top-level window from a cross-origin iframe will soon require that the iframe has received a user gesture. See https://www.chromestatus.com/features/5851021045661696.

DoSubmit @ oauth20_authorize…
onload @ oauth20_authorize…

This causes the main site to redirect, which turns acquireTokenSilent into acquireTokenBoisterous. Just kidding.

I tried to sandbox the msalRenewFrame… with ifr.setAttribute("sandbox", "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts") according to https://www.w3schools.com/tags/att_iframe_sandbox.asp. Now the main site does not redirect away, but now Chrome shows an error:

Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://localhost:4200/#/dashboard' from frame with URL 'https://login.live.com/oauth20_authorize.srf?client_id=… The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.

I assume this framebusting happens for compatibility reasons (we all know how redirect heavy logging in into Microsoft services is). I am afraid this is no easy fix. But Chrome will break it soon anyway so maybe the team behind https://login.live.com/oauth20_authorize.srf is already on it. Until then Azure AD B2C in combination with Live Accounts and MSAL.js is broken and cannot be used.

I have posted this finding at issue 267 of MSAL.js but since this is not an MSAL.js problem, I am posting it here too. I hope someone of the Microsoft Account Team sees it and can maybe provide more information.


This is how I instantiate MSAL:

public initAndHandleRedirects() {
  const authority = `https://login.microsoftonline.com/tfp/${environment.msalConfig.tenant}/${environment.msalConfig.signUpSignInPolicy}`;
  this.clientApplication = new UserAgentApplication(environment.msalConfig.clientId, authority,
    function (errorDesc, token, error, tokenType) {
      if (error) {
        console.error(error);
      } else {
        console.warn(`got new ${tokenType} token: ${token}`);
      }
    },
    {
      navigateToLoginRequestUrl: false,
      redirectUri: environment.msalConfig.redirectUri,
      logger: new Logger(this.log)
    }
  );

  if (this.authenticated) {
    console.warn(`User: ${this.idToken['extension_Nickname']} (${this.idToken['sub']})`);
  }
}

and this is how I try to get an access token

public getAccessToken(): Observable<string> {
  const that = this;
  const acquireTokenPromise = this.clientApplication.acquireTokenSilent(environment.msalConfig.scopes);
  return fromPromise(acquireTokenPromise);
}

Scopes is [ 'https://....onmicrosoft.com/.../user_impersonation' ]

halllo
  • 858
  • 12
  • 25
  • Can you example your flow a little more? Seems like you're trying to have the user authentication to B2C w/ the Microsoft Identity Provider and then request an access token from the Microsoft Identity Provider, correct? – spottedmahn Apr 15 '18 at 21:09
  • I need an access token and try to get it with invoking acquireTokenSilent on the MSAL.js library. – halllo Apr 16 '18 at 10:16
  • Can you share how you are creating an instance of the MSAL `ClientApplication`? – spottedmahn Apr 17 '18 at 00:05
  • Sure :) I added it to the question. – halllo Apr 18 '18 at 16:58
  • . That looks good. Now how are trying to get an access token? Code please . Are you using the same instance of `this.clientApplication`? – spottedmahn Apr 18 '18 at 17:03
  • Yes, it is the same instance. – halllo Apr 18 '18 at 17:11
  • 1
    I've been trying to get this working and hit this issue and I think, on balance, the issue does lie with the MSAL library; the library should work with what the service provides. It is disappointing that other services work okay with acquireTokenSilent but the MSA service does not. – Keith Davidson Nov 02 '18 at 18:02
  • Hi @halllo Did you get any solution to this problem. I am facing same problem where this.clientApplication.acquireTokenSilent is not returning anything to me. Any alternative to get around this? – Raj Feb 18 '19 at 07:56
  • @Raj unfortunately not. – halllo Feb 19 '19 at 12:55

1 Answers1

1

You can request access tokens from B2C, for scopes defined in B2C.

Example:

https://login.microsoftonline.com/<tenantName>.onmicrosoft.com/oauth2/v2.0/authorize?p=<yourPolicyId>&client_id=<appID_of_your_client_application>&nonce=anyRandomValue&redirect_uri=<redirect_uri_of_your_client_application>&scope=https%3A%2F%2Fcontoso.onmicrosoft.com%2Fnotes%2Fread&response_type=code

You can not request access from an Identity Provider (IDP) for a B2C authentication.

spottedmahn
  • 14,823
  • 13
  • 108
  • 178
  • Yes, that makes sense. But the MSAL.js library tries to acquire a token from `https://login.live.com/oauth20_authorize.srf` when I invoke `acquireTokenSilent` (which is for access tokens) and then the browser redirects away (which is bad) and gives me an access token over the redirect uri (which I expected inside the iframe). – halllo Apr 16 '18 at 10:22
  • MSAL tries to get a token from where it has been configured to @halllo – spottedmahn Apr 17 '18 at 00:03
  • 3
    I though the whole point of external identity providers was to only configure them in the B2C portal and not in the client. – halllo Apr 18 '18 at 16:59