/* * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung * * Lizenziert unter der EUPL, Version 1.2 oder - sobald * diese von der Europäischen Kommission genehmigt wurden - * Folgeversionen der EUPL ("Lizenz"); * Sie dürfen dieses Werk ausschließlich gemäß * dieser Lizenz nutzen. * Eine Kopie der Lizenz finden Sie hier: * * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * Sofern nicht durch anwendbare Rechtsvorschriften * gefordert oder in schriftlicher Form vereinbart, wird * die unter der Lizenz verbreitete Software "so wie sie * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - * ausdrücklich oder stillschweigend - verbreitet. * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Environment, ENVIRONMENT_CONFIG } from '@alfa-client/environment-shared'; import { Inject, Injectable } from '@angular/core'; import { AuthConfig, OAuthEvent, OAuthService } from 'angular-oauth2-oidc'; import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks'; import { UserProfileResource } from 'libs/user-profile-shared/src/lib/user-profile.model'; import { getUserNameInitials } from 'libs/user-profile-shared/src/lib/user-profile.util'; import { filter, Subscription } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthenticationService { currentUserResource: UserProfileResource; private eventSubscription: Subscription; constructor( private oAuthService: OAuthService, @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, ) {} public async login(): Promise<void> { this.oAuthService.configure(this.buildConfiguration()); this.oAuthService.setupAutomaticSilentRefresh(); this.oAuthService.tokenValidationHandler = new JwksValidationHandler(); const eventPromise: Promise<void> = this.buildAuthEventPromise(); await this.oAuthService.loadDiscoveryDocumentAndLogin(); return eventPromise; } buildAuthEventPromise(): Promise<void> { return new Promise<void>((resolve, reject) => this.handleAuthEventsForPromise(resolve, reject)); } private handleAuthEventsForPromise(resolve: (value: void | PromiseLike<void>) => void, reject: (reason?: any) => void): void { this.eventSubscription = this.oAuthService.events .pipe(filter((event: OAuthEvent) => this.shouldProceedByAuthEvent(event))) .subscribe({ next: () => { this.setCurrentUser(); this.unsubscribeEvents(); resolve(); }, error: (error: any) => { this.unsubscribeEvents(); reject(error); }, }); } shouldProceedByAuthEvent(event: OAuthEvent): boolean { return this.consideredAsLoginEvent(event.type) || this.consideredAsPageReloadEvent(event.type); } consideredAsLoginEvent(eventType: string): boolean { return eventType === 'token_received'; } consideredAsPageReloadEvent(eventType: string): boolean { return eventType === 'discovery_document_loaded' && this.hasValidToken(); } hasValidToken(): boolean { return this.oAuthService.hasValidAccessToken() && this.oAuthService.hasValidIdToken(); } buildConfiguration(): AuthConfig { return { issuer: this.envConfig.authServer + '/realms/' + this.envConfig.realm, tokenEndpoint: this.envConfig.authServer + '/realms/' + this.envConfig.realm + '/protocol/openid-connect/token', redirectUri: window.location.origin + '/', clientId: this.envConfig.clientId, scope: 'openid profile', requireHttps: false, responseType: 'code', showDebugInformation: false, }; } setCurrentUser(): void { const claims: Record<string, any> = this.oAuthService.getIdentityClaims(); const userResource: UserProfileResource = <any>{ firstName: claims['given_name'], lastName: claims['family_name'], }; this.currentUserResource = userResource; } unsubscribeEvents(): void { this.eventSubscription.unsubscribe(); } public getCurrentUserInitials(): string { return getUserNameInitials(this.currentUserResource); } public logout(): void { this.oAuthService.revokeTokenAndLogout(); } }