@odx/auth 6.0.2 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +16 -10
  3. package/esm2022/index.mjs +2 -1
  4. package/esm2022/lib/auth.config.mjs +6 -23
  5. package/esm2022/lib/auth.guard.mjs +10 -3
  6. package/esm2022/lib/auth.i18n.mjs +1 -1
  7. package/esm2022/lib/auth.interceptor.mjs +15 -0
  8. package/esm2022/lib/auth.logger.mjs +3 -0
  9. package/esm2022/lib/auth.providers.mjs +53 -36
  10. package/esm2022/lib/auth.service.mjs +27 -15
  11. package/esm2022/lib/auth.typings.mjs +1 -1
  12. package/esm2022/lib/components/auth-loading-screen/auth-loading-screen.component.mjs +6 -6
  13. package/esm2022/lib/helpers/create-auth-host-url.mjs +6 -0
  14. package/esm2022/lib/helpers/index.mjs +4 -1
  15. package/esm2022/lib/helpers/set-http-auth-header.mjs +13 -0
  16. package/esm2022/lib/helpers/user-language-loader.mjs +10 -0
  17. package/esm2022/lib/models/auth-environment.mjs +3 -2
  18. package/esm2022/lib/models/auth-http-cache.mjs +19 -23
  19. package/esm2022/lib/models/auth-plugin-manager.mjs +14 -9
  20. package/esm2022/lib/plugins/core-debug.plugin.mjs +20 -0
  21. package/esm2022/lib/plugins/index.mjs +2 -1
  22. package/esm2022/lib/plugins/user-profile-link.plugin.mjs +3 -3
  23. package/esm2022/lib/unauth.guard.mjs +10 -3
  24. package/esm2022/plugins/service-connect/index.mjs +2 -2
  25. package/esm2022/plugins/service-connect/lib/dtos/get-service-connect-user-response.dto.mjs +2 -0
  26. package/esm2022/plugins/service-connect/lib/dtos/index.mjs +2 -1
  27. package/esm2022/plugins/service-connect/lib/service-connect-rights.guard.mjs +3 -3
  28. package/esm2022/plugins/service-connect/lib/service-connect-rights.plugin.mjs +1 -2
  29. package/esm2022/plugins/service-connect/lib/service-connect-user-language.plugin.mjs +8 -0
  30. package/esm2022/plugins/service-connect/lib/service-connect.config.mjs +6 -4
  31. package/fesm2022/odx-auth-plugins-service-connect.mjs +15 -9
  32. package/fesm2022/odx-auth-plugins-service-connect.mjs.map +1 -1
  33. package/fesm2022/odx-auth.mjs +308 -240
  34. package/fesm2022/odx-auth.mjs.map +1 -1
  35. package/index.d.ts +1 -0
  36. package/lib/auth.config.d.ts +11 -10
  37. package/lib/auth.guard.d.ts +1 -1
  38. package/lib/auth.i18n.d.ts +2 -2
  39. package/lib/auth.interceptor.d.ts +2 -0
  40. package/lib/auth.logger.d.ts +3 -0
  41. package/lib/auth.providers.d.ts +7 -4
  42. package/lib/auth.service.d.ts +6 -2
  43. package/lib/auth.typings.d.ts +1 -1
  44. package/lib/helpers/create-auth-host-url.d.ts +2 -0
  45. package/lib/helpers/index.d.ts +3 -0
  46. package/lib/helpers/set-http-auth-header.d.ts +2 -0
  47. package/lib/helpers/user-language-loader.d.ts +4 -0
  48. package/lib/models/auth-environment.d.ts +6 -1
  49. package/lib/models/auth-http-cache.d.ts +3 -1
  50. package/lib/models/auth-plugin-manager.d.ts +2 -0
  51. package/lib/plugins/core-debug.plugin.d.ts +2 -0
  52. package/lib/plugins/index.d.ts +1 -0
  53. package/lib/unauth.guard.d.ts +1 -1
  54. package/package.json +2 -2
  55. package/plugins/service-connect/index.d.ts +1 -1
  56. package/plugins/service-connect/lib/dtos/get-service-connect-user-response.dto.d.ts +3 -0
  57. package/plugins/service-connect/lib/dtos/index.d.ts +1 -0
  58. package/plugins/service-connect/lib/service-connect-rights.guard.d.ts +1 -1
  59. package/plugins/service-connect/lib/service-connect-rights.plugin.d.ts +8 -1
  60. package/plugins/service-connect/lib/service-connect-user-language.plugin.d.ts +1 -0
  61. package/plugins/service-connect/lib/service-connect.config.d.ts +1 -0
  62. package/esm2022/plugins/service-connect/lib/service-connect.typings.mjs +0 -2
  63. package/plugins/service-connect/lib/service-connect.typings.d.ts +0 -9
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, EnvironmentInjector, InjectionToken, Injectable, ErrorHandler, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, Directive, EventEmitter, Output, HostListener, NgModule, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, APP_INITIALIZER } from '@angular/core';
3
- import { WindowRef, CoreModule } from '@odx/angular';
2
+ import { inject, EnvironmentInjector, InjectionToken, Injector, Injectable, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, DestroyRef, ENVIRONMENT_INITIALIZER, makeEnvironmentProviders, APP_INITIALIZER, ErrorHandler, Directive, EventEmitter, Output, HostListener, NgModule } from '@angular/core';
3
+ import { Environment, WindowRef, CoreModule } from '@odx/angular';
4
4
  import * as i3$1 from '@odx/angular/components/area-header';
5
5
  import { AreaHeaderModule } from '@odx/angular/components/area-header';
6
6
  import * as i8 from '@odx/angular/components/dropdown';
@@ -10,30 +10,35 @@ import * as i1$1 from '@odx/angular/components/loading-spinner';
10
10
  import { LoadingSpinnerDirective, LoadingSpinnerModule } from '@odx/angular/components/loading-spinner';
11
11
  import { LogoDirective } from '@odx/angular/components/logo';
