angular-auth-oidc-client icon indicating copy to clipboard operation
angular-auth-oidc-client copied to clipboard

[Question]: Automatically logging out users when tokens have expired

Open adchsm opened this issue 2 years ago • 3 comments

What Version of the library are you using? angular-auth-oidc-client: Tried both: 14.1.2 + 5.0.3 angular: 14.1.3

Question We'd like to automatically log out our users whose tokens have expired, and were hoping to utilise either the public events stream or the isAuthenticated$ observable to do this, however, they aren't behaving as I thought they would - but that might be me!

Here's our setup:

OIDCAUthModule.forRoot({
      config: {
        postLoginRoute: 'sign-in',
        authority: environment.authUrls.authorityUrl,
        redirectUrl: environment.authUrls.loginRedirectUrl,
        postLogoutRedirectUri: environment.authUrls.logoutRedirectUrl,
        clientId: '...',
        scope: 'openid profile offline_access',
        responseType: 'code',
        useRefreshToken: true,
      },
    }),

And in our app.component, we have the following:

export class AppComponent {
  private isAuthenticated$: Observable<AuthenticatedResult> =
    this.oidcSecurityService.isAuthenticated$;

  constructor(
    private oidcSecurityService: OidcSecurityService,
    private publicEventsService: PublicEventsService
  ) {
    this.isAuthenticated$.subscribe((isAuthenticated) =>
      console.log('isAuthenticated', isAuthenticated));

    this.publicEventsService
      .registerForEvents()
      .subscribe((event) => console.log(event));
  }
}

After authenticating, our id token is valid for 5 minutes, and access token for 1 hour.

I was hoping that:

  • After 5 minutes the publicEventsService would fire off an IdTokenExpired event, but it doesn't, this only seems to happen on the checkAuth method
  • After 1 hour the publicEventsService would fire off a TokenExpired event, but I've never seen this emitted.
  • After 5 minutes, the isAuthenicated$ observable in the app component would emit false, however, it doesn't seem to ever emit again once the ID token is expired.

I was hoping to be able to hook into these events to sign out users. If I'm incorrectly guessing the behaviour of these two things, please let me know - likewise if there are any other best practices I might be missing to log out users whose tokens have expired I'd be hugely grateful to hear them.

Thank you so much in advance,

Adam

adchsm avatar Feb 10 '23 12:02 adchsm

So normally logging out users after x minutes is custom logic. But the lib should fire the events that you can react to it. Will have to look into this.

FabianGosebrink avatar Feb 11 '23 15:02 FabianGosebrink

Hi, there @FabianGosebrink - thanks for offering to take a look - if it helps - I've just created a minimal repo to help illustrate where I'm experiencing difficulties: https://github.com/adchsm/angular-auth-oidc-client-test

You'll need to add in the authority and clientId, and it should be good to go (perhaps change the redirectUrl). Once you've authenticated, the id token expiry time should show. When that time passes, nothing happens, but I was expecting that the isAuthenticated$ observable would emit false.

Please let me know if this helps you to replicate this issue, or if I can be of any further help.

adchsm avatar Feb 15 '23 18:02 adchsm

I also ran into this (where I wasn't getting the events I expected based on Token expiration).

I traced through the code and am wondering if this is intentional:

The PeriodicallyTokenCheckService.startTokenValidationPeriodically() returns out of the method without setting up the periodic check if you don't have silent renew enabled https://github.com/damienbod/angular-auth-oidc-client/blob/main/projects/angular-auth-oidc-client/src/lib/callback/periodically-token-check.service.ts#L40

In my case, I'm am building a sample app where I don't want silent renew or a refresh token, so the validation check never triggers. I changed my config to use silent renew + refresh token to force the validation and emit the token expiration event as shown below. I didn't add offline_access intentionally (I also configured my IdP to not return refresh tokens).

AuthModule.forRoot({
      config: {
        authority: 'my-auth-server',
        redirectUrl: `${window.location.origin}`,
        postLogoutRedirectUri: window.location.origin,
        clientId: 'my-client-id',
        scope: 'openid profile email',
        responseType: 'code',
        silentRenew: true,
        useRefreshToken: true
      }
    })

Since I don't have a refresh token, I get a console error when my token expires, but I can deal with it for my use case.

@adchsm I took a look at your minimal repo to see if it would help me, have you tried enabling silentRefresh in your config?

alisaduncan avatar Apr 22 '23 20:04 alisaduncan