microsoft-authentication-library-for-js: 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.

Please follow the issue template below. Failure to do so will result in a delay in answering your question.

Library

  • msal@1.2.0 or @azure/msal@1.x.x
  • @azure/msal-angular@0.x.x
  • @azure/msal-angular@1.x.x
  • @azure/msal-angularjs@1.x.x

Important: Please fill in your exact version number above, e.g. msal@1.1.3.

Framework

If you are using a framework, please provide the framework and version (e.g. Angular v8, React v16, etc).

Description

On each API request I call acquireTokenSilent to get an access token (as I understood from the documentation, this call retrieves the value from cache or calls Azure AD to generate a new token. So it’s not a cache related problem. And I have one instance of Msal in my react application).

After some requests (3-4, inconsistent behavior) I get the following error in Chrome.

authorize?response_type=token&scope=openid api%3A%2F%2F97374b48-cf6a-4799-a635-0ee27c9abc1a%2Fapi profile&client_id={}&redirect_uri=http%3A%2F%2Flocalhost%2Flocal&state=d80df44d-f75e-4c06-87e3-659eceaec2e9&nonce=f43a42b1-c35e-4d18-a93f-13e5bd325f39&client_info=1&x-client-SKU=MSAL.JS&x-client-Ver=1.2.0&login_hint={}&login_req=299a6a66-f86c-4e17-9dc1-90efac82241a&domain_req=598e09b7-4cb7-4728-a5c0-6ae7395f428d&domain_hint=organizations&client-request-id=615f2fec-f9c5-4553-8636-6eb8793f938a&prompt=none&response_mode=fragment:80 Unsafe JavaScript attempt to initiate navigation for frame with origin ‘http://localhost’ from frame with URL 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.

Uncaught DOMException: Failed to set the ‘href’ property on ‘Location’: The current window does not have permission to navigate the target frame to 'https://login.microsoftonline.com/ A clear and concise description of the bug. If you receive specific error codes, please include them.

Security

Is this issue security related?

Regression

Did this behavior work before?

Configuration

Please provide your MSAL configuration options.

export const MsalApp = new UserAgentApplication({
    auth: {
        clientId: "{clientId}",
        authority: "https://login.microsoftonline.com/{tenantId}",
    },
    cache: {
        cacheLocation: "localStorage",
        storeAuthStateInCookie: true   
    }
});

Reproduction steps

  1. Login using loginRedirect option
  2. Call acquireTokenSilenton every API request that required authorization with
this.authenticationParameters = {
            scopes: ['openid', 'api://' + clientId + '/api']
        }; 

Browsers

Is this issue browser-specific? If so, please detail which browsers are impacted (e.g. IE 11, Safari). Chrome

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 26 (9 by maintainers)

Most upvoted comments

@arabelaa – I experienced this issue as well and after substantial troubleshooting came to realize that, depsite what this error was saying, the actual error was that the token redirect uri was not configured as a redirect uri in the AAD app registration (App Registrations --> Authentication --> Redirect URIs).

I would have expected the error to say the normal “the reply url is not valid” error, but instead received the exact error you mention. I wonder if checking that configuration resolves your issue? I experienced the issue the same way you did – initial login was fine and I am using redirect – the error only manifested after the auth expired and msal attempted to acquire a new token silently.

@sameerag – Any way to improve/correct this error response? Really tough to troubleshoot because it seems like a library issue when it was just a reply/redirect uri config issue in AAD.

@davidramos13 – That is where I had left off as well. You can use a tool like Fiddler to see what url is provided as the redirect uri (it will be a query string param in the request / response to login.microsoftonline.com. )