12
12
  import { TranslatePipe, provideTranslations } from '@odx/angular/internal/translate';
13
- import { isString, createConfigTokens, injectElement, untilDestroyed, Position, buildUrl } from '@odx/angular/utils';
14
- import { OAuthErrorEvent, OAuthService, provideOAuthClient, OAuthModuleConfig, OAuthStorage } from 'angular-oauth2-oidc';
15
- import { filter, switchMap, BehaviorSubject, map, distinctUntilChanged, share, of, combineLatest, catchError, tap, take, fromEvent, startWith, shareReplay, merge, EMPTY } from 'rxjs';
16
- import { HttpErrorResponse } from '@angular/common/http';
13
+ import { buildUrl, isString, CacheStorageClient, matchUrl, injectElement, isNumber, isNonEmptyString, createConfigTokens, untilDestroyed, Position } from '@odx/angular/utils';
14
+ import { OAuthErrorEvent, OAuthService, provideOAuthClient, OAuthStorage } from 'angular-oauth2-oidc';
15
+ import { filter, switchMap, firstValueFrom, mergeMap, map, of, tap, BehaviorSubject, distinctUntilChanged, share, combineLatest, take, timeout, catchError, fromEvent, startWith, shareReplay, merge, EMPTY } from 'rxjs';
16
+ import { HttpRequest, provideHttpClient, withInterceptors, HttpErrorResponse } from '@angular/common/http';
17
17
  import { Router } from '@angular/router';
18
18
  import { deepmerge } from 'deepmerge-ts';
19
+ import { DynamicViewDirective, DynamicViewService } from '@odx/angular/cdk/dynamic-view';
20
+ import { Logger, CSSComponent } from '@odx/angular/internal';
19
21
  import { __decorate } from 'tslib';
20
22
  import * as i2 from '@odx/angular/components/list';
21
23
  import { ListModule } from '@odx/angular/components/list';
22
- import { CSSComponent } from '@odx/angular/internal';
23
24
  import * as i1 from '@angular/common';
24
25
  import { CommonModule, NgIf } from '@angular/common';
25
26
  import * as i3 from '@odx/angular/components/icon';
26
27
  import { IconComponent } from '@odx/angular/components/icon';
27
28
  import { trigger, transition, useAnimation } from '@angular/animations';
28
29
  import { fadeOut } from '@odx/angular/animations';
29
- import { DynamicViewDirective, DynamicViewService } from '@odx/angular/cdk/dynamic-view';
30
30
  import * as i6 from '@odx/angular/components/button';
31
31
  import { ButtonComponent } from '@odx/angular/components/button';
32
32
  import { CircularProgressComponent } from '@odx/angular/components/circular-progress';
33
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
33
34
  import * as i2$1 from '@ngrx/component';
34
35
  import * as i4 from '@odx/angular/components/avatar';
35
36
  import * as i5 from '@odx/angular/components/action-group';
36
37
 
