import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; import { KeycloakAngularModule, KeycloakOptions, KeycloakService } from 'keycloak-angular'; import { DefaultUserService } from './default-user.service'; import { IIqserUser } from './types/user.response'; import { BaseUserService } from './base-user.service'; import { BASE_HREF, ModuleWithOptions } from '../utils'; import { AuthModuleOptions } from './types/auth-module-options'; import { IqserUser } from './user.model'; import { RoleGuard } from './role.guard'; import { AuthGuard } from './auth.guard'; import { BaseConfigService } from '../services'; function getKeycloakOptions(baseUrl: string, configService: BaseConfigService): KeycloakOptions { let url: string = configService.values.OAUTH_URL; url = url.replace(/\/$/, ''); // remove trailing slash const realm = url.substring(url.lastIndexOf('/') + 1, url.length); url = url.substring(0, url.lastIndexOf('/realms')); return { config: { url: url, realm: realm, clientId: configService.values.OAUTH_CLIENT_ID, }, initOptions: { checkLoginIframe: false, onLoad: 'check-sso', silentCheckSsoRedirectUri: window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html', flow: 'standard', }, enableBearerInterceptor: true, }; } function configureAutomaticRedirectToLoginScreen(keyCloakService: KeycloakService) { keyCloakService.getKeycloakInstance().onAuthRefreshError = async () => { await keyCloakService.logout(); }; } export function keycloakInitializer( keycloakService: KeycloakService, configService: BaseConfigService, baseUrl: string, ): () => Promise { const x = keycloakService.init(getKeycloakOptions(baseUrl, configService)); return () => x.then(() => configureAutomaticRedirectToLoginScreen(keycloakService)); } @NgModule({ imports: [CommonModule, HttpClientModule, KeycloakAngularModule], providers: [ AuthGuard, { provide: APP_INITIALIZER, useFactory: keycloakInitializer, multi: true, deps: [KeycloakService, BaseConfigService, BASE_HREF], }, ], }) export class AuthModule extends ModuleWithOptions { static forRoot< Interface extends IIqserUser, Class extends IqserUser & Interface, UserService extends BaseUserService, RolesGuard extends RoleGuard = RoleGuard, >(options: AuthModuleOptions): ModuleWithProviders { const userService = this._getService(BaseUserService, DefaultUserService, options.existingUserService); const roleGuard = this._getService(RoleGuard, RoleGuard, options.existingRoleGuard); return { ngModule: AuthModule, providers: [userService, roleGuard], }; } }