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

Msal Js Supports Iframe In Iframe scenarios #899

Closed
5 of 6 tasks
DarylThayil opened this issue Jul 31, 2019 · 37 comments
Closed
5 of 6 tasks

Msal Js Supports Iframe In Iframe scenarios #899

DarylThayil opened this issue Jul 31, 2019 · 37 comments
Assignees
Labels
feature Feature requests. internal Issues created by MSAL.js team for internal tracking.

Comments

@DarylThayil
Copy link
Contributor

DarylThayil commented Jul 31, 2019

As it currently stands msal js blocks certain scenarios when rendered inside of an iframe because there are edge case scenarios that can not be supported.

The goal is to unblock these so that it can be supported.

Linking all the relevant PRs for this ask:

Beta release
Released msal@1.2.0-beta.0 here

Next beta release contents

@mozart27
Copy link

What's the time-frame for this to be available for us?

@NickSevens
Copy link

@mozart27 they mention end of September here. Hope they hold up to it 😄

@DarylThayil
Copy link
Contributor Author

We are on track to deliver at end of September! We have some beta versions being tested with customers. Please let us know If you would like to test some betas with us! @sameerag

@yuriys-kentico
Copy link

Hi @DarylThayil, what would it take for me to use a beta version that supports this? I want to see if my use case applies.

@AndrewCraswell
Copy link
Contributor

Would this unblock the scenarios where MSAL authentication in Teams apps breaks? If I recall Teams renders tab app inside an iframe so there were authentication issues trying to use MSAL...

@sameerag
Copy link
Member

@AndrewCraswell Teams app's requirements have some specific restrictions on the iframe applications, we are in internal discussions with them. Our solution is generic, and ideally should work but your specific scenario may need some fine tuning from the "Teams" app too.

@sameerag
Copy link
Member

@yuriys-kentico Can you please expand on your scenario? If you do not want to do it in public, you can reach me by email at sameera.gajjarapu@microsoft.com. I can share the internal beta build. We are planning a public beta in a week or so, currently it is being tested internally.

@yuriys-kentico
Copy link

@sameerag The scenario is slightly complicated. We have one product called Kentico and another product called Kentico Kontent. The first product is an on-premise installation that is highly customizable but occasionally needs to be inspected locally by us after communication with the customer. Since there is also a database, the complete backups usually run a few gigabytes. Traditionally, we have used FTP to transfer these backups to us. This process has problems.

We are now developing a microservice infrastructure to replace the FTP process. The first phase of this infrastructure is a browser-based frontend that allows a backup to be uploaded or downloaded through a browser. Each backup request is created in Kentico Kontent using an internal project. The Kontent workflow needs to be customized for this scenario since the infrastructure depends on secure URLs for each backup request. The Kontent interface allows for customization through what we call custom elements. These elements sit inside iframes and are hosted externally. Since it is hosted externally and uses JavaScript, it is a good idea to add some kind of authentication. I want to do this authentication using the beta version to see how it interacts with the iframe.

@sameerag
Copy link
Member

sameerag commented Sep 16, 2019

@yuriys-kentico Can we set up a call?

  • For popups for interaction and silent calls for tokens, the beta we have works as expected. That is all your interactions (consent/credential entry) within the iframe are through popup calls - loginPopup() and acquireTokenPopup(), token acquisition in non-interactive usecases is through acquireTokenSilent().

  • For redirect flows, we have a little song and dance going with the top frame as iframes are blocked from interactions by the STS. If your usecase needs those APIs (loginRedirect() and acquireTokenRedirect()), we have a new beta coming up this week and I can help with the directions to test the same.

I would like to discuss the specifics before we put together the release notes for everyone if you want to help us with testing the same.

@yuriys-kentico
Copy link

@sameerag sure, I'll send you an email.

@keystroke
Copy link

@sameerag I'm using MSAL.js version 1.1.2 and I hosted my MSAL SPA inside the Azure Portal to test if it would work (embedded in an iframe and side-loaded). I can see that the page loads fine, and I can successfully call loginpop and authenticate! However, when I call "acquireTokenSilent" I don't see any outgoing calls or errors generated, it returns a promise that seems to never resolve. No errors in the developer console, within the iframe or in the top frame. Any idea what is going on? If I instead call "acquiretokenpopup" then it works successfully! So something funky going on with the acquire token silent implementation; what could cause the promise "deadlock"? Why is there no error thrown or logged?

@sameerag
Copy link
Member

@keystroke 1.1.2 does not resolve promises in silent calls. There is a decorator that restricts this in the code. This ticket(which has a bunch of PRs listed in the description) is an effort to remove that restriction in msal js and allow apps in iframes to resolve tokens.