38
+ function createAuthHostUrl(environment, ...segments) {
39
+ return buildUrl(ODX_AUTH_HOSTS[environment], ...segments);
40
+ }
41
+
37
42
  function createInitials(value) {
38
43
  if (!value)
39
44
  return '';
@@ -101,103 +106,47 @@ function resolveUsername(claims) {
101
106
  return '';
102
107
  }
103
108
 
104
- const DEFAULT_AUTH_SCOPES = ['openid', 'profile', 'email', 'offline_access'];
105
- const DEFAULT_OKTA_URLS = {
106
- dev: 'https://dev.login.draeger.com',
107
- stage: 'https://test.login.draeger.com',
108
- prod: 'https://login.draeger.com',
109
- };
110
- const DEFAULT_USER_PROFILE_URLS = {
111
- dev: 'https://lemon-ocean-04a922703.3.azurestaticapps.net',
112
- stage: 'https://purple-cliff-0e61c5703.3.azurestaticapps.net',
113
- prod: 'https://id.draeger.com',
114
- };
115
- const ODX_AUTH_CORE_PLUGINS = new InjectionToken('@odx/auth::CorePlugins', {
116
- providedIn: 'root',
117
- factory: () => [],
118
- });
119
- const ODX_AUTH_ERROR_HANDLERS = new InjectionToken('@odx/auth::ErrorHandlers', {
120
- providedIn: 'root',
121
- factory: () => [],
122
- });
123
- const ODX_AUTH_PLUGINS = new InjectionToken('@odx/auth::Plugins', {
124
- providedIn: 'root',
125
- factory: () => {
126
- const { plugins } = injectAuthConfig();
127
- const corePlugins = inject(ODX_AUTH_CORE_PLUGINS);
128
- return [...corePlugins, ...plugins].map((pluginFactory) => pluginFactory());
129
- },
130
- });
131
- const { AuthDefaultConfig, AuthConfig, injectAuthConfig, provideAuthConfig } = createConfigTokens('Auth', '@odx/auth', {
132
- environment: 'prod',
133
- redirectPath: 'login/callback',
134
- allowedUrls: [],
135
- timeoutFactor: 0.75,
136
- maxOfflineTime: 24 * 60 * 60,
137
- loadUserProfile: false,
138
- errorHandler: (error) => {
139
- throw error;
140
- },
141
- createInitials,
142
- resolveEmail,
143
- resolveUsername,
144
- plugins: [],
145
- defaultAuthorizedHandler: null,
146
- enableLoadingScreen: true,
147
- loadingScreenMessage: null,
148
- refreshTokenOnInit: true,
149
- requireSignIn: false,
150
- });
109
+ function setHttpAuthHeader(req, token) {
110
+ if (!token)
111
+ return req;
112
+ const header = `Bearer ${token}`;
113
+ if (req instanceof HttpRequest) {
114
+ return req.clone({ headers: req.headers.set(AUTH_HTTP_HEADER, header) });
115
+ }
116
+ req.headers.set(AUTH_HTTP_HEADER, header);
117
+ return req;
118
+ }
151
119
 
152
- var translations = {
153
- en: {
154
- userProfileLink: 'My profile',
155
- signInButtonText: 'Sign in',
156
- signOutButtonText: 'Sign out',
157
- },
158
- de: {
159
- userProfileLink: 'Mein Profil',
160
- signInButtonText: 'Einloggen',
161
- signOutButtonText: 'Ausloggen',
162
- },
163
- };
120
+ const AuthEnvironment = Environment;
164
121
 
165
122
  const ODX_AUTH_HTTP_CACHE_STORAGE = new InjectionToken('@odx/auth::AuthHttpCacheStorage', {
166
123
  providedIn: 'root',
167
124
  factory: () => inject(WindowRef).nativeWindow.caches,
168
125
  });
126
+ const ODX_AUTH_HTTP_CACHE_STORAGE_CLIENT = new InjectionToken('@odx/auth::AuthHttpCacheStorageClient', {
127
+ providedIn: 'root',
128
+ factory: () => new CacheStorageClient('@odx/auth/http-cache', inject(ODX_AUTH_HTTP_CACHE_STORAGE)),
129
+ });
169
130
  class AuthHttpCache {
170
- static { this.CACHE_KEY = '@odx/auth/http-cache'; }
171
131
  constructor() {
172
- this.cacheStorage = inject(ODX_AUTH_HTTP_CACHE_STORAGE);
132
+ this.cacheStorage = inject(ODX_AUTH_HTTP_CACHE_STORAGE_CLIENT);
173
133
  this.oauthService = inject(OAuthService);
134
+ this.injector = inject(Injector);
174
135
  this.oauthService.events.pipe(handleOAuthEvent('logout', () => this.deleteAll())).subscribe();
175
136
  }
176
137
  async deleteAll() {
177
- const cache = await this.cacheStorage.open(AuthHttpCache.CACHE_KEY);
178
- for (const key of await cache.keys()) {
179
- await cache.delete(key);
180
- }
138
+ await this.cacheStorage.deleteAll();
181
139
  }
182
140
  async delete(request) {
183
- const cache = await this.cacheStorage.open(AuthHttpCache.CACHE_KEY);
184
- return cache.delete(request);
141
+ return this.cacheStorage.delete(request);
185
142
  }
186
143
  async request(requestInfo, authentication = false) {
187
- const request = new Request(requestInfo);
188
- const authorizationHeader = authentication ? this.oauthService.authorizationHeader() : null;
189
- if (authorizationHeader) {
190
- request.headers.set('Authorization', authorizationHeader);
144
+ if (authentication) {
145
+ const authService = this.injector.get(AuthService);
146
+ const request = await firstValueFrom(authService.prepareAuthRequest$(new Request(requestInfo)));
147
+ return this.cacheStorage.request(request, ({ status }) => request.headers.has(AUTH_HTTP_HEADER) && status === 401);
191
148
  }
192
- const cache = await this.cacheStorage.open(AuthHttpCache.CACHE_KEY);
193
- const response = await fetch(request).catch(() => null);
194
- if (response?.ok) {
195
- await cache.put(request, response).catch(() => null);
196
- }
197
- if (authorizationHeader && response?.status === 401) {
198
- await cache.delete(request);
199
- }
200
- return cache.match(request).then((res) => res?.json() ?? null);
149
+ return this.cacheStorage.request(requestInfo, () => false);
201
150
  }
202
151
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthHttpCache, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
203
152
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthHttpCache, providedIn: 'root' }); }
@@ -207,8 +156,183 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
207
156
  args: [{ providedIn: 'root' }]
208
157
  }], ctorParameters: function () { return []; } });
209
158
 
159
+ const authInterceptor = (req, next) => {
160
+ const { allowedUrls, requireSignInForRequests } = injectAuthConfig();
161
+ const isUrlAllowed = allowedUrls.some((allowedUrl) => matchUrl(req.url, allowedUrl));
162
+ if (!isUrlAllowed) {
163
+ return next(req);
164
+ }
165
+ const authService = inject(AuthService);
166
+ return authService.prepareAuthRequest$(req, requireSignInForRequests).pipe(mergeMap(next));
167
+ };
168
+
169
+ var logger = new Logger('@odx/auth');
170
+
171
+ let AuthActionsComponent = class AuthActionsComponent {
172
+ constructor() {
173
+ this.element = injectElement();
174
+ this.claims = null;
175
+ }
176
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
177
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthActionsComponent, isStandalone: true, selector: "odx-auth-actions", inputs: { claims: "claims" }, ngImport: i0, template: "<odx-list>\n <a data-testid=\"odx-auth-user-profile-link\" odxListItem [href]=\"url\" rel=\"noopener\" target=\"_blank\" *ngIf=\"claims?.userProfileUrl as url\">\n <odx-icon name=\"user-administration\" iconSet=\"core\" odxListPrefix></odx-icon>\n {{ 'userProfileLink' | odxTranslate | async }}\n </a>\n</odx-list>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ListModule }, { kind: "component", type: i2.ListComponent, selector: "odx-list" }, { kind: "component", type: i2.ListItemComponent, selector: "odx-list-item, [odxListItem]", inputs: ["danger", "selected"] }, { kind: "component", type: i3.IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "pipe", type: TranslatePipe, name: "odxTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
178
+ };
179
+ AuthActionsComponent = __decorate([
180
+ CSSComponent('auth-actions')
181
+ ], AuthActionsComponent);
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthActionsComponent, decorators: [{
183
+ type: Component,
184
+ args: [{ standalone: true, selector: 'odx-auth-actions', imports: [CoreModule, ListModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<odx-list>\n <a data-testid=\"odx-auth-user-profile-link\" odxListItem [href]=\"url\" rel=\"noopener\" target=\"_blank\" *ngIf=\"claims?.userProfileUrl as url\">\n <odx-icon name=\"user-administration\" iconSet=\"core\" odxListPrefix></odx-icon>\n {{ 'userProfileLink' | odxTranslate | async }}\n </a>\n</odx-list>\n" }]
185
+ }], propDecorators: { claims: [{
186
+ type: Input
187
+ }] } });
188
+
189
+ class AuthLoadingScreenComponent {
190
+ constructor() {
191
+ this.authConfig = injectAuthConfig();
192
+ this.icon$ = inject(AuthService).isRedirecting$.pipe(map((isRedirecting) => (isRedirecting ? 'link-external' : 'user')));
193
+ }
194
+ static { this.instance = null; }
195
+ static initialize(authService, dynamicViewService) {
196
+ authService.isLoading$.subscribe((isLoading) => {
197
+ if (isLoading) {
198
+ AuthLoadingScreenComponent.instance ??= dynamicViewService.createView(AuthLoadingScreenComponent);
199
+ }
200
+ else {
201
+ AuthLoadingScreenComponent.instance?.destroy();
202
+ AuthLoadingScreenComponent.instance = null;
203
+ }
204
+ });
205
+ }
206
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthLoadingScreenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
207
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthLoadingScreenComponent, isStandalone: true, selector: "div.odx-auth-loading-screen", host: { properties: { "@hostAnimation": "true" } }, ngImport: i0, template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\" />\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\" />\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\" />\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);inset:0;position:fixed;z-index:var(--odx-v-layer-5)}.odx-auth-loading-screen__content{animation:odx-auth-loading-screen-animation .75s ease;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "component", type: CircularProgressComponent, selector: "odx-circular-progress", inputs: ["stroke", "size", "value"] }, { kind: "directive", type: DynamicViewDirective, selector: "ng-template[odxDynamicView]", inputs: ["odxDynamicView", "odxDynamicViewInjector", "odxDynamicViewContext"] }], animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
208
+ }
209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthLoadingScreenComponent, decorators: [{
210
+ type: Component,
211
+ args: [{ standalone: true, selector: 'div.odx-auth-loading-screen', imports: [CommonModule, ButtonComponent, IconComponent, LogoDirective, CircularProgressComponent, DynamicViewDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
212
+ '[@hostAnimation]': 'true',
213
+ }, animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\" />\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\" />\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\" />\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);inset:0;position:fixed;z-index:var(--odx-v-layer-5)}.odx-auth-loading-screen__content{animation:odx-auth-loading-screen-animation .75s ease;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}\n"] }]
214
+ }] });
215
+
216
+ const coreDebugPlugin = () => {
217
+ logger.warn('DEBUG MODE ENABLED - DO NOT USE IN PRODUCTION!');
218
+ const destroyRef = inject(DestroyRef);
219
+ let instance = null;
220
+ return (authService) => {
221
+ instance ??= authService.identityClaims$.pipe(takeUntilDestroyed(destroyRef)).subscribe((claims) => {
222
+ logger.info(`User: ${claims?.username} (${claims?.email})`);
223
+ logger.group('Identity claims', (log) => log(claims), false);
224
+ logger.group('Access token', (log) => log(authService.getAccessToken()));
225
+ logger.group('Refresh token', (log) => log(authService.getRefreshToken()));
226
+ logger.group('ID token', (log) => log(authService.getIdToken()));
227
+ });
228
+ return of({});
229
+ };
230
+ };
231
+
232
+ const coreIdentityPlugin = () => {
233
+ const { resolveEmail, resolveUsername, createInitials } = injectAuthConfig();
234
+ return (authService) => {
235
+ const claims = authService.getRawIdentityClaims();
236
+ if (!claims)
237
+ return of({});
238
+ const username = resolveUsername(claims);
239
+ return of({ email: resolveEmail(claims), username, initials: createInitials(username) });
240
+ };
241
+ };
242
+
243
+ const userProfileUrlPlugin = () => {
244
+ const { environment, userProfileUrl } = injectAuthConfig();
245
+ return () => {
246
+ return of({ userProfileUrl: userProfileUrl ?? ODX_AUTH_USER_PROFILE_HOSTS[environment] });
247
+ };
248
+ };
249
+
250
+ const ODX_AUTH_ERROR_HANDLERS = new InjectionToken('@odx/auth::ErrorHandlers', {
251
+ providedIn: 'root',
252
+ factory: () => {
253
+ const { errorHandler } = injectAuthConfig();
254
+ return [offlineAuthErrorHandler, errorHandler];
255
+ },
256
+ });
257
+ const ODX_AUTH_CORE_PLUGINS = new InjectionToken('@odx/auth::CorePlugins', {
258
+ providedIn: 'root',
259
+ factory: () => {
260
+ const { showDebugInformation } = injectAuthConfig();
261
+ const plugins = [coreIdentityPlugin, userProfileUrlPlugin];
262
+ if (showDebugInformation) {
263
+ plugins.push(coreDebugPlugin);
264
+ }
265
+ return plugins;
266
+ },
267
+ });
268
+ const ODX_AUTH_PLUGINS = new InjectionToken('@odx/auth::Plugins', {
269
+ providedIn: 'root',
270
+ factory: () => {
271
+ const { plugins } = injectAuthConfig();
272
+ const corePlugins = inject(ODX_AUTH_CORE_PLUGINS);
273
+ return [...corePlugins, ...plugins].map((pluginFactory) => pluginFactory());
274
+ },
275
+ });
276
+ function provideAuthLogger() {
277
+ return {
278
+ provide: ENVIRONMENT_INITIALIZER,
279
+ useFactory: () => {
280
+ const { showDebugInformation } = injectAuthConfig();
281
+ if (!showDebugInformation)
282
+ logger.disable();
283
+ return () => void 0;
284
+ },
285
+ multi: true,
286
+ };
287
+ }
288
+ function initializeAuthErrorHandlers() {
289
+ const authService = inject(AuthService);
290
+ const handler = handleAuthError(inject(ODX_AUTH_ERROR_HANDLERS));
291
+ authService.errors$.pipe(tap((error) => handler(error))).subscribe();
292
+ }
293
+ function initalizeAuthConfig() {
294
+ const { clientId, scopes, redirectPath, environment, postLogoutRedirectUrl, issuer, timeoutFactor, discoveryUrl, enableLoadingScreen } = injectAuthConfig();
295
+ const authService = inject(AuthService);
296
+ const redirectUri = buildUrl(inject(WindowRef).getOrigin(), redirectPath);
297
+ const scope = Array.from(new Set(ODX_AUTH_DEFAULT_SCOPES.concat(scopes ?? []))).join(' ');
298
+ if (enableLoadingScreen) {
299
+ AuthLoadingScreenComponent.initialize(authService, inject(DynamicViewService));
300
+ }
301
+ return () => authService.initialize({
302
+ clientId,
303
+ issuer: issuer ?? createAuthHostUrl(environment, 'oauth2/default'),
304
+ scope,
305
+ redirectUri,
306
+ postLogoutRedirectUri: postLogoutRedirectUrl,
307
+ preserveRequestedRoute: true,
308
+ strictDiscoveryDocumentValidation: !discoveryUrl,
309
+ responseType: 'code',
310
+ showDebugInformation: false,
311
+ timeoutFactor,
312
+ waitForTokenInMsec: 1000,
313
+ });
314
+ }
315
+ function provideAuth(config) {
316
+ return makeEnvironmentProviders([
317
+ provideAuthConfig(config),
318
+ provideAuthLogger(),
319
+ provideOAuthClient({ resourceServer: { sendAccessToken: false, allowedUrls: [] } }),
320
+ provideHttpClient(withInterceptors([authInterceptor])),
321
+ {
322
+ provide: APP_INITIALIZER,
323
+ useFactory: initalizeAuthConfig,
324
+ multi: true,
325
+ },
326
+ {
327
+ provide: OAuthStorage,
328
+ useFactory: () => injectAuthConfig().storage ?? inject(WindowRef).nativeWindow.localStorage,
329
+ },
330
+ ]);
331
+ }
332
+
210
333
  class AuthPluginManager {
211
334
  constructor() {
335
+ this.authConfig = injectAuthConfig();
212
336
  this.errorHandler = inject(ErrorHandler, { optional: true });
213
337
  this.plugins = inject(ODX_AUTH_PLUGINS);
214
338
  this.result$$ = new BehaviorSubject(null);
@@ -219,12 +343,11 @@ class AuthPluginManager {
219
343
  if (this.plugins.length < 1) {
220
344
  return of({});
221
345
  }
222
- return authService.isInitialized$.pipe(switchMap(() => {
223
- if (!authService.getAccessToken()) {
224
- return of({});
225
- }
226
- return combineLatest(this.plugins.map((plugin) => plugin(authService).pipe(catchError(this.handlePluginError.bind(this))))).pipe(map((results) => deepmerge(...results)));
227
- }), tap((result) => this.result$$.next(result)), take(1));
346
+ return authService.waitForAccessToken$(false).pipe(switchMap((token) => {
347
+ if (!token)
348
+ return of([{}]);
349
+ return combineLatest(this.plugins.map((plugin) => this.runPlugin(authService, plugin)));
350
+ }), map((results) => deepmerge(...results)), tap((result) => this.result$$.next(result)), take(1));
228
351
  }
229
352
  getResult() {
230
353
  return this.result$$.getValue() ?? {};
@@ -233,6 +356,9 @@ class AuthPluginManager {
233
356
  this.errorHandler?.handleError(error);
234
357
  return of({});
235
358
  }
359
+ runPlugin(authService, plugin) {
360
+ return plugin(authService).pipe(isNumber(this.authConfig.pluginTimeout) ? timeout(this.authConfig.pluginTimeout) : tap(), catchError(this.handlePluginError.bind(this)));
361
+ }
236
362
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPluginManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
237
363
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPluginManager, providedIn: 'root' }); }
238
364
  }
