title: MSAL.js acquireTokenSilent on Azure AD B2C with Microsoft Account (login.live.com) framebusting
body: <p>There is a problem with <code>login.live.com</code> that prevents acquiring access tokens with <a href="https://github.com/AzureAD/microsoft-authentication-library-for-js" rel="noreferrer">MSAL.js</a> for Azure AD B2C with the Identity Provider Microsoft Account.</p>
  
  <p>When the iframe (<code>msalRenewFrame…</code>) tries to authenticate at <code>https://login.live.com/oauth20_authorize.srf</code>, <code>https://login.live.com/oauth20_authorize.srf</code> attempts to ‘framebust’ (navigate the parent of the iframe which is the main site). Chrome shows this warning:</p>
  
  <blockquote>
    <p>Frame with URL
    '<a href="https://login.live.com/oauth20_authorize.srf?client_id=" rel="noreferrer">https://login.live.com/oauth20_authorize.srf?client_id=</a>… attempted to
    navigate its top-level window with URL
    '<a href="http://localhost:4200/#/dashboard" rel="noreferrer">http://localhost:4200/#/dashboard</a>'. Navigating the top-level window
    from a cross-origin iframe will soon require that the iframe has
    received a user gesture. See
    <a href="https://www.chromestatus.com/features/5851021045661696" rel="noreferrer">https://www.chromestatus.com/features/5851021045661696</a>.</p>
    
    <p>DoSubmit @ oauth20_authorize…<br>
    onload @ oauth20_authorize…</p>
  </blockquote>
  
  <p>This causes the main site to redirect, which turns <code>acquireTokenSilent</code> into <code>acquireTokenBoisterous</code>. Just kidding.</p>
  
  <p>I tried to sandbox the <code>msalRenewFrame…</code> with <code>ifr.setAttribute("sandbox", "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts")</code> according to <a href="https://www.w3schools.com/tags/att_iframe_sandbox.asp" rel="noreferrer">https://www.w3schools.com/tags/att_iframe_sandbox.asp</a>. Now the main site does not redirect away, but now Chrome shows an error:</p>
  
  <blockquote>
    <p>Unsafe JavaScript attempt to initiate navigation for frame with URL
    '<a href="http://localhost:4200/#/dashboard" rel="noreferrer">http://localhost:4200/#/dashboard</a>' from frame with URL
    '<a href="https://login.live.com/oauth20_authorize.srf?client_id=" rel="noreferrer">https://login.live.com/oauth20_authorize.srf?client_id=</a>… 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.</p>
  </blockquote>
  
  <p>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 <code>https://login.live.com/oauth20_authorize.srf</code> is already on it. Until then Azure AD B2C in combination with Live Accounts and MSAL.js is broken and cannot be used.</p>
  
  <p>I have posted this finding at <a href="https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/267" rel="noreferrer">issue 267 of MSAL.js</a> 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.</p>
  
  <hr>
  
  <p>This is how I instantiate MSAL:</p>
  
  <pre><code>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']})`);
    }
  }
  </code></pre>
  
  <p>and this is how I try to get an access token</p>
  
  <pre><code>public getAccessToken(): Observable&lt;string&gt; {
    const that = this;
    const acquireTokenPromise = this.clientApplication.acquireTokenSilent(environment.msalConfig.scopes);
    return fromPromise(acquireTokenPromise);
  }
  </code></pre>
  
  <p>Scopes is <code>[ 'https://....onmicrosoft.com/.../user_impersonation' ]</code></p>