Angular-auth-oidc-client: Check session & silent renew

Created on 20 Oct 2017  路  16Comments  路  Source: damienbod/angular-auth-oidc-client

As a dev
I want to keep the control of library events
so that I can improve my app performance

Check session & silent renew, at the moment, are not manageable by the developer.

  • Check session is used to verify if the user has disconnected from the authorization server:
        let source = Observable.timer(3000, 3000)
            .timeInterval()
            .pluck('interval')
            .take(10000);
  • _It runs every 3 seconds for 10000 times_
  • It does not seem possible to stop it even after the user has disconnected from the client
  • The max authentication time is 8 hours

Suggestions:

  • We should create a new setting: check_session_interval to set a different interval
  • We should remove the limit of 10000 times & stop it after user logout

The spec in fact do not seem to interfere in this: http://openid.net/specs/openid-connect-session-1_0.html

  • Silent renew is used to renew the token when the token is expired: to check if the token is expired we have:
        let source = Observable.timer(5000, 3000)
            .timeInterval()
            .pluck('interval')
            .take(10000);

        let subscription = source.subscribe(() => {
            if (this._isAuthorizedValue) {
                if (this.oidcSecurityValidation.isTokenExpired(this.oidcSecurityCommon.retrieve(this.oidcSecurityCommon.storage_id_token), this.authConfiguration.silent_renew_offset_in_seconds)) {
                    this.oidcSecurityCommon.logDebug('IsAuthorized: id_token isTokenExpired, start silent renew if active');

                    if (this.authConfiguration.silent_renew) {
                        this.refreshSession();
                    } else {
                        this.resetAuthorizationData(false);
                    }
                }
            }
        },

  • _It runs every 3 seconds for 10000 times_
  • When it finds that the token has expired, it starts the renewal

Suggestions:

  • We should read the expireIn before, and set the interval (with offset) at the same duration (here an example: https://github.com/robisim74/AngularSPAWebAPI/blob/master/AngularSPAWebAPI/app/services/authentication.service.ts#L105)

The dev who implements the library have two timers and two subscriptions that are activated _2400 times in one hour_ and that it is not possible to unsubscribe. In a large application it could generate performance problems (and _memory leak_ ?).

Opinions, please.

enhancement question

Most helpful comment

@damienbod @robisim74 I could work on this one, if you both agreed.

All 16 comments

Super improvement

I was running into this as well and have a question which is hopefully not to much off-topic:

The oidcSecurityValidation.isTokenExpired() method checks against the expparameter of the id_token. My server sets the value at 120s which seemed very low, but then I read the description of the parameter:

Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

This seems to make sense on a server client, or a tipical code flow where the open_id information is stored in a database. But I wonder if this parameter is the correct one to use when we want to decide if the token needs renewal? The webclient has already _processed_ the token. I wonder if the max_age parameter might be more suitable for this? Or perhaps I misunderstand the purpose of isTokenExpired() and the silent_renew?

@damienbod @robisim74 I could work on this one, if you both agreed.

This seems to be what is causing an entire change-detection cycle in our application every few seconds, and it's killing performance. Is it by design that the entire shadow DOM would be re-evaluated just for session checking, or could I have done something wrong in my implementation?

Set the lifespan of the tokens to 10, or 20 minutes

I already have it set to 24 hours...

The entire change-detection cycle in the application should not be affected by the silent renew. This checks every n seconds if something is required and does nothing. Only if the id_token has expired, will it execute the authorize and validation functions

If you have set the lifespan of the id_token to 24 hrs, nothing is affected by the silent renew for 24 hrs

I have run several tests and it appears this is not correct. The change detection cycle still runs even if the token has not expired.

This should not happen. Can you post your id_token, access_token, STS config configuration?, oidc configuration?

@robisim74 @FabianGosebrink I thinking of implementing the silent renew in a separate component which can be used as an entryComponent and loaded dynamically. Wondering if this is a good idea, or looking for ways to implement this.

It would be great if the silent renew logic ran in a way that the whole SPA was not loaded inside the iframe.

Greetings Damien

Related to this issue, I was seeing errors today where it seemed like if the silent renew was slow, a 2nd silent renew would start up before the first one completely finished. The code seemed to keep doing this over and over and the silent renew never succeeded. When I changed the validation/timeout polling interval from 3 seconds to 7 seconds, this problem disappeared. It would be great if the silent renew polling interval could be configured or if the code could be updated to ensure that the renew AND the token validation all get a chance to finish before another renew can start.

First of all, great credits to the author. This library rocks, which saves me massive pains of implementing the openID by myself...

At the moment I just feel the Silent Renew functionality is not perfect:

  1. Angular's change detection is indeed triggered every 3 seconds from the
 let source = Observable.timer(3000, 3000)
            .timeInterval()
            .pluck('interval')
            .take(10000);

observable. This will no doubt happen because by default, setTimeout, user interactions and Ajax are the 3 main ways triggering Angular CD. To avoid this, you can use ngZone, and put all this logic into

this.zone.runOutsideAngular(() 
=> {//...})
  1. The subscription will be broken in case of any errors/exceptions during the silentRenew process. I often see SilentRenew "silently" stop after a couple of hours with indeterministic red error messages left in the console. To make it continue with errors, you may use Obsevable.onErrorResumeNext() method.

  2. Does user have a way to completely shutdown the silent renew process? It seems no at the moment. Ideally I think users should be allowed to prepare their own timer and call oidcSecurityService.refreshSession() according to their own requirements. I hope we can have a new configuration parameter to achieve this.

@runninghare

thanks and these are super improvements. All 3 are cool. If you would create a PR, it would be cool, otherwise I will try to implement this in the near future. (got a time problem at the moment)

Greetings Damien

@damienbod thanks for your prompt reply. I'll do some more investigations. If they work I'll create PR.

There still seems to be an issue which makes oidcSecurityCommon.silentRenewRunning always be 'running' in authorizedCallback() function of oidc.security.service.ts:

this.getSigningKeys().subscribe(jwtKeys => {
...
})

This subscriber doesn't have an error handler. I think we need to add one, at least reset oidcSecurityCommon.silentRenewRunning to a falsy value.

I just added a simple handler in my latest PR, but maybe it's not enough. You need to take a look.

Hi, @damienbod I am new to this library, Silent renewal is a little tough to understand for me. can I get an actual example of how silent renewal works? In my project, v6.0.0 is used. Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Roman1991 picture Roman1991  路  4Comments

cgatian picture cgatian  路  4Comments

daudihusbands picture daudihusbands  路  3Comments

brentos99 picture brentos99  路  4Comments

haidelber picture haidelber  路  3Comments