@@ -263,10 +389,11 @@ class AuthService {
263
389
  this.isInitialized$ = this.isInitialized$$.pipe(filter(Boolean), distinctUntilChanged());
264
390
  this.isRedirecting$ = this.isRedirecting$$.pipe(distinctUntilChanged(), shareReplay({ refCount: true }));
265
391
  this.isLoading$ = merge(this.isRedirecting$, this.authPluginManager.pluginsLoading$).pipe(distinctUntilChanged());
266
- this.isAuthenticated$ = this.isInitialized$.pipe(switchMap(() => this.authPluginManager.pluginsReady$), switchMap(() => this.onAuthStateChange$), map(() => this.isAuthenticated()), shareReplay({ refCount: true }));
392
+ this.isAuthenticated$ = this.isInitialized$.pipe(switchMap(() => this.authPluginManager.pluginsReady$), switchMap(() => this.onAuthStateChange$), map(() => this.isAuthenticated()), distinctUntilChanged(), shareReplay({ refCount: true }));
267
393
  this.identityClaims$ = this.isAuthenticated$.pipe(map(() => this.getIdentityClaims()), shareReplay({ refCount: true }));
268
394
  this.errors$ = this.oauthService.events.pipe(filter((event) => event instanceof OAuthErrorEvent), share());
269
- this.authPluginManager.runPlugins(this).subscribe();
395
+ this.onTokenReceived$ = this.oauthService.events.pipe(filter((event) => event.type === 'token_received'), share());
396
+ this.runPlugins();
270
397
  this.silentRefreshHandler$.subscribe();
271
398
  }