My solution is also using react-aad-msal, and following the best practice (https://www.npmjs.com/package/react-aad-msal#options) of using a blank html page for token refresh to prevent scripts from running amok while middleware was attempting the silent auth roundtrip. So, I have an ‘auth.html’ file in the public directory that is empty and use that as the tokenRefreshUri in options config for the auth provider. Then, added that to the redirect Uris in app registration (e.g. http://localhost:3000/auth.html). All worked as expected after that.

If that doesn’t solve your issue, send over your react-aad-msal auth provider config and if possible the redirect uri via fiddler/other tool, and I’ll see if I can help further!

Everyone: this error will be received when some kind of error occurs on the target acquire token silent page which is not handled by redirection. This thread is discussing only one possible reason for such an error, which is using an invalid reply URL. But you can encounter this for other errors as well, and here is how to debug them.

First, a simplified example which will induce this error:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>MSAL Bug</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js" class="pre"></script>
    <script src="https://alcdn.msauth.net/lib/1.2.0/js/msal.min.js"></script>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
</head>

<body>

    <script>
        'use strict';
        $(document).ready(function (e) {

            const msal = new Msal.UserAgentApplication({
                auth: {
                    clientId: 'a963b646-fa01-4c06-b302-42c6ed1b2774',
                    authority: 'https://login.microsoftonline.com/common'
                }
            });

            msal.handleRedirectCallback(function (error, response) {
                console.log('MSAL redirect callback: ', { error: error, response: response });
            });

            if (msal.isCallback(window.location.hash)) {
                return;
            }

            if (!msal.getAccount()) {
                msal.loginRedirect({
                    scopes: ['openid'],
                    prompt: 'select_account'
                });
                return;
            }

            msal.acquireTokenSilent({ scopes: ['openid', 'test/test'] })
                .then(console.log.bind(console))
                .catch(console.error.bind(console));
        });
    </script>

</body>

</html>

Notice the bogus scope of “test/test”? If you run above code, you will see this in the developer console:

Navigated to https://localhost:3000/

Unsafe JavaScript attempt to initiate navigation for frame with origin 'https://localhost:3000' from frame with URL '[REDACTED]'. 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.

Uncaught DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to '[REDACTED]'.

If you manually browse to the link articulated in that developer console window, you will see a better description of the error:

Sign in
Sorry, but we’re having trouble signing you in.

AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope openid test/test profile is not valid. The scope format is invalid. Scope must be in a valid URI form <https://example/scope> or a valid Guid <guid/scope>.

Above process can be used to debug why you are seeing this behavior. In this case, it was the use of a spurious scope value used in the request. The AAD authorization page is attempting to redirect the host page to render a description of the error to the user. Note in this case, I would consider this to be a bug with the AAD authorization page, since this error should just be redirect like other errors back to the target application for it to render the problem to the user (if running in a iframe). Because the authorization page can be used with user redirection, when the page is not loaded in a iframe, it can perhaps continue with the current behavior.

Thanks @thisisbrianstewart for your contribution in detailing these error types for the community.

To generalize these class of errors and why msal js cannot handle them better, I will try to summarize the root cause and discuss current/future mitigations:

  • implicit flow authorization grant’s security relies on the fact that the set of redirect uris registered during app creation/elsewhere are accessed independently by the AAD service. Once any authorization application (in this case msal js) requests a token with implicit flow, the service validates the URI and redirects the response to that URI.

  • Errors that happen before the redirect URI validation or due to an invalid redirect URI, . The service cannot redirect in this case and displays an error message in the frame/page it is loaded. For silent use cases, since it is handled in a hidden iframe, the user cannot see the message. Sincemsal js monitors the iframe for a hash, in this use cases, it handles the error by timing out and displaying an error message which contains the URL, giving the user a choice to click it and find out the error message. For non-silent cases, the user should have a window that displays the error. I understand that this use case is tricky as the user may be programmatically expecting an error type and msal js needs to improve here.

  • All these happen for any reason AAD cannot respond with an error-code to the hidden iframe; invalid URIs, or errors like sending prompt=? twice etc.

Current mitigation:

  • Please click the failed URI detailed in the error messaging in all use cases

Future action plan from our end to lessen this confusion:

  • Document these use cases better, I already tagged this as a documentation issue and we will try to add as much detail as we can in the wiki soon.
  • Better messaging for silent/interactive cases where the user understands he should click on the URI

Some use cases do not see a time out (as inferred from above) and only the iframe blocking allow-top-navigation. I will work next week to reproduce this issue and improve the messaging for these use cases too.

@thisisbrianstewart @arabelaa Yes. Short answer: We have a way to help users get a better error messaging already. I am trying to create a FAQ section on how we communicate these types of errors, will update the link here soon.

Hi @don1989 – answering the questions you’ve asked below, but in general, you will need to setup the Azure AD App Registration to have both http://localhost:3000/auth.html and http://localhost:3000 as Redirect URIs. The silent token refresh loads an iframe using that empty auth.html file, and that same auth.html file needs to receive the response back, so the acquire token silent flow provides the /auth.html endpoint as the redirect uri. This is different from the user-facing flow because there is no iframe that the middleware loads into the page, redirecting back to auth.html will not hook into react or msal and auth would halt – it must redirect back to your react app in the user-facing flow. More details and responses below.

Just to clarify, are we also meant to add the /auth.html to the redirectUri in the code too? You should leave this as is, without adding /auth.html. The redirect for a user login needs to redirect back to your react app so that the response is received by the msal middleware configured.

In the Azure AD portal, should the URLs contain /auth.html (or /auth without .html)? As noted above, you will need both http://localhost:3000 and http://localhost:3000/auth.html. When a user authenticates, they will flow through the auth mechanism that provides http://localhost:3000 as the redirect uri. Since you’ve added auth.html and configured tokenRefreshUri to use that, the silent auth will flow through the auth mechanism that provides http://localhost:3000/auth.html as the redirect uri. So, both need to be setup as redirect URIs in Azure AD.

Here is my config if that is a helpful reference.

image

import { MsalAuthProvider, LoginType } from 'react-aad-msal';
import '../config';
 
const config = {
  auth: global.AUTH,
  cache: {
    cacheLocation: "localStorage",
    storeAuthStateInCookie: true
  }
};
 
const authenticationParameters = {
  scopes: global.SCOPES
}

const options = {
  loginType: LoginType.Redirect,
  tokenRefreshUri: window.location.origin + '/auth.html'
};

export const AuthService = new MsalAuthProvider(config, authenticationParameters, options)

Adding Implicit Grant flow and using the correct reply uri fixed the issue for me. I now use the readt-aad-msal recommendation about a separate empty auth.html file for my redirectUri and tokenRefreshUri. Thank you guys for quick answers.

yeah thanks! i just found it was because of that, i needed to add https://localhost:3000/auth.html

Awesome @thisisbrianstewart thanks a lot for your assistance and taking your time out to explain so thoroughly! It is very much appreciated! 😃