Angular-auth-oidc-client: During silent renew process failure your App can fully hang

Created on 21 Aug 2020  路  14Comments  路  Source: damienbod/angular-auth-oidc-client

Our team faced with an issue when our users can't open our App.

Steps to reproduce:

  1. OIDC flow: authorization code
  2. Turn on silent renew (refresh token have to be turned off).
  3. After App initialization use checkAuthIncludingServer()
  4. Then need to simulate some connection problems to your IS (for this test you can turn off your IS)
  5. Wait until silent renew process will trigger IS /authorize endpoint (it should fail because we turn off IS in the previous step)
  6. Then need to wait when your token will expire
  7. Refresh your page or open your app in a new tab
  8. App will fully hang.

Here are the reasons why it's happens:

During silent renew process client app does redirect your IS /authorize endpoint inside special silent renew iframe. Before the angular-auth-oidc-client library will run this process it will set special record [client_ID]_storageSilentRenewRunning = "running" to your storage (in my case it's local storage). So if for some reasons this redirect (inside iframe) will fail (unavaliable server, connection problems ect.) then this record will be always in "running" state. It means that the silent renew won't be launched anymore.

Then if token is expired and user try to reload the page or open app in a new tab, page loading will hang because of checkAuthIncludingServer() implementation. Under the hood checkAuthIncludingServer() invokes forceRefreshSession()
and here is the root cause of the problem. It will forever wait for a response from silentRenewService.refreshSessionWithIFrameCompleted$ and it will never happen because real silent renew process doesn't launched because the storage record shows the opposite [client_ID]_storageSilentRenewRunning = "running".

To resolve this issue user have to clear storage or directly that record from the storage.

bug investigate

Most helpful comment

any new on this? I麓m having the exact same error on reloading the page when [client_ID]_storageSilentRenewRunning == "running" (exactly after AccessTokenLifetime is reinitialized)

All 14 comments

@Expelz Thanks for reporting. I will look into this and see if I can solve it.

@damienbod Hi! Have any update on this, or some lead in how to fix it? We are having the same issue after upgrading from version 10.

I just did a PR but I am not sure if that fixes the problem. Maybe you can re-test this branch @Expelz @lschuft ?

@FabianGosebrink Thank you! I'll try to make some time today to test it and I'll let you know.

That would be perfect. We merged too early, that was our mistake in this case. However the changes are small so it should not break anything. (Famous last words of a software engineer 馃榾)

I'm no expert on trying out local libraries in my projects; I downloaded master, npm install, npm pack, and then npm install'ed the local .tgz in my Angular project. But running ng serve throws a "ERROR in Cannot read property '0' of undefined" error with no stack trace 馃槄.

I'll try to keep looking and report back!

@FabianGosebrink thank you for your intention to this problem. Unfortunately your commit #857 doesn't solve the problem. Also I want to admit that the problem isn't related to catch all errors during silent renew process, it doesn't fix it (only partially).

The root cause of the problem is the inability to understand the end of the silent renew transaction (process). Silent renew process strongly depends on special record [client_ID]_storageSilentRenewRunning = "running" inside storage.
If for some reasons (failed request inside silent renew iframe or user reload page when[client_ID]_storageSilentRenewRunning = "running" record already has been saved into storage ect.) then library will be always in an invalid state (all library services which are dependent on this record, because it will forever wait until this state will be changed).

Ideas to discuss:

  1. In case of checkAuthIncludingServer() we need to add rxjs timeout. It will fix fully hang of App which I have described in this issue description
  2. Create some mechanism during invocation of flowsDataService.isSilentRenewRunning() which would determine that silent renew process doesn't respond and clear this record from storage after some time.

any new on this? I麓m having the exact same error on reloading the page when [client_ID]_storageSilentRenewRunning == "running" (exactly after AccessTokenLifetime is reinitialized)

@AlvaroP95 I ran into this problem as well. Turns out my silent_renew.html code was the culprit.

Bad code:

var event = new CustomEvent("oidc-silent-renew-message", {  detail: window.location.hash.substr(1) });

Correct code:

var event = new CustomEvent("oidc-silent-renew-message", {  detail: window.location });

Hey @ph3b , can you tell what the window.location was? Maybe this needs a fix from our side. Thanks.

Hi @FabianGosebrink , I think our application was configured to use silent renew with refresh tokens, but we didn't actually use refresh tokens (not set to true in our oidc config). Thus, the incorrect silent_renew.html was used (from: https://github.com/damienbod/angular-auth-oidc-client/blob/main/docs/silent-renew.md). Using window.location instead of window.location.hash.substr(1) seems to fix it for us.

Hi @ph3b and thanks for replying! But unfortunately my code was already like your "Correct code" 馃槩. My silentRenew is also set to true in my case. I'm still investigating the problem but it seems really complicated.

Hi,
Here is my solution for this problem - #942. It has been tested in our develop environment.
@damienbod @FabianGosebrink - I will wait for your feedback and review.

fix will be released in next reelease

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xaviergxf picture xaviergxf  路  3Comments

cgatian picture cgatian  路  4Comments

toddtsic picture toddtsic  路  4Comments

profet23 picture profet23  路  3Comments

Roman1991 picture Roman1991  路  4Comments