272
399
  async initialize(config) {
@@ -275,7 +402,9 @@ class AuthService {
275
402
  try {
276
403
  await this.oauthService.loadDiscoveryDocument(this.authConfig.discoveryUrl);
277
404
  await this.oauthService.tryLogin();
278
- await this.tryRefreshToken();
405
+ if (this.authConfig.refreshTokenOnInit) {
406
+ await this.tryRefreshToken();
407
+ }
279
408
  }
280
409
  catch (error) {
281
410
  if (!(error instanceof HttpErrorResponse || error instanceof OAuthErrorEvent)) {
@@ -293,6 +422,9 @@ class AuthService {
293
422
  await this.tryLoadUserProfile();
294
423
  await this.routeToRequestedUrl();
295
424
  }
425
+ runPlugins() {
426
+ this.authPluginManager.runPlugins(this).subscribe();
427
+ }
296
428
  getIssuer() {
297
429
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
298
430
  return new URL(this.oauthService.issuer);
@@ -303,9 +435,6 @@ class AuthService {
303
435
  signOut(noRedirect) {
304
436
  this.oauthService.logOut(noRedirect || !this.getAccessToken());
305
437
  }
306
- async loadUserProfile() {
307
- await this.oauthService.loadUserProfile();
308
- }
309
438
  async refreshTokens() {
310
439
  return this.oauthService.refreshToken();
311
440
  }
@@ -341,6 +470,14 @@ class AuthService {
341
470
  isAuthorized$(authorizedHandler) {
342
471
  return this.isAuthenticated$.pipe(map(() => this.isAuthorized(authorizedHandler)));
343
472
  }
473
+ prepareAuthRequest$(req, requireSignIn = false) {
474
+ return this.waitForAccessToken$(requireSignIn).pipe(map((token) => setHttpAuthHeader(req, token)));
475
+ }
476
+ waitForAccessToken$(requireSignIn) {
477
+ const accessToken$ = of(this.getAccessToken()).pipe(filter((token) => !!token && this.isAuthenticated()));
478
+ const waitForAccessToken$ = this.onTokenReceived$.pipe(timeout(this.authConfig.waitForTokenInMs), catchError(async () => this.tryRefreshToken().catch(() => null)));
479
+ return this.isInitialized$.pipe(switchMap(() => merge(accessToken$, waitForAccessToken$)), take(1), map(() => this.getAccessToken()), tap((token) => !token && requireSignIn && this.signIn(this.windowRef.location.pathname)));
480
+ }
344
481
  async routeToRequestedUrl() {
345
482
  if (!this.oauthService.state || !this.oauthService.hasValidAccessToken())
346
483
  return;
@@ -354,15 +491,15 @@ class AuthService {
354
491
  this.windowRef.location.assign(uri);
355
492
  this.isRedirecting$$.next(true);
356
493
  }
357
- async tryRefreshToken() {
358
- if (!this.authConfig.refreshTokenOnInit || !this.getRefreshToken())
494
+ async tryLoadUserProfile() {
495
+ if (!this.authConfig.loadUserProfile || !this.isAuthenticated())
359
496
  return;
360
- await this.oauthService.refreshToken();
497
+ await this.oauthService.loadUserProfile().catch(() => null);
361
498
  }
362
- async tryLoadUserProfile() {
363
- if (!this.authConfig.loadUserProfile || !this.oauthService.hasValidAccessToken())
499
+ async tryRefreshToken() {
500
+ if (!this.getRefreshToken())
364
501
  return;
365
- await this.loadUserProfile().catch(() => null);
502
+ await this.oauthService.refreshToken();
366
503
  }
367
504
  assertAudience(clientId) {
368
505
  const tokenClientId = this.getIdentityClaims()?.aud;
@@ -386,50 +523,56 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
386
523
  args: [{ providedIn: 'root' }]
387
524
  }], ctorParameters: function () { return []; } });
388
525
 
389
- let AuthActionsComponent = class AuthActionsComponent {
390
- constructor() {
391
- this.element = injectElement();
392
- this.claims = null;
393
- }
394
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
395
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthActionsComponent, isStandalone: true, selector: "odx-auth-actions", inputs: { claims: "claims" }, ngImport: i0, template: "<odx-list>\n <a data-testid=\"odx-auth-user-profile-link\" odxListItem [href]=\"url\" rel=\"noopener\" target=\"_blank\" *ngIf=\"claims?.userProfileUrl as url\">\n <odx-icon name=\"user-administration\" iconSet=\"core\" odxListPrefix></odx-icon>\n {{ 'userProfileLink' | odxTranslate | async }}\n </a>\n</odx-list>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ListModule }, { kind: "component", type: i2.ListComponent, selector: "odx-list" }, { kind: "component", type: i2.ListItemComponent, selector: "odx-list-item, [odxListItem]", inputs: ["danger", "selected"] }, { kind: "component", type: i3.IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "pipe", type: TranslatePipe, name: "odxTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
526
+ function userLanguageLoader(languageSelector = (claims) => claims?.preferredLanguage) {
527
+ return () => {
528
+ return inject(AuthService).identityClaims$.pipe(map(languageSelector), map((value) => (isNonEmptyString(value) ? value : undefined)));
529
+ };
530
+ }
531
+
532
+ const AUTH_HTTP_HEADER = 'Authorization';
533
+ const ODX_AUTH_DEFAULT_SCOPES = ['openid', 'profile', 'email', 'offline_access'];
534
+ const ODX_AUTH_HOSTS = {
535
+ dev: 'https://dev.login.draeger.com',
536
+ stage: 'https://test.login.draeger.com',
537
+ prod: 'https://login.draeger.com',
396
538
  };
397
- AuthActionsComponent = __decorate([
398
- CSSComponent('auth-actions')
399
- ], AuthActionsComponent);
400
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthActionsComponent, decorators: [{
401
- type: Component,
402
- args: [{ standalone: true, selector: 'odx-auth-actions', imports: [CoreModule, ListModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<odx-list>\n <a data-testid=\"odx-auth-user-profile-link\" odxListItem [href]=\"url\" rel=\"noopener\" target=\"_blank\" *ngIf=\"claims?.userProfileUrl as url\">\n <odx-icon name=\"user-administration\" iconSet=\"core\" odxListPrefix></odx-icon>\n {{ 'userProfileLink' | odxTranslate | async }}\n </a>\n</odx-list>\n" }]
403
- }], propDecorators: { claims: [{
404
- type: Input
405
- }] } });
539
+ const ODX_AUTH_USER_PROFILE_HOSTS = {
540
+ dev: 'https://lemon-ocean-04a922703.3.azurestaticapps.net',
541
+ stage: 'https://purple-cliff-0e61c5703.3.azurestaticapps.net',
542
+ prod: 'https://id.draeger.com',
543
+ };
544
+ const { AuthDefaultConfig, AuthConfig, injectAuthConfig, provideAuthConfig } = createConfigTokens('Auth', '@odx/auth', {
545
+ environment: 'prod',
546
+ redirectPath: 'login/callback',
547
+ allowedUrls: [],
548
+ timeoutFactor: 0.75,
549
+ maxOfflineTime: 24 * 60 * 60,
550
+ loadUserProfile: false,
551
+ errorHandler: (error) => {
552
+ throw error;
553
+ },
554
+ createInitials,
555
+ resolveEmail,
556
+ resolveUsername,
557
+ plugins: [],
558
+ defaultAuthorizedHandler: null,
559
+ enableLoadingScreen: true,
560
+ loadingScreenMessage: null,
561
+ waitForTokenInMs: 1000,
562
+ });
406
563
 
407
- class AuthLoadingScreenComponent {
408
- constructor() {
409
- this.authConfig = injectAuthConfig();
410
- this.icon$ = inject(AuthService).isRedirecting$.pipe(distinctUntilChanged(), map((isRedirecting) => (isRedirecting ? 'link-external' : 'user')));
411
- }
412
- static { this.instance = null; }
413
- static initialize(authService, dynamicViewService) {
414
- authService.isLoading$.subscribe((isLoading) => {
415
- if (isLoading) {
416
- AuthLoadingScreenComponent.instance ??= dynamicViewService.createView(AuthLoadingScreenComponent);
417
- }
418
- else {
419
- AuthLoadingScreenComponent.instance?.destroy();
420
- AuthLoadingScreenComponent.instance = null;
421
- }
422
- });
423
- }
424
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthLoadingScreenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
425
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthLoadingScreenComponent, isStandalone: true, selector: "div.odx-auth-loading-screen", host: { properties: { "@hostAnimation": "true" } }, ngImport: i0, template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\"></ng-template>\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-loading-screen__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-loading-screen-animation .75s ease}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "component", type: CircularProgressComponent, selector: "odx-circular-progress", inputs: ["stroke", "size", "value"] }, { kind: "directive", type: DynamicViewDirective, selector: "ng-template[odxDynamicView]", inputs: ["odxDynamicView", "odxDynamicViewInjector", "odxDynamicViewContext"] }], animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
426
- }
427
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthLoadingScreenComponent, decorators: [{
428
- type: Component,
429
- args: [{ standalone: true, selector: 'div.odx-auth-loading-screen', imports: [CommonModule, ButtonComponent, IconComponent, LogoDirective, CircularProgressComponent, DynamicViewDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
430
- '[@hostAnimation]': 'true',
431
- }, animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\"></ng-template>\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-loading-screen__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-loading-screen-animation .75s ease}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"] }]
432
- }] });
564
+ var translations = {
565
+ en: {
566
+ userProfileLink: 'My profile',
567
+ signInButtonText: 'Sign in',
568
+ signOutButtonText: 'Sign out',
569
+ },
570
+ de: {
571
+ userProfileLink: 'Mein Profil',
572
+ signInButtonText: 'Einloggen',
573
+ signOutButtonText: 'Ausloggen',
574
+ },
575
+ };
433
576
 
434
577
  class AuthActionDirective {
435
578
  constructor() {
@@ -571,9 +714,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
571
714
  }] } });
572
715
 
573
716
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
574
- function authGuard(authorizedHandler, redirectTo) {
717
+ function authGuard(authorizedHandler, redirectTo, isExternal = false) {
575
718
  return (_, state) => {
576
719
  const authService = inject(AuthService);
720
+ const windowRef = inject(WindowRef);
577
721
  const router = inject(Router, { optional: true });
578
722
  return authService.isAuthenticated$.pipe(switchMap((isAuthenticated) => {
579
723
  if (!isAuthenticated) {
@@ -585,7 +729,12 @@ function authGuard(authorizedHandler, redirectTo) {
585
729
  if (isAuthorized || !router)
586
730
  return;
587
731
  if (isString(redirectTo)) {
588
- router.navigateByUrl(redirectTo);
732
+ if (isExternal) {
733
+ windowRef.location.assign(redirectTo);
734
+ }
735
+ else {
736
+ router.navigateByUrl(redirectTo);
737
+ }
589
738
  }
590
739
  else if (Array.isArray(redirectTo)) {
591
740
  router.navigate(redirectTo);
@@ -608,103 +757,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
608
757
  }]
609
758
  }] });
610
759
 
611
- const coreIdentityPlugin = () => {
612
- const { resolveEmail, resolveUsername, createInitials } = injectAuthConfig();
613
- return (authService) => {
614
- const claims = authService.getRawIdentityClaims();
615
- if (!claims)
616
- return of({});
617
- const username = resolveUsername(claims);
618
- return of({ email: resolveEmail(claims), username, initials: createInitials(username) });
619
- };
620
- };
621
-
622
- const userProfileUrlPlugin = () => {
623
- const { environment, userProfileUrl } = injectAuthConfig();
624
- return () => {
625
- return of({ userProfileUrl: userProfileUrl ?? DEFAULT_USER_PROFILE_URLS[environment] });
626
- };
627
- };
628
-
629
- function configureInterceptor() {
630
- const { allowedUrls } = injectAuthConfig();
631
- const urls = allowedUrls.filter(Boolean);
632
- return {
633
- resourceServer: {
634
- customUrlValidation: (url) => urls.some((allowedUrl) => (isString(allowedUrl) ? url.startsWith(allowedUrl) : !!url.match(allowedUrl))),
635
- sendAccessToken: true,
636
- },
637
- };
638
- }
639
- function initializeAuthErrorHandlers() {
640
- const authService = inject(AuthService);
641
- const handler = handleAuthError(inject(ODX_AUTH_ERROR_HANDLERS));
642
- authService.errors$.pipe(tap((error) => handler(error))).subscribe();
643
- }
644
- function initalizeAuthConfig() {
645
- const { clientId, scopes, redirectPath, environment, postLogoutRedirectUrl, issuer, timeoutFactor, discoveryUrl, enableLoadingScreen } = injectAuthConfig();
646
- const authService = inject(AuthService);
647
- const origin = inject(WindowRef).getOrigin();
648
- const scope = Array.from(new Set(DEFAULT_AUTH_SCOPES.concat(scopes ?? []))).join(' ');
649
- if (enableLoadingScreen) {
650
- AuthLoadingScreenComponent.initialize(authService, inject(DynamicViewService));
651
- }
652
- return () => authService.initialize({
653
- clientId,
654
- issuer: issuer ?? `${DEFAULT_OKTA_URLS[environment]}/oauth2/default`,
655
- scope,
656
- redirectUri: buildUrl(origin, redirectPath),
657
- postLogoutRedirectUri: postLogoutRedirectUrl,
658
- preserveRequestedRoute: true,
659
- strictDiscoveryDocumentValidation: !discoveryUrl,
660
- responseType: 'code',
661
- showDebugInformation: environment === 'dev',
662
- timeoutFactor,
663
- });
664
- }
665
- function provideAuth(config) {
666
- return makeEnvironmentProviders([
667
- provideAuthConfig(config),
668
- provideOAuthClient(),
669
- {
670
- provide: OAuthModuleConfig,
671
- useFactory: configureInterceptor,
672
- },
673
- {
674
- provide: ENVIRONMENT_INITIALIZER,
675
- useValue: initializeAuthErrorHandlers,
676
- multi: true,
677
- },
678
- {
679
- provide: ODX_AUTH_ERROR_HANDLERS,
680
- useFactory: () => [offlineAuthErrorHandler, injectAuthConfig().errorHandler],
681
- },
682
- {
683
- provide: APP_INITIALIZER,
684
- useFactory: initalizeAuthConfig,
685
- multi: true,
686
- },
687
- {
688
- provide: OAuthStorage,
689
- useFactory: () => injectAuthConfig().storage ?? inject(WindowRef).nativeWindow.localStorage,
690
- },
691
- {
692
- provide: ODX_AUTH_CORE_PLUGINS,
693
- useValue: [coreIdentityPlugin, userProfileUrlPlugin],
694
- },
695
- ]);
696
- }
697
-
698
760
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
699
- function unauthGuard(authorizedHandler, redirectTo) {
761
+ function unauthGuard(authorizedHandler, redirectTo, isExternal = false) {
700
762
  return (_) => {
701
763
  const authService = inject(AuthService);
702
764
  const router = inject(Router, { optional: true });
765
+ const windowRef = inject(WindowRef);
703
766
  return authService.isAuthenticated$.pipe(map(() => !authService.isAuthorized(authorizedHandler)), tap((isUnauthorized) => {
704
767
  if (isUnauthorized || !router)
705
768
  return;
706
769
  if (isString(redirectTo)) {
707
- router.navigateByUrl(redirectTo);
770
+ if (isExternal) {
771
+ windowRef.location.assign(redirectTo);
772
+ }
773
+ else {
774
+ router.navigateByUrl(redirectTo);
775
+ }
708
776
  }
709
777
  else if (Array.isArray(redirectTo)) {
710
778
  router.navigate(redirectTo);
@@ -717,5 +785,5 @@ function unauthGuard(authorizedHandler, redirectTo) {
717
785
  * Generated bundle index. Do not edit.
718
786
  */
719
787
 
720
- export { AuthActionDirective, AuthActionsComponent, AuthComponent, AuthConfig, AuthDefaultConfig, AuthDirective, AuthHttpCache, AuthLoadingScreenComponent, AuthModule, AuthPluginManager, AuthService, DEFAULT_AUTH_SCOPES, DEFAULT_OKTA_URLS, DEFAULT_USER_PROFILE_URLS, ODX_AUTH_CORE_PLUGINS, ODX_AUTH_ERROR_HANDLERS, ODX_AUTH_HTTP_CACHE_STORAGE, ODX_AUTH_PLUGINS, SignInDirective, SignOutDirective, authGuard, configureInterceptor, coreIdentityPlugin, createInitials, handleAuthError, handleOAuthEvent, initalizeAuthConfig, initializeAuthErrorHandlers, injectAuthConfig, offlineAuthErrorHandler, provideAuth, provideAuthConfig, resolveEmail, resolveUsername, unauthGuard, userProfileUrlPlugin };
788
+ export { AUTH_HTTP_HEADER, AuthActionDirective, AuthActionsComponent, AuthComponent, AuthConfig, AuthDefaultConfig, AuthDirective, AuthEnvironment, AuthHttpCache, AuthLoadingScreenComponent, AuthModule, AuthPluginManager, AuthService, ODX_AUTH_CORE_PLUGINS, ODX_AUTH_DEFAULT_SCOPES, ODX_AUTH_ERROR_HANDLERS, ODX_AUTH_HOSTS, ODX_AUTH_HTTP_CACHE_STORAGE, ODX_AUTH_HTTP_CACHE_STORAGE_CLIENT, ODX_AUTH_PLUGINS, ODX_AUTH_USER_PROFILE_HOSTS, SignInDirective, SignOutDirective, authGuard, authInterceptor, coreDebugPlugin, coreIdentityPlugin, createAuthHostUrl, createInitials, handleAuthError, handleOAuthEvent, initalizeAuthConfig, initializeAuthErrorHandlers, injectAuthConfig, offlineAuthErrorHandler, provideAuth, provideAuthConfig, provideAuthLogger, resolveEmail, resolveUsername, setHttpAuthHeader, unauthGuard, userLanguageLoader, userProfileUrlPlugin };
721
789
  //# sourceMappingURL=odx-auth.mjs.map