benbaran / adal-angular4

Angular 4/5/6/7 ADAL Wrapper
MIT License
86 stars 104 forks source link

Refresh after token renewal - memory leak? #84

Open jo-me opened 6 years ago

jo-me commented 6 years ago

Hi,

I've noticed an issue related to adal that I cannot quite understand.

It seems like when a token is renewed silently the Angular App gets "restarted". In the Chrome console, you can see: core.js:3123 Angular is running in the development mode. Call enableProdMode() to enable the production mode. running through when this happens when you're running it locally.

You can also provoke this issue by removing the adal.expiration.key entry from local storage. Immediately, the token gets renewed and the app gets restarted

The problem is not the restart itself but that the old application remains completely in memory. A heap snapshot shows two instances of AppComponent and two instances of all services that are provided through dependency injection and everything UI related as well.

Is anyone seeing this as well? What causes this "soft restart" and how can I prevent the leak?

Thanks

geerzo commented 6 years ago

Any of the silent calls use an iframe that calls out to AAD to get the access token. The way AAD works is that it redirects back to the original application with the token in the url so in that iFrame the original application gets loaded which is why you see that initialization. I'm hopeful there is an elegant solution but I haven't found it yet.

It's important to realize that on the silent calls, the handleCallback method is being called in the instance of the app in the iFrame, not the parent app.

jo-me commented 6 years ago

Oohh. I understand. Never came to me to look inside the iframe. I thought that there are just some AAD dragons living there that I did not want to wake up.

I guess then I'll have to modify the app so that the iframe instance does not go overboard with backend interactions.

How can I detect inside the app whether I'm running inside the iframe ? window.parent === window?

geerzo commented 6 years ago

You can use window.self != window.top but there might be a better way.

jo-me commented 6 years ago

So, I ended up spending way too much time on this.

Even after detecting the iframe from within my app and doing just the minimal things (like initializing adal to handle the callback) it still did not work . It always came back with dubious invalid_state adal errors and did therefore not write the new token to the storage.

Today, I tried this: https://stackoverflow.com/a/49109828 and it really worked. You don't have to adapt the angular app at all. The script will prevent it from bootstrapping in the iframe and just do the token handling directly in the parent app.

douglasfernandesjr commented 5 years ago

I`m facing the same issue, my app became really slow on the first access.

I tried the @jo-me solution, and i had to change the if statement, for: "if (window.parent && window.parent._adalInstance)". It`s stop the Angular from starting, but still didn't solve the problem.