Skip to content

Keycloak is not fully initialized on page refresh #601

Closed
@detrist

Description

@detrist

Bug Report or Feature Request (mark with an x)

- [x] bug report -> please search for issues before submitting
- [ ] feature request

Versions.

angular: 19.0.0
keycloak-js: 26.0.7
keycloak-angular: equivalent with 19.0.1 (i had to previously import the code into my project for testing purpose)

Repro steps.

After refactoring this module, a simple page refresh on the component triggers unexpected behavior.

Here’s the scenario:

  • There are two Angular standalone components.
  • The first component handles login and includes a navigation button that redirects to the second component after a successful login.
  • The second component requires a specific role, defined in the routing configuration.

The expected flow works as intended: after a successful login, you can access the second component. However, if the page is refreshed while on the second component, the user is redirected to the fallback route (forbidden).

The issue seems to be that Keycloak is not fully initialized before the routing validation occurs. My understanding is that the current logic does not wait for the promise in the provideAppInitializer call to resolve, returning prematurely and resulting in a misconfigured Keycloak provider.

My working change looks like the following

const provideKeycloakInAppInitializer = (
  keycloak: Keycloak,
  options: ProvideKeycloakOptions
): EnvironmentProviders | Provider[] => {
  const { initOptions, features = [] } = options;

  if (!initOptions) {
    return [];
  }

  return provideAppInitializer(async () => {
    await keycloak.init(initOptions).catch((error) => {
      console.error('Keycloak initialization failed', error);
      return Promise.reject(error);
    });
    features.forEach((feature) => feature.configure());
  });
};

The only problem is that it breaks the features due to the injections inside the function, and so far I have not found a working solution for the injection problem. So it works by removing the feature configuration part of the provideKeycloakAngular function:

export const provideKeycloakAngular = () =>
  provideKeycloak({
    config: {
      realm: 'digital',
      url: 'https://localhost:8443',
      clientId: 'local',
    },
    initOptions: {
      onLoad: 'check-sso',
      silentCheckSsoRedirectUri:
        window.location.origin + '/silent-check-sso.html',
      redirectUri: window.location.origin + '/',
      pkceMethod: 'S256',
    },
    features: [
      /*withAutoRefreshToken({
        onInactivityTimeout: 'logout',
        sessionTimeout: 60000,
      }),*/
    ],
    providers: [
      AutoRefreshTokenService,
      UserActivityService,
      {
        provide: INCLUDE_BEARER_TOKEN_INTERCEPTOR_CONFIG,
        useValue: [localhostCondition],
      },
    ],
  });

The log given by the failure.

Similar error appears on enabled features with injections:

ERROR RuntimeError: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.dev/errors/NG0203
    at injectInjectorOnly (core.mjs:1096:11)
    at ɵɵinject (core.mjs:1106:40)
    at inject (core.mjs:1191:10)
    at Object.configure (with-refresh-token.feature.ts:75:39)
    at provide-keycloak.ts:63:43
    at Array.forEach (<anonymous>)
    at provide-keycloak.ts:63:14
    at Generator.next (<anonymous>)
    at fulfilled (main.js:24:24)
    at _ZoneDelegate.invoke (zone.js:369:28)

Desired functionality.

I'm not sure if this is a regression caused by the recent code refactor, as I don't recall encountering similar issues in the past.

The expected behavior is something I’ve already started to address: the provider initialization should wait for the promise to resolve before returning. Without this, Angular triggers the authorization check before Keycloak is fully initialized.

What remains unresolved is how to handle injections in feature modules. Any suggestions or guidelines for addressing this would be greatly appreciated.

Metadata

Metadata

Labels

need-investigationNeeds more investigation to identify if it is a bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions