-
Notifications
You must be signed in to change notification settings - Fork 372
FAQs
Adal uses iframes to renew tokens silently in the background. AAD returns the token back to the redirect_uri
specified in the token request (this redirect_uri
must be registered with AAD). Since the response is a 302, it results in the html corresponding to the redirect_uri
getting loaded in the iframe. Usually, it's the app's root/default page. This causes an app's reload. In other cases, if the app's root page requires authentication, it might lead to nested iframes or xframe deny error.
Since, adal cannot cancel the 302 issued by AAD, it cannot prevent the redirect_uri
from getting loaded in the iframe. But, there are workarounds for this that one can use to avoid the entire app reloading again or other errors caused because of this:
-
Specify a different html for the iframe:
Set
redirect_uri
property on config to a simple page, that does not require authentication. You have to make sure that it matches with theredirect_uri
registered in AAD portal. This will not affect user's login experience as Adal saves the start page when user begins the login process and redirects back to the exact location after login is completed.Please look at the gist for an example of template html you can use. You will need to make some modifications to the html for it to work with your specific app: https://gist.github.com/tushargupta51/5fa6d000357120adbc8fd1d5c68853c4
-
Conditional initialization in your main app.js file: If your app is structured similar to our sample single-page app where there is one central Javascript file (app.js in the sample) that defines the app's initialization, routing and other stuff, you can use an if...else based on whether the app is loading in an iframe or not. Something like this: https://gist.github.com/tushargupta51/78ce0b6bce998f6851abd02d91eb3a95
There could be multiple reasons for the infinite loop. I am detailing below the known causes:
- If using ui-router: Most common cause of running into infinite loops when using ui-router is state transition error. The root causes are documented here #2238(summary version) and #600. One-line explanation of this is missing state definition for root page "/". Add this to your state provider routing:
$stateProvider.state("/", {
url: "/",
templateUrl: <could be home page or default page",
requireADLogin: true,
});
- Nested iframe creation: if an iframe is creating another iframe, this could lead to a loop where adal keeps sending token renewal requests. Please see this answer for more details.
- Hash reset: Adal used to do reset the hash in the response sent from AAD in the locationChangeStart event. This sometimes was leading to multiple location change events and also app reload at times. This hash reset was removed in 1.0.11. Please use this version if none of the above solutions work for you.
The root cause for this is same as Q1. Please try one of the solutions suggested in the answer.
The root cause for this is same as Q1. Please try one of the solutions suggested in the answer.
Adal uses a displayCall function which is a property of the config object which when set, is used to accomplish user defined way of handling the navigation during the login process. The displayCall function opens a popup window and sets it location to the authorization endpoint in Azure AD. It then sets up a timer that periodically checks if the pop up page URL matches the Redirect URL, which will happen in the case of login success/failure. Upon successful authentication, the popup will be redirected to your Redirect/Reply URL and an id token will be passed along in the hash of the URL. Once the popup redirects back to the Redirect URL, we copy the hash of the popup window and move it to the hash of the main browser window. We then call the Adal's handleWindowCallback method to extract the hash from the main window and close the pop up window. For all this to work, the Redirect/Reply URL of the your application registered in Azure AD should match the redirectUri property of the config object. Below are code snippets, you can add to the config object of your apps using plain Adal or Adal-angular:
- Code snippet for apps using plain Adal:
window.config = {
redirectUri:'https://localhost:44302/loginHandler.html',//to avoid app reload inside the popup
displayCall: function (urlNavigate) {
var popupWindow = window.open(urlNavigate, "login", 'width=483, height=600');
if (popupWindow && popupWindow.focus)
popupWindow.focus();
var registeredRedirectUri = this.redirectUri;
var pollTimer = window.setInterval(function () {
if (!popupWindow || popupWindow.closed || popupWindow.closed === undefined) {
window.clearInterval(pollTimer);
}
try {
if (popupWindow.document.URL.indexOf(registeredRedirectUri) != -1) {
window.clearInterval(pollTimer);
window.location.hash = popupWindow.location.hash;
authContext.handleWindowCallback();
popupWindow.close();
}
} catch (e) {
}
}, 20);
}
};
- Code snippet for apps using Adal-angular:
adalProvider.init(
{
redirectUri:'https://localhost:44302/loginHandler.html',//to avoid app reload inside the popup displayCall: function (urlNavigate) {
var popupWindow = window.open(urlNavigate, "login", 'width=483, height=600');
if (popupWindow && popupWindow.focus)
popupWindow.focus();
var registeredRedirectUri = this.redirectUri;
var pollTimer = window.setInterval(function () {
if (!popupWindow || popupWindow.closed || popupWindow.closed === undefined) {
window.clearInterval(pollTimer);
}
try {
if (popupWindow.document.URL.indexOf(registeredRedirectUri) != -1) {
window.clearInterval(pollTimer);
window.location.hash = popupWindow.location.hash;
popupWindow.close();
}
} catch (e) {
}
}, 20);
}
},
$httpProvider
);
One thing to note is that the Redirect URL is set to the app's root page by default. This leads to the app being reloaded in the popup. To prevent this, you need to create an empty html page in your application and set the Redirect URL of the app in Azure AD and the redirectUri property of the config object to an empty html page('https://localhost:44302/loginHandler.html') as shown in the code snippet.