However identity places some restrictions on interactions on an iframe, hence we have certain conditions placed on redirect flows where there is no popup to fall back. Please watch out for the next beta release or you can ping me to try out an internal beta we are testing out right now if you want to early test this.

Hope this clarifies.

@keystroke
Copy link

@sameerag I was able to work around the current behavior with below code snippet:

const key = request.authority + options.scope;
if (!this.HACK[key]) this.HACK[key] = msal.acquireTokenPopup(request);
return await this.HACK[key];

I tried above code to replace old pattern shown below for now and verified this works, though it will generate a popup which automatically closes in the scenarios where silent token acquisition would work. THIS IS NOT PRODUCTION CODE DON'T WORRY ;)

const request = { authority: this.authority(), scopes: [options.scope] };
try {
    const silentResponse = await msal.acquireTokenSilent(request);
    return silentResponse;
} catch (error) {
    if (error.name === 'InteractionRequiredAuthError') {
        console.log(error);
        const interactiveResponse = await msal.acquireTokenPopup(request);
        return interactiveResponse;
    }
    console.error(error);
    throw error;
}

I am only working with MSAL.js for proof-of-concept right now, good to know there is already beta version that will enable these scenarios :)

Do you folks support any use of MSAL.js directly in the Azure Portal for Ibiza Extensions? Curious if you've explored this scenario at all. I noticed the Azure Portal exposes an "OAuthButton" control that also launches a popup to handle user login flows: https://ms.portal.azure.com/?Microsoft_Azure_Playground=true#blade/Microsoft_Azure_Playground/ControlsIndexBlade/OAuthButton_create_Playground

@sameerag
Copy link
Member

We haven't. Would need some time to check this scenario and if we can support it. Can I reach out may be in a week once we stabilize our beta release? @DarylThayil FYI for the scenario.

@keystroke
Copy link

@sameerag @DarylThayil Thanks! Some more info as FYI below on integrating with the Azure Portal (please note I'm not actually on their team or anything, nor am I a proper front-end dev, I've just been hacking this stuff together for Azure Stack).

Looking through Ibiza docs, they have a "frame control" where you can host an external page in an iframe: https://ms.portal.azure.com/?Microsoft_Azure_Playground=true#blade/Microsoft_Azure_Playground/ControlsIndexBlade/FrameControl_create_Playground

They include this example for how to host the page, this is what I used

import * as FrameControl from "Fx/Controls/FrameControl";

const myFrameControl = FrameControl.create(container,
{
    onReceiveMessage: (message: any) => {
        // Handle message from the iframe.
        switch(message.messageType) {
            // This is an example of how to listen for messages from your iframe.
            case 2:
                MsPortalFx.Hubs.Notifications.ClientNotification.publish({
                    title: "FrameControl",
                    description: message.data,
                    status: MsPortalFx.Hubs.Notifications.NotificationStatus.Information,
                });
                break;
            default:
                break;
        }
    },
        
    src: "https://playground.hosting.portal.azure.net/playground/Content/5.0.302.481011398.190913-0124/framecontrolpage.html",
});

I was able to host a "hello world" extension locally on my dev box and "side-load" it into the Azure Portal and host a SPA using the msal.js (modifying the src property above). Something like this is probably a decent way to test support for MSAL in iframes in a "real world" app. Note that I only tested the popup flows, not the redirect flows.

@eirikb
Copy link

eirikb commented Sep 21, 2019

Would acquireTokenSilent ever work from an iframe? Isn't that technically impossible because of things like X-Frame-Options: deny (which should be set to prevent clickjacking)?

@sameerag
Copy link
Member

@eirikb For acquireTokenSilent msal js spins off a hidden iframe and as long as no interaction is needed (SSO when you already have a session with the STS, it is supported in iframes.

X-Frame-Options: deny is set and the setting blocks interactive flows on the same frame -> which translates to acquireTokenRedirect and loginRedirect not working the classic way. We came up with a trust model with the parent app (which is top frame and full window) to support these usecases for certain app models.

In the coming weeks, we plan to release beta versions supporting these changes with a detailed blog post. Hope this clarifies.

@sameerag
Copy link
Member

@keystroke There was never any restriction on Popups for iframed applications. The restrictions were only for acquireTokenSilent and redirect flows though not restricted from MSAL JS would not work for reasons mentioned above.

Please reach out to me on teams, if you are willing to test out early builds for these scenarios, any testing is appreciated :-)

@NickSevens
Copy link

@sameerag does this beta you're talking about have any relation to https://youtu.be/xLjT1Hw5a1E?t=1472 ?

@sameerag
Copy link
Member

UPDATE
#939 is merged to dev today. Working on stabilizing #980 and #994 today to release the first beta npm release publicly.

@sameerag
Copy link
Member

sameerag commented Sep 26, 2019

Released msal@1.2.0-beta.0 here. Please note that the CDN for this beta is not yet released and will be available early next week.

We are working on releasing a follow up beta for the remaining use cases mentioned in the description.

@sameerag
Copy link
Member

sameerag commented Oct 5, 2019

UPDATE:
#975 and #1010 in the final leg of testing.

@sameerag
Copy link
Member

UPDATE:
Added #1042 to handle cache cleanup in error cases.

@sameerag
Copy link
Member

Released couples of betas now with all the changes, latest beta being msal 1.2.0-beta.2. Gearing up for the release of msal 1.2.0 with samples and documentation.

Note: The betas are available in npm, we will be making the CDN release for the latest beta soon, and then follow up with the wiki update on the release notes.

@CalamityLorenzo
Copy link

Is there to be a scenario for Microsoft Teams and MSAL? (Which Is an Iframe, on iframe with an Iframe?)
I can get the current beta to work with Teams in a browser, but not the actual Teams app itself, I am unable to complete login via pop-up or msteams.authenitcation + re-direct.

@sameerag
Copy link
Member

sameerag commented Dec 4, 2019

UPDATE:

To facilitate feedback from various teams, we have been releasing betas for the last 2 months and currently at msal 1.2.0-beta.4. The final PR needed for cache cleanup is merged this week to dev and we are releasing msal 1.2.0-beta.5 today. There will be a msal 1.2.0 released later this week which will be the same as msal 1.2.0-beta.5.

@jmckennon jmckennon added the internal Issues created by MSAL.js team for internal tracking. label Dec 4, 2019
@aappddeevv
Copy link

Is there something we need to do to activate this capability. I'm on 1.2.0-beta.5 but when I run the process of acquiring a token via acquireTokenSilent but that fails with the error ClientAuthError: Token calls are blocked in hidden iframes still. Are these changes suppose to allow acquireTokenSilent to work correctly?

I'm on chrome.

@sameerag
Copy link
Member

sameerag commented Dec 8, 2019

@aappddeevv This is expected. Please check the beta release notes here. You can either:

  1. Choose to ignore this error
  2. Set a blank page or any page without scripts running as the redirectUri for acquireTokenSilent() calls.

msal@1.2.0 will be released soon (which is technically same content as msal@1.2.0-beta.5) with sample code for option 2.

@aappddeevv
Copy link

Thanks. I had read a bunch of those notes but did not understand that option (1) was available. I assume (1) means ignore the error but it is still working all Ok.

@sameerag
Copy link
Member

sameerag commented Dec 8, 2019

@aappddeevv yes, your understanding is correct. We will try to get this message across board in the release notes for msal@1.2.0. Thank you for the quick testing and feedback.

@aappddeevv
Copy link

I must admit, I still can't get this library to work consistently on its own sometimes.

I am trying to get an idtoken first then an access token. I do not provide any scopes to my loginRedirect() request so that only openid and profile are sent. The request goes out but when I try to get a token (acquireTokenSilent) the cookie is not set and I get a AADSTS50058: A silent sign-in request was sent but no user is signed in... error from the authorize endpoint.

  • If I set a minimal scope, such as "user.read" I do not get this error.
  • If I set a minimal scope, with a custom scope, "api:///user", I do not get this error but I'm not logged in as there is a msal.error in storage with message "login_required.". The "my app" (not graph) token for my app resource will not validate with passport-azure-ad. The authorize request for my api custom scope returns "302".

@jasonnutter
Copy link
Contributor

@aappddeevv If this isn't specific to iframe-in-iframe, can you please open a separate issue with your questions? Thanks!

@aappddeevv
Copy link

I can do that, but I I thought it was due to the use of "redirect" which runs in an embedded iframe vs "popup".

@jasonnutter
Copy link
Contributor

@aappddeevv Currently, applications running inside an embedded iframe will not be able to use loginRedirect, as the AAD login UI cannot be shown in an iframe. We're working on a long-term solution for this, but for now, you will need to use popup methods when MSAL is running inside an iframe.

@aappddeevv
Copy link

Hmm..perhaps I am on the wrong issue then. I'm not able to get redirect methods to work in the toplevel iframe. My app is not in an embedded iframe. I'll keep playing with this issue and see if its pilot error. Thanks.

@jasonnutter
Copy link
Contributor

@aappddeevv Ah, yes if you need help with an application running in the top frame, please open a new issue, thanks!

@sameerag
Copy link
Member

msal@1.2.0 released.

  • Please check the release in npm; CDN release will be coming soon; mostly today.
  • Please read the release blog and the changelog for the feature/fixes summary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature Feature requests. internal Issues created by MSAL.js team for internal tracking.
Projects
None yet
Development

No branches or pull requests