AzureAD / azure-activedirectory-library-for-js

The code for ADAL.js and ADAL Angular has been moved to the MSAL.js repo. Please open any issues or PRs at the link below.
https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/maintenance/adal-angular
Apache License 2.0
627 stars 372 forks source link

Page reloads 3 or 4 times after log-in #151

Closed drGarbinsky closed 8 years ago

drGarbinsky commented 9 years ago

There is a strange issue that looks similar to other posted issues but can't quite figure it out. After logging in and being redirected back to the app the page loads 3 or 4 times in a row. After that everything works great. It appears to be triggered by the first call to a protected endpoint via $http.

I have an API on a different URL with CORS configured and oauth2AllowImplicitFlow set to true. The general structure of the app is based on the SinglePageApp-WebAPI-AngularJS-DotNet sample.

I posted a issue on stackoverflow with more detail.

I've been fighting this for a while and would really appreciate any help or troubleshooting guidance.

weijjia commented 9 years ago

I'm looking into the issue, and trying to reproduce it on my side.

drGarbinsky commented 9 years ago

Appreciate any help. Thanks. Let me know if more details are needed.

weijjia commented 9 years ago

Did you take the latest version? I'm playing with the SinglePageApp-WebAPI-AngularJS-DotNet sample, and I could not reproduce the problem by trying: 1) set the require AD to true for the route you want to access, which is triggered by the first call to a protected endpoint via $http 2) click on log in and then do the same thing.

If you could provide the detailed steps for reproducing, that will be great.

drGarbinsky commented 9 years ago

I did take the latest version. Those are the repro steps. I'll go back to a clean copy of the ToDo Spa App sample and see if I can reproduce it as well.

weijjia commented 9 years ago

Where is the repro steps? Did you forget to attach?

drGarbinsky commented 9 years ago

Sorry The ones that you listed are the basic repro steps: 1) Setup the app. 2) log into the app then do something to trigger a AJAX request to a protected endpoint.

drGarbinsky commented 9 years ago

I think I was able to repro the issue using the stock sample. Here are the specific repro steps I used.

  1. If logged in, log out of app.
  2. Set a breakpoint in the .config function within app.js (this is how I am measuring the behavior)
  3. Click "Login" in the upper right
  4. Log in
  5. Notice that the break point is hit once.
  6. Click on ToGo List link (uses a protected endpoint)
  7. .config is invoked again.

In my actual app .config is invoked 3 times. With each invocation several API calls are repeated causing a long initial load time for the user.

Let me know if you see the same behavior using the more specific repro steps.

weijjia commented 9 years ago

Thanks for the repro steps. I'll try to recreate on my side.

weijjia commented 9 years ago

For the sample, when clicking on ToGo List, it will call the acquireToken if no token stored in cache, and adal.js currently did a full redirect. This will cause .config to be invoked again.

drGarbinsky commented 9 years ago

is aquireToken called before adal:loginSuccess is triggered or only when a call to a protected endpoint is invoked?

I ask because I am only starting the ajax request when isAuthenticated is true or on adal:loginSuccess event.

if ($scope.userInfo.isAuthenticated) {
        userSvc.getMe();
    } else {
        $scope.$on("adal:loginSuccess", function () {
            userSvc.getMe();
        });
    }`
weijjia commented 9 years ago

acquireToken is used to get token for a given resources, it could be trigger in different conditions. A call to a protected endpoint could trigger it.

Actually, you could set requireADLogin to be true for the route you want to protect, and ADAL will start login and load the protect route. And then you can make your ajax request.

drGarbinsky commented 9 years ago

I have all of the routes configured as requireADLogin = true except for the postLogoutRedirect location. Are there any debugging tips that I can use to gather more specific data? I've pasted the console output below where you can see you can see the repeating cycle.

                DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
            File: authorize
            HTML1300: Navigation occurred.
            File: login
            HTML1200: microsoftonline.com is on the Internet Explorer Compatibility View List ('C:\Users\Micah\AppData\Local\Microsoft\Internet Explorer\IECompatData\iecompatdata.xml').
            File: login
            DOM7011: The code on this page disabled back and forward caching. For more information, see: http://go.microsoft.com/fwlink/?LinkID=291337
            File: authorize
            HTML1506: Unexpected token.
            File: localhost:44300, Line: 115, Column: 1
            The returned id_token is not parseable.
            The returned id_token is not parseable.
            State: 0edacc1d-a253-42ac-8a1d-cf1206ad3beb
            State status:true
            State is right
            renewToken is called for resource:https://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Renew token Expected state: ca98c6f9-7a16-4744-828f-351cffedec9b|https://cloudmedIdentity.onmicrosoft.com/dataApi
            Navigate url:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=ca98c6f9-7a16-4744-828f-351cffedec9b%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
            Navigate to:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=ca98c6f9-7a16-4744-828f-351cffedec9b%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2&prompt=none&login_hint=Test1%40cloudMedIdentity.onmicrosoft.com&domain_hint=cloudMedIdentity.onmicrosoft.com&nonce=220c7d60-d07a-449d-bbcf-dd4cd053365a
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            renewToken is called for resource:https://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Renew token Expected state: ca355b60-742a-48c2-8b8c-cd46a1b9b620|https://cloudmedIdentity.onmicrosoft.com/dataApi
            Navigate url:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=ca355b60-742a-48c2-8b8c-cd46a1b9b620%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
            Navigate to:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=ca355b60-742a-48c2-8b8c-cd46a1b9b620%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2&prompt=none&login_hint=Test1%40cloudMedIdentity.onmicrosoft.com&domain_hint=cloudMedIdentity.onmicrosoft.com&nonce=c204e5c3-9d07-42e3-9787-2e340935ab8c
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            renewToken is called for resource:https://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Renew token Expected state: fdc47862-650b-411b-b59f-98cbf13b5715|https://cloudmedIdentity.onmicrosoft.com/dataApi
            Navigate url:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=fdc47862-650b-411b-b59f-98cbf13b5715%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
            Navigate to:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=fdc47862-650b-411b-b59f-98cbf13b5715%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2&prompt=none&login_hint=Test1%40cloudMedIdentity.onmicrosoft.com&domain_hint=cloudMedIdentity.onmicrosoft.com&nonce=2f110029-8c7a-4584-aaae-b9a68284b3d9
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            renewToken is called for resource:https://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Renew token Expected state: 46dce352-c78b-453e-993d-7b43dbfee4c0|https://cloudmedIdentity.onmicrosoft.com/dataApi
            Navigate url:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=46dce352-c78b-453e-993d-7b43dbfee4c0%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
            Navigate to:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=46dce352-c78b-453e-993d-7b43dbfee4c0%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2&prompt=none&login_hint=Test1%40cloudMedIdentity.onmicrosoft.com&domain_hint=cloudMedIdentity.onmicrosoft.com&nonce=ef3226f4-0c07-4dff-ad99-36dde840f7ee
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            renewToken is called for resource:https://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Renew token Expected state: e392c56e-5298-41cf-9f0b-4f0bed985b3d|https://cloudmedIdentity.onmicrosoft.com/dataApi
            Navigate url:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=e392c56e-5298-41cf-9f0b-4f0bed985b3d%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
            Navigate to:https://login.microsoftonline.com/cloudMedIdentity.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=96408f66-4eab-4c44-8e59-eed93746bf8f&resource=https%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&redirect_uri=http%3A%2F%2Flocalhost%3A44300%2F&state=e392c56e-5298-41cf-9f0b-4f0bed985b3d%7Chttps%3A%2F%2FcloudmedIdentity.onmicrosoft.com%2FdataApi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2&prompt=none&login_hint=Test1%40cloudMedIdentity.onmicrosoft.com&domain_hint=cloudMedIdentity.onmicrosoft.com&nonce=c09911ac-c4ff-495f-b0a8-19931c82b902
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            State: ca98c6f9-7a16-4744-828f-351cffedec9b|https://cloudmedIdentity.onmicrosoft.com/dataApi
            State status:true
            State is right
            Fragment has access token
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            LoadFrame: adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            Add adal frame to document:adalRenewFramehttps://cloudmedIdentity.onmicrosoft.com/dataApi
            State: 46dce352-c78b-453e-993d-7b43dbfee4c0|https://cloudmedIdentity.onmicrosoft.com/dataApi
            State status:true
            State is right
            Fragment has access token
weijjia commented 9 years ago

Interesting. It looks like acquireToken is called multiple times for https://cloudmedIdentity.onmicrosoft.com/dataApi.

Is this the most recent logs you have? In the latest version, we start to log out the request type. I just want to make sure you did take the latest version, I saw some similar loop before, and we make a fix to it.

Another thing, could you set breakpoint on acquireToken in adal.js, and check when it's called?

drGarbinsky commented 9 years ago

Thanks for the effort so far, we're really stuck on this one. I'll take the tip from github and repro the issue and capture new logs as well as set the breakpoint on aquireToken.

drGarbinsky commented 9 years ago

I'm back at it after having to focus on some other priorities. I updated to 1.0.5 and reproduced the issue. I see the new logging messages regarding request type. I've also captured the call stack when aquireToken is called (3 times). Also update angular to the latest (1.4.4) Let me know if there is any other info I can gather or tests I can run to help pin this down.

here is the stack trace:

  AuthenticationContext.prototype.acquireToken [adal.js] Line 357     Script
  acquireToken [adal-angular.js] Line 223     Script
  request [adal-angular.js] Line 296     Script
  processQueue [angular.js] Line 14634     Script
  Anonymous function [angular.js] Line 14650     Script
  Scope.prototype.$eval [angular.js] Line 15916     Script
  Scope.prototype.$digest [angular.js] Line 15727     Script
  Scope.prototype.$apply [angular.js] Line 16024     Script
  bootstrapApply [angular.js] Line 1658     Script
  invoke [angular.js] Line 4473     Script
  doBootstrap [angular.js] Line 1656     Script
  bootstrap [angular.js] Line 1676     Script
  angularInit [angular.js] Line 1570     Script
  Anonymous function [angular.js] Line 28599     Script
  fire [jquery-2.1.4.js] Line 3099     Script
  self.fireWith [jquery-2.1.4.js] Line 3211     Script
  ready [jquery-2.1.4.js] Line 3417     Script
  completed [jquery-2.1.4.js] Line 3433     Script
  [Async Call]     
  jQuery.ready.promise [jquery-2.1.4.js] Line 3451     Script
  Anonymous function [jquery-2.1.4.js] Line 3461     Script
  Anonymous function [jquery-2.1.4.js] Line 34     Script
  Global code [jquery-2.1.4.js] Line 15     Script

Here are the log messages:

adal.js:975 The returned id_token is not parseable.
adal.js:975 The returned id_token is not parseable.
adal.js:975 State: 8f987284-b403-4931-802f-d54f1961bdf5
adal.js:975 State status:true
adal.js:975 State is right
adal.js:975 renewToken is called for resource:https://api.cloudmedsolutions.com/api
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 Renew token Expected state: 21ed0c20-f8d8-4c6b-ae72-4d9a3f9b0b59|https://api.cloudmedsolutions.com/api
adal.js:975 Navigate url:https://login.microsoftonline.com/cmdevapps.onmicrosoft.com/oauth2/authoriz…2Fapi.cloudmedsolutions.com%2Fapi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
adal.js:975 Navigate to:https://login.microsoftonline.com/cmdevapps.onmicrosoft.com/oauth2/authoriz…main_hint=cloudmedsolutions.com&nonce=4b2e9b12-03b0-4042-b40f-abd4b56a9504
adal.js:975 LoadFrame: adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 LoadFrame: adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 renewToken is called for resource:https://api.cloudmedsolutions.com/api
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 Renew token Expected state: 2726ff21-6909-478d-8a1f-a2ab90e25dd7|https://api.cloudmedsolutions.com/api
adal.js:975 Navigate url:https://login.microsoftonline.com/cmdevapps.onmicrosoft.com/oauth2/authoriz…2Fapi.cloudmedsolutions.com%2Fapi&nux=1&x-client-SKU=Js&x-client-Ver=1.0.2
adal.js:975 Navigate to:https://login.microsoftonline.com/cmdevapps.onmicrosoft.com/oauth2/authoriz…main_hint=cloudmedsolutions.com&nonce=ca68303a-a320-453a-8840-ca16514e4ba0
adal.js:975 LoadFrame: adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 State: 21ed0c20-f8d8-4c6b-ae72-4d9a3f9b0b59|https://api.cloudmedsolutions.com/api
adal.js:975 State status:true
adal.js:975 State is right
adal.js:975 Fragment has access token
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 LoadFrame: adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 Add adal frame to document:adalRenewFramehttps://api.cloudmedsolutions.com/api
adal.js:975 State: 2726ff21-6909-478d-8a1f-a2ab90e25dd7|https://api.cloudmedsolutions.com/api
adal.js:975 State status:true
adal.js:975 State is right
adal.js:975 Fragment has access token
weijjia commented 9 years ago

This could be related to you listen on the adal:successlogin. Have you already logged in or you directly go to the protected route? If you went to the protected route without the user logged in, adal will trigger the user logged in(this will cause the broadcast of adal:successlogin event), and then add tokens. Your app listens on the login event, and when it captures it, this could trigger another token request.

drGarbinsky commented 9 years ago

All routes in this scenario are configured as protected routes.

Using breakpoints I have verified that the successLogin event is only triggered once. I've tested it with that code removed and when redirected back from the login page $scope.userInfo.isAuthenticated is still false and a second or two later successLogin is triggered and $scope.userInfo.isAuthenticated is set to true.

Regardless of how it is initiated the first API call to be made after adal:successLogin is fired the page reloads 3 times.

I could supply you with a test account to repro the issue with if you'd be willing to take a look.

fhellwig commented 9 years ago

I have the same issue. At first, I noticed that my API calls were occurring twice, as indicated by the OP. But, on further investigation, the entire app module is instantiated twice so basically, everything is done twice.

leandroshan commented 9 years ago

I have the same issue as the users above, everything executes twice after the first log in.

drGarbinsky commented 9 years ago

@weijjia any plans to dig into this? Or any other steps I could take to further troubleshoot this?

weijjia commented 9 years ago

Sorry for the delay. I'll get back to it this wee.

drGarbinsky commented 9 years ago

Let me know if you want me to setup you up with an account to our app for a repro.

absqueued commented 9 years ago

I too have the same issue. Couldn't fix, any updates? Here is what I get. I get this error in all browsers (including MS EDGE) adal-error

drGarbinsky commented 9 years ago

Just an FYI: This appears to be unaffected by 1.0.7 release.

lxghtless commented 9 years ago

Did you try adding https://login.microsoftonline.com to your trusted sites?

wizjack commented 8 years ago

Hi, The same problem is faced by me. App is initialized twice, (thrice in case if refresh token it seems), first call gives "The returned id_token is not parseable" and API call fails, second call works as expected with no "The returned id_token is not parseable" logs and API call succeeds. - Tested on chrome.

I wonder if this is related to https://github.com/AzureAD/azure-activedirectory-library-for-js/pull/182 - for Firefox or https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/42 maybe!

sunilbhujle commented 8 years ago

Facing the same issue. is there a known solution/work around?

bveerendrakumar commented 8 years ago

Hi this issue happening because of handle window hash. When this function is called it strips off Hash and sets window location which causes refresh again.

I struggled a lot to workaround this issue. Also i am facing another strange issue and that too its happening only in IE,. It is AAD 6500: renew token failed due to app doesn't have permission to read user data. I really did not understand why this issue is coming during renew token. If permission is not there it should fail during login itself. Can anybody help us on this?

winseros commented 8 years ago

Hi guys, same thing here.

I too have the same issue. Couldn't fix, any updates? Here is what I get. I get this error in all browsers (including MS EDGE)

@shekhardesigner, after having spent some hours for investigation of the issue, I wrote a small piece of code which fixed the situation for me:

function fixAngularLocationBug(e) {

    function isUserAuthenticated() {
        const result = $rootScope.userInfo && $rootScope.userInfo.isAuthenticated;
        return result;
    }

    function isLocationMailformed() {
        const idToken = "id_token";
        const result = $location.path().indexOf(idToken) > 0 && window.location.pathname.indexOf(idToken) < 0;
        return result;
    }

    const authenticated = isUserAuthenticated();
    const mailFormed = isLocationMailformed();
    if (authenticated && mailFormed) {
        e.preventDefault();
    }
}

$rootScope.$on("$locationChangeStart", fixAngularLocationBug);

The things happen there and causing the bug are the following: 1) after azure authorizes user and redirects him back to your app, AdalAngular looks at the redirect url, extracts authentication information from there and refreshes the auth data 2) this makes angular $location crazy, and it starts firing this lines of code over and over again 3) somewhere down the tree this code causes a $digest cycle, and angular detects infinite $digest loop and throws an error

wizjack commented 8 years ago

@winseros thanks for the update. But I'm still not sure what is causing the redirects and from where to where. If this line has the issue which causes the angular system to go crazy, why not put our custom route here and let the library do the rest. Also I'd like to know what happens when azure AD redirects us back, what is the life cycle here? Does my code takes precedence or library takes it away.

krushnachandra commented 8 years ago

I have also same issue in my application

venkateshappala commented 8 years ago

Any fix on this issue?

jjmschofield commented 8 years ago

This sounds like what we have been experiencing in https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/219

In addition to this issue I also see the run blocks for our modules get activated when the user goes to a resource/endpoint they don't already have a token for - I think it might also be linked to an issue we are having where the back button requires two clicks to actually go back.

For us adding this intercepting rule stopped endless loops and made the application stable.

$urlRouterProvider.rule(function ($injector, $location) { //Intercept every location change
  var $state = $injector.get("$state");
  var path = $location.path();

  if (path.indexOf("error=access_denied") > -1) { //If Microsoft has added an error to the path handle it
    $location.path('403'); //Blank the path off as, if we don't do this, there is a chain reaction which causes infinite digest loops of death
    $state.go('403');
  }

  if (path.indexOf("access_token") > -1 || path.indexOf("id_token") > -1) { //If Microsoft has added a token to the path handle it
    $location.path('/');  //Blank the path off as, if we don't do this, there is a chain reaction which causes infinite digest loops of death
  }
});
jjmschofield commented 8 years ago

Another related issue we raised and closed which looks again like the same thing https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/210

jjmschofield commented 8 years ago

As mentioned, even though we've stopped the digest looping, the app still reloads when a user tries to access an endpoint which they don't have a token in the cache for:

First request appreload

Request with cached token appreloadcached

Not sure how to proceed from here as it isn't clear what is causing the reload.

PavelPikat commented 8 years ago

I have the same issue and I think this is caused by adal-angular doing "$window.location.hash = ''; every time it gets and\or renews a token. Changing the hash makes the router to reload the state and thus controller executing for every acquireToken call.

This will only happen on the initial login, when adal needs to retrieve or renew its tokens for specified resources. If you have configured 10 endpoints, the app will reload 10 times. Once tokens are cached, the app will work as expected.

PavelPikat commented 8 years ago

I think I found the reason why the app reloads: whenever adal's iframe gets the token, it redirects to the url specified in "config.redirectUri" or, if not specified, to "Reply Url" from Azure AD, where the app is registered. Usually this Reply Url is the app root, so when the iframe hits this, the browser loads everything again.

Any ideas on how to disable redirection for requests that renew tokens?

jbone1972 commented 8 years ago

I have something going on very similar to this but I am certain its a rogue dev attacking me. Whoever or whatever is attacking me represents itself as Microsoft and uses bogus apps/tool using the MICROSOFT TM. I'm more than certain its highly illegal! He's even taken over my router. I've fought this for 2 years and lost laptops over it and now I'm going to scream until someone takes notice. I'm not real computer savvy so I'm asking if anyone can spend some time with me to help figure this out?

rossholdway commented 8 years ago

Also getting this same issue on v1.0.8

tushargupta51 commented 8 years ago

@PavelPikat @rossholdway Is there a way you can share a repro? I am having a hard time reproducing it on my local machine, using https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi sample.

PavelPikat commented 8 years ago

@tushargupta51 Here you go: https://plnkr.co/edit/XGhjO7Wd6RakXrJKJMLi You can see the sample in action here: https://adaljsdemo.azurewebsites.net Look in the console and notice how the app is loaded twice after adal gets its token. After the token is cached, navigation back and forth will not trigger app reload. Try removing the token from SessionStorage manually and you will see app reloading twice again.

tushargupta51 commented 8 years ago

@PavelPikat Thanks for the pointer, I was able to repro the issue. And I think you are right about the redirection. Whenever iframe returns back with the token, app is reloaded. I am looking into how we can disable this redirection.

PavelPikat commented 8 years ago

@tushargupta51 Shoud that be included in 1.0.9 milestone as well? I think this is the most annoying bug in ADAL so far which kind of prevents from using the library in a more or less serious application. Or maybe you have any tips on how we could solve this temporarily?

tushargupta51 commented 8 years ago

@PavelPikat You got it.

ischrei commented 8 years ago

Consider managing the loginInProgress value in the session storage (i.e. mark it with "in progress" before redirection, skip re-login if this is the value in the storage, and set it to "connected" when login completes. (However, if you do choose this direction, please contact me for some edge cases I run into)

tushargupta51 commented 8 years ago

I did some more investigation into this. From the console logs and debugging, it seems that the app is reloaded even before locationChangeHandler is called to process the token fragment, where we change the window.location.hash. So, the reason that the app is reloading again on a token renewal is not related to the way we update the location.hash.

My theory is that the server sends a 302 response to iframe, because that is how AAD works when a token is requested. Even before the angular app gets a chance to process the response, the response url (which is same as reply url registered at AAD appended by fragments) gets loaded in the iframe. Looking at the html, iframe's document object loads the html corresponding to the reply url.

The another issue that people reported on this thread: digest cycles/loop when requesting token, they seem to be related to window.location.hash update causing a digest cycle. But the issue about app reloading twice on every token renewal seems to be result of AAD sending a 302 response, which causes app to reload.

At this point, am not sure if we can prevent this reload at adal level or not. I have tried several things, frame onload events, using sandbox and some other stuff but none of them prevents that reload. I will continue looking into this and will update the thread if there is more info.

PavelPikat commented 8 years ago

What if AAD would accept some special parameter from adal telling it not to return to reply url?

ischrei commented 8 years ago

Indeed the app is reloaded in each one of the iframes as a result of the redirect from AAD. In order to minimize the effect in my app, I've calculated a flag "window.IS_ADAL_IFRAME = window !== window.parent" in the main html. In case of "true", i'm not reloading the rest of the app (i.e.only the main html and a few small scripts are reloaded)

laksh-parab commented 8 years ago

any update on why app is reloading twice?

tushargupta51 commented 8 years ago

Hi everyone, there is PR: https://github.com/AzureAD/azure-activedirectory-library-for-js/pull/284 submitted by a community member: @Neil665 which adds an extensibility point to specify an html file that will be loaded in the iframe instead of loading the entire app. You can specify that path to config.frameRedirectUri. I will also upload a template file to our wiki, that you can use for this purpose. Users will only need to update couple of paths and names in that html file.

This should fix the issue where app reload on every token renewal. Please note that, app will reload twice on initial login since that is a full page redirect.

Update: Instead of introducing a new property frameRedirectUri, we are using the redirectUri property for this purpose. Please look at the code snippets and a description of how you can take this fix: https://github.com/AzureAD/azure-activedirectory-library-for-js/wiki/FAQs#q1-my-app-is-re-loading-every-time-adal-renews-a-token