keycloak-angular icon indicating copy to clipboard operation
keycloak-angular copied to clipboard

Is there a guide for using SSR with Angular 19 and provideKeycloak?

Open soungsid opened this issue 11 months ago • 9 comments

Bug Report or Feature Request (mark with an x)

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

Versions.

keycloak-angular 19

Repro steps.

The log given by the failure.

Desired functionality.

I'm working with Angular 19 and keycloak-angular for authentication. I'm trying to implement Server-Side Rendering (SSR) using Angular Universal, and I want to use the provideKeycloak provider for Keycloak authentication.

However, I'm unsure how to properly set up provideKeycloak in an SSR environment, as there are issues with accessing the window object and configuring the provider correctly.

What I’m looking for:

  • Is there an official guide or example on how to configure provideKeycloak with SSR in Angular 19?
  • Specifically, how should I handle the server-side environment when using Keycloak with Angular Universal?
  • Any known issues or best practices for SSR with keycloak-angular in Angular 19?

I would appreciate any help or links to documentation.

Thank you in advance!

soungsid avatar Jan 14 '25 06:01 soungsid

any comment on this request?

soungsid avatar Jan 29 '25 15:01 soungsid

Hi @soungsid, I'll be working on an example SSR application using the library, along with documentation to support it. While I can't commit to a specific deadline, I’m aiming to have it ready by the end of February.

mauriciovigolo avatar Feb 02 '25 01:02 mauriciovigolo

Hi, Are there any updates regarding SSR? Is the end of February deadline feasible?

karolix1279 avatar Feb 16 '25 19:02 karolix1279

@mauriciovigolo Any updates on this?

LaurensChipmunk avatar Mar 12 '25 15:03 LaurensChipmunk

Hi, I saw the updates to keycloak-angular and tried it out with Angular 19 and SSR. I had an issue with keycloak.init (window is not defined on the server) when using provideKeycloak(...).

It seems to work for me when the keycloak.init is only executed in the browser

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

  if (!initOptions) {
    return [];
  }

  return provideAppInitializer(async () => {
    const platform = inject(PLATFORM_ID);

    // 👇 browser guard: only init keycloak in the browser
    if (isPlatformBrowser(platform)) {
      const injector = inject(EnvironmentInjector);
      runInInjectionContext(injector, () => features.forEach((feature) => feature.configure()));

      await keycloak.init(initOptions).catch((error) => console.error("Keycloak initialization failed", error));
    } else {
      console.log("Keycloak initialization skipped on server side");
    }
  });
};

What do you think about adding this check to provideKeycloakInAppInitializer?

Second, this is a change detection thing from Angular. Using the KEYCLOAK_EVENT_SIGNAL as described in the docs with effect to check authenticated, this will result in displaying Logout and Login button (when logged in) at the same time for RenderMode.Server, but only Logout for RenderMode.Client.

You can find my reproduction repo and fixes to both problems here: https://github.com/marcjulian/ng-19-ssr-keycloak

Let me know, if this helps solve the issue. Also let me know if I should create a PR to either add the isPlatformBrowser check or also to update docs/readme.

marcjulian avatar Apr 03 '25 11:04 marcjulian

Thank you, Marc. Your explanations are wonderful, and your example works perfectly. Thanks to you, I'll be able to move forward with my Angular 19 / Keycloak project. Stephane

stephanechevrier38 avatar Apr 04 '25 14:04 stephanechevrier38

Currently trying to implement Keycloak Angular with Angular 20 and SSR and I currently face the same problem with both my application as well as the application you linked above: When reloading the app (or hot reloading when developing) after having logged in successfully, both apps seem to freeze up. They only return to working order once I remove the keycloak related cookies (which kind of defeats the purpose). Could this be related to a misconfigured Keycloak Setting or is this a known bug?

From what I noticed the KEYCLOAK_EVENT_SIGNAL never seems to fire

ghostlydilemma avatar Jul 22 '25 20:07 ghostlydilemma

It's difficult to help you precisely based on your explanations. I'll share my code with you; maybe it will help.

interface KeycloakConfig { url: string; realm: string; clientId: string; }

export const keycloakConfig: KeycloakConfig = { url: environment.keycloak_protocol + '://' + environment.keycloak_ip + ':' + environment.keycloak_port, realm: environment.keycloak_realm, clientId: environment.keycloak_client_id, };

……

export class KeycloakServiceImpl {

private readonly injector = inject(Injector); private keycloak: any = undefined; private keycloakEventLast : KeycloakEvent | undefined = undefined; private keycloakSignalEvent : Signal<KeycloakEvent> | undefined;

……

public constructor() {

afterNextRender(async () => {

  if (this.keycloak === undefined) {
    // @ts-ignore
    this.keycloak = new Keycloak(keycloakConfig);
    this.keycloakSignalEvent = createKeycloakSignal(this.keycloak);
  }

  effect(
    async () => {
      if (this.keycloakSignalEvent === undefined) return; 
      let keycloakEvent: KeycloakEvent  = this.keycloakSignalEvent();
      if ( (keycloakEvent.type === this.keycloakEventLast?.type) && (keycloakEvent.args === this.keycloakEventLast?.args) ) return;
      this.keycloakEventLast = keycloakEvent;
      if (keycloakEvent.args !== undefined) --> TODO
      }
    },
    {injector: this.injector}
  );
});

}

stephanechevrier38 avatar Jul 25 '25 10:07 stephanechevrier38

Heya! Thanks for your answer. I sadly missed the response completely... I tried using the solution provided above by marcjulian (https://github.com/marcjulian/ng-19-ssr-keycloak) and implemented the services/fixes as mentioned. After playing around with it some more now I realised that the problem on my end seems to be with using locally signed SSL certificates for the angular application. On the initial load everything seems to be working fine, but whenever the application is reloaded (or changes in the codebase trigger a (partial) reload), the entire application freezes, causing no further communication with Keycloak (or anything else in the application to function for that matter). I highly doubt this issue stems from Keycloak or this library, thank you for your help regardless :)

ghostlydilemma avatar Aug 22 '25 16:08 ghostlydilemma