“Invalid token specified error” only at first login in Angular app with oauth2-oidc and keycloak

341 Views Asked by At

In my Angular application I’m using oauth2-oidc library and Keycloak to manage authentication.

This is the oauth configuration:

//auth-config.ts

import { AuthConfig } from "angular-oauth2-oidc";

export const oauthConfig: AuthConfig = {
  issuer: 'http://localhost:8083/realms/Plus365-local', // URL of the Identity Provider
  requireHttps: false,
  redirectUri: window.location.origin + '/home',// URL of the SPA to redirect the user to after login
  clientId: 'client-frontend', // The SPA's id. The SPA is registered with this id at the auth-server
  scope: 'openid profile email offline_access'
}

I have some routes that need to be accessible without authentication (i.e. register/…) so I cannot make an immediate redirect to keycloak login using for exemple APP_INIZIALIZER pattern. I need to actually bootstrap the application first.

So in my app.component I use this code to handle the login:

// app.component

handleLogin()

...

handleLogin() {
// This timeout is the only way I found to prevent from redirect to the keycloak login page when the user is on register page. 
    setTimeout(() => { 
      this.isRegisterPage$ = this.store.select(isOnRegisterPage);
      this.isRegisterPage$.subscribe(
        b => {
          if (!b) { // If user is not on register page do oauth login
            this.clientAuthService.performLogin().then(() => {
              this.store.dispatch(AuthActions.loginDone());
            })
          }
        }
      )
    })
  }

and in my service:

// auth-service

import { Injectable } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { oauthConfig } from './auth-config';

@Injectable({
  providedIn: 'root'
})
export class ClientAuthService {

  constructor(private oauthService: OAuthService) { }

  performLogin() {
    this.oauthService.configure(oauthConfig);
    return this.oauthService.loadDiscoveryDocumentAndLogin();
  }

  logOut() {
    this.oauthService.logOut();
  }
}

I’m using standalone approach so I don’t use NgModules and my main.ts file looks like this:

// main.ts

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(APP_ROUTES),
    provideOAuthClient(),
    provideStore(appReducer),
    provideEffects([
      //…NgRx stuff…
    ]),
    provideStoreDevtools({
      maxAge: 25,
      logOnly: !isDevMode()
    }),
    provideHttpClient()
   ]
}).catch(err => console.error(err));

Now, at first login I get an Invalid token specified error:

*n { message: 'Invalid token specified', stack: 'InvalidTokenError\n at 9168 (http://localhost:42…equire__ (http://localhost:4200/runtime.js:23:42)'} message: "Invalid token specified" stack: "InvalidTokenError\n at 9168 (http://localhost:4200/vendor.js:5729:15)\n at webpack_require (http://localhost:4200/runtime.js:23:42)\n at 3496 (http://localhost:4200/main.js:4542:68)\n *

At this stage I can see the access_token and all the keycloak stuff saved in my session storage, but it looks like at the very first login the access_token is not immediately available so I have this error.

If I reload the page (so everything is already present in the session storage) everything works as expected.

I know the problem is probably related to relying on the ngrx store to check if the current page is the registration page, but I cannot find an alternative solution.

Tryed to remove the setTimeout in app component handleLogin() but it is the only way I found to prevent from redirect to the keycloak login page when the user is on register page. If I remove the timeout it always redirect.

This is very annoying and I really hope someone can help.

0

There are 0 best solutions below