Skip to content

Instantly share code, notes, and snippets.

@tushargupta51
Last active February 24, 2021 04:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tushargupta51/5fa6d000357120adbc8fd1d5c68853c4 to your computer and use it in GitHub Desktop.
Save tushargupta51/5fa6d000357120adbc8fd1d5c68853c4 to your computer and use it in GitHub Desktop.
App reloading inside iFrame when renewing token - Solution 2
'use strict';
angular.module('todoApp', ['ngRoute','AdalAngular'])
.config(['$routeProvider', '$httpProvider', 'adalAuthenticationServiceProvider', function ($routeProvider, $httpProvider, adalProvider) {
$routeProvider.when("/Home", {
controller: "homeCtrl",
templateUrl: "/App/Views/Home.html",
}).when("/TodoList", {
controller: "todoListCtrl",
templateUrl: "/App/Views/TodoList.html",
requireADLogin: true,
}).when("/UserData", {
controller: "userDataCtrl",
templateUrl: "/App/Views/UserData.html",
}).otherwise({ redirectTo: "/Home" });
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'Enter your tenant name here e.g. contoso.onmicrosoft.com',
clientId: 'Enter your client ID here e.g. e9a5a8b6-8af7-4719-9821-0deef255f68e',
redirectUri: 'Enter the url where your special html for iframe is located e.g. https://localhost:12345/frameRedirect.html'
//cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
},
$httpProvider
);
}]);
<html ng-app="todoApp">
<body>
<script src="<local path to angular.js>"></script>
<script src="<local path to adal.js>"></script>
<script src="<local path to adal-angular.js>"></script>
<script type="text/javascript">
angular.module('todoApp', ['AdalAngular'])
.config(['$httpProvider', 'adalAuthenticationServiceProvider', function ($httpProvider, adalProvider) {
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'Enter your tenant name here e.g. contoso.onmicrosoft.com',
clientId: 'Enter your client ID here e.g. e9a5a8b6-8af7-4719-9821-0deef255f68e',
redirectUri: 'Enter the url where your special html for iframe is located e.g. https://localhost:12345/frameRedirect.html'
//cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
},
$httpProvider
);
}]);
// Copy over the event listeners for loginSuccess, loginFailure and stateMismatch from main app.js
</script>
</body>
</html>
@tushargupta51
Copy link
Author

tushargupta51 commented Jun 24, 2016

NOTE: This solution requires 1.0.11 or later versions of adal js to work.

One requirement to use this is that the path to frameRedirect.html should not use client routing e.g. https://locahost:12345/#/frame. The "#" will kick in the angular routing and will load the route corresponding to "frame". As this will load the index.html and all the scripts included inside (which could be your entire app), you will run into the sample problem of app reloading inside the iframe.

Another solution is described here: https://gist.github.com/tushargupta51/78ce0b6bce998f6851abd02d91eb3a95

@tushargupta51
Copy link
Author

When configuring the frameRedirect.html, please copy over the following from your main app.js configuration:

  1. Adal initialization config
  2. Event listeners: listeners for loginSuccess, loginFailure, stateMismatch.

@Tsunade90
Copy link

Tsunade90 commented Aug 8, 2016

Hello @tushargupta51,
That solution solved my reloads issue but leads to another issue:
when the token has expired, my website doesn't load at all. I turned on the adal verbose logs and got this:

app.js:20 Mon, 08 Aug 2016 08:44:36 GMT:1.0.11-INFO: Add adal frame to document:adalIdTokenFrame
app.js:20 Mon, 08 Aug 2016 08:44:36 GMT:1.0.11-INFO: LoadFrame: adalIdTokenFrame
app.js:20 Mon, 08 Aug 2016 08:44:36 GMT:1.0.11-INFO: Add adal frame to document:adalRenewFramehttps://mysp.sharepoint.com
app.js:20 Mon, 08 Aug 2016 08:44:36 GMT:1.0.11-INFO: LoadFrame: adalRenewFramehttps://mysp.sharepoint.com
app.js:20 Mon, 08 Aug 2016 08:44:37 GMT:1.0.11-INFO: Add adal frame to document:adalIdTokenFrame
app.js:20 Mon, 08 Aug 2016 08:44:37 GMT:1.0.11-INFO: Add adal frame to document:adalRenewFramehttps://mysp.sharepoint.com
4app.js:20 Mon, 08 Aug 2016 08:44:37 GMT:1.0.11-ERROR: Error when acquiring token for resource: https://mysp.sharepoint.com
stack:
undefined

When setting a breakpoint on adal-angular.js's "acquireToken" function, I get more detail about the azur error:

AADSTS50058: A silent sign-in request was sent but no user is signed in. The cookies used to represent the user's session were not sent in the request to Azure AD. This can happen if the user is using Internet Explorer or Edge, and the web app sending the silent sign-in request is in different IE security zone than the Azure AD endpoint (login.microsoftonline.com).
Trace ID: c6326161-8b80-4bd2-a5cb-e81dca2247de
Correlation ID: 6a838b71-33a3-4e71-8555-bea2cd00e3c6
Timestamp: 2016-08-08 09:11:18Z

The error appears in all the browsers.
I have to clear my cache and cookies to make it work so the issue affects only the token renewal.
Our app is already on stage at our customer so it's pretty urgent for us to solve it.

Thank you very much

Update:
I saw that post AzureAD/azure-activedirectory-library-for-js#323
So I added this piece of code:

        if (adalAuthenticationService.getCachedToken(clientId) === null) {
            adalAuthenticationService.login();
        }

Which works with localhost but not on stage with minified code, the page stays stuck on frameRedirect.html:
http://mysite.azurewebsites.net/frameRedirect.html#/id_token=eyJ0eXAiOiJKV1Q[...]

@GuiguiMtl
Copy link

I am having the same issues as above. With this option the application is stucked on /frameredirect.html#!#id_token.... Any ideas ?

@ShahnavazKazi
Copy link

ShahnavazKazi commented May 8, 2018

Hi @tushargupta51, I am facing the same issue and the redirection is stucked at http://mysite.com/frameRedirect.html#/default and adal.login.error in localstorage says "Nonce is not same as undefined".

Can you please help?

@balbany
Copy link

balbany commented May 22, 2018

@shahnavasKazi, here's the solution I came up with:

From frameRedirect.html, redirect again back to the root of the web app (or where-ever your SPA is hosted), preserving the hash, ONLY if the frame redirect page isn't loaded in an iFrame (otherwise handleWindowCallback will just work it's magic).

No more double-loading of SPA. Example frameRedirect.html below.

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Frame Redirect</title>
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.17/js/adal.min.js"></script>
</head>
<body>
<script>
  var adalConfig = {
    clientId: "guid-goes-here"
  };
  var authContext = new AuthenticationContext(adalConfig);
  authContext.handleWindowCallback();

  if (window === window.parent) { window.location.replace(location.origin + location.hash); }
</script>
</body>
</html>

@MarkLeMerise
Copy link

MarkLeMerise commented Apr 10, 2019

For anyone who comes across this gist, @balbany's frameRedirect.html sample was the winning solution for me as well. I've done a ton of Googling on this issue, and haven't found a sanctioned "best practice" from Microsoft, or anyone really. Since they've disallowed wildcards in reply URLs (which is the traditional way I've seen on other platforms' APIs expose to allow navigating anywhere into an app on a particular domain) as well the the oauth2AllowUrlPathMatching option in Azure AD configuration, that seems to strongly imply a client-side solution.

In my particular use case, I'm running a React application with react-adal in the index.html file and added this frameRedirect.html to my SPA output bundle. It Works!™

Thanks for taking the time to share your solution, @balbany.

@vcs38
Copy link

vcs38 commented Jun 29, 2019

I'm trying to use this solution but I get this error
adal.min.js:2 Uncaught TypeError: Cannot read property 'getRequestInfo' of null at AuthenticationContext.handleWindowCallback (adal.min.js:2) at test.html:14 AuthenticationContext.handleWindowCallback @ adal.min.js:2 (anonymous) @ test.html:14

What am I doing wrong ?

here is the configuration of the module
MsalModule.forRoot({ clientID: 'my-app-id', loadFrameTimeout: 20000, redirectUri: 'http://localhost:4200/assets/html/test.html', }),

I've copied-pasted the frameredirect.html ode and pasted it in a separate html file (test.html) in assets/html/

@chetanc97
Copy link

@balbany : That worked fine . Thanks!

@vbutani
Copy link

vbutani commented Jul 29, 2019

@MarkLeMerise or someone please share some code snippet for react-adal solution. I am facing the app reload issue by using React with server side rendering. Thanks.

@MarkLeMerise
Copy link

MarkLeMerise commented Jul 30, 2019

@vbutani, I can't speak for SSR, but @balbany's answer is what worked for me. Copy the frameRedirect.html file (substitute in your own client ID) into your code base. Configure Azure AD to redirect to that file.

@camilogiraldo
Copy link

For those that might face this issue using angular 2, here's the additional steps to make @balbany solution work.

https://gist.github.com/camilogiraldo/d29f66f4509eb3fcdaad7f543a94ca46

@ChristopherHButler
Copy link

@MarkLeMerise Can I ask where in your project you added this file? I also have a react project but not sure where to add the frameRedirect.html file. Any tips would be greatly appreciated!

@Wizardcraft1
Copy link

I would encourage people here to upvote @balbany solution so that others find it easy to check out the comment.

@MarkLeMerise
Copy link

@ChristopherHButler, I've distilled the setup in my app into its own Gist. Hopefully, it helps.

You'll see the files, how they interact, and what you need in your Azure AD setup. In addition, I included a screenshot of my dist directory. When deployed, the index.html and redirect.html files exist as siblings.

@avis2311
Copy link

avis2311 commented Feb 24, 2021

@balbany/@tushargupta51 - authContext.handleWindowCallback(); throws uncaught DOMException - Blocked a frame with origin '' from accessing a cross origin. Any idea on this issue ? I know its too late.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment