@onecx/shell-auth 8.0.0-rc.4 → 8.0.0-rc.5

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.
@@ -0,0 +1,353 @@
1
+ import { loadRemoteModule } from '@angular-architects/module-federation';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, Injectable, Injector, provideAppInitializer } from '@angular/core';
4
+ import { ConfigurationService, CONFIG_KEY, AppStateService } from '@onecx/angular-integration-interface';
5
+ import { EventsTopic, EventType } from '@onecx/integration-interface';
6
+ import { filter } from 'rxjs/internal/operators/filter';
7
+ import { createLoggerFactory } from '@onecx/accelerator';
8
+
9
+ var Injectables;
10
+ (function (Injectables) {
11
+ Injectables["KEYCLOAK_AUTH_SERVICE"] = "KEYCLOAK_AUTH_SERVICE";
12
+ Injectables["CONFIG"] = "CONFIG";
13
+ })(Injectables || (Injectables = {}));
14
+
15
+ // This file is not planned to be in the index.ts so it is private to this lib
16
+ const createLogger = createLoggerFactory('@onecx/shell-auth');
17
+
18
+ const KC_REFRESH_TOKEN_LS = 'onecx_kc_refreshToken';
19
+ const KC_ID_TOKEN_LS = 'onecx_kc_idToken';
20
+ const KC_TOKEN_LS = 'onecx_kc_token';
21
+ class KeycloakAuthService {
22
+ constructor() {
23
+ this.logger = createLogger('KeycloakAuthService');
24
+ this.configService = inject(ConfigurationService);
25
+ }
26
+ async init(config) {
27
+ this.config = config;
28
+ let token = localStorage.getItem(KC_TOKEN_LS);
29
+ let idToken = localStorage.getItem(KC_ID_TOKEN_LS);
30
+ let refreshToken = localStorage.getItem(KC_REFRESH_TOKEN_LS);
31
+ if (token && refreshToken) {
32
+ const parsedToken = JSON.parse(atob(refreshToken.split('.')[1]));
33
+ if (parsedToken.exp * 1000 < new Date().getTime()) {
34
+ token = null;
35
+ refreshToken = null;
36
+ idToken = null;
37
+ this.clearKCStateFromLocalstorage();
38
+ }
39
+ }
40
+ let kcConfig;
41
+ const validKCConfig = await this.getValidKCConfig();
42
+ kcConfig = { ...validKCConfig, ...(config ?? {}) };
43
+ if (!kcConfig.clientId || !kcConfig.realm || !kcConfig.url) {
44
+ kcConfig = './assets/keycloak.json';
45
+ }
46
+ const enableSilentSSOCheck = (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_ENABLE_SILENT_SSO)) === 'true';
47
+ try {
48
+ await import('keycloak-js').then(({ default: Keycloak }) => {
49
+ this.keycloak = new Keycloak(kcConfig);
50
+ });
51
+ }
52
+ catch (err) {
53
+ const errorMessage = 'Keycloak initialization failed! Could not load keycloak-js library which is required in the current environment.';
54
+ this.logger.error(errorMessage, err);
55
+ throw new Error(errorMessage);
56
+ }
57
+ if (!this.keycloak) {
58
+ throw new Error('Keycloak initialization failed!');
59
+ }
60
+ this.setupEventListener();
61
+ return this.keycloak
62
+ .init({
63
+ onLoad: 'check-sso',
64
+ checkLoginIframe: false,
65
+ silentCheckSsoRedirectUri: enableSilentSSOCheck ? this.getSilentSSOUrl() : undefined,
66
+ idToken: idToken || undefined,
67
+ refreshToken: refreshToken || undefined,
68
+ token: token || undefined,
69
+ })
70
+ .catch((err) => {
71
+ this.logger.warn(`Keycloak err: ${err}, try force login`);
72
+ return this.keycloak?.login(this.config);
73
+ })
74
+ .then((loginOk) => {
75
+ if (loginOk) {
76
+ return this.keycloak?.token;
77
+ }
78
+ else {
79
+ return this.keycloak?.login(this.config).then(() => 'login');
80
+ }
81
+ })
82
+ .then(() => {
83
+ return true;
84
+ })
85
+ .catch((err) => {
86
+ this.logger.error(`KC ERROR ${err} as json ${JSON.stringify(err)}`);
87
+ throw err;
88
+ });
89
+ }
90
+ async getValidKCConfig() {
91
+ const clientId = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_CLIENT_ID);
92
+ if (!clientId) {
93
+ throw new Error('Invalid KC config, missing clientId');
94
+ }
95
+ const realm = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_REALM);
96
+ if (!realm) {
97
+ throw new Error('Invalid KC config, missing realm');
98
+ }
99
+ const url = (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_URL)) ?? '';
100
+ return {
101
+ url,
102
+ clientId,
103
+ realm,
104
+ };
105
+ }
106
+ setupEventListener() {
107
+ if (this.keycloak) {
108
+ this.keycloak.onAuthError = () => {
109
+ this.updateLocalStorage();
110
+ };
111
+ this.keycloak.onAuthLogout = () => {
112
+ this.logger.info('SSO logout nav to root');
113
+ this.clearKCStateFromLocalstorage();
114
+ this.keycloak?.login(this.config);
115
+ };
116
+ this.keycloak.onAuthRefreshSuccess = () => {
117
+ this.updateLocalStorage();
118
+ };
119
+ this.keycloak.onAuthRefreshError = () => {
120
+ this.updateLocalStorage();
121
+ };
122
+ this.keycloak.onAuthSuccess = () => {
123
+ this.updateLocalStorage();
124
+ };
125
+ this.keycloak.onTokenExpired = () => {
126
+ this.updateLocalStorage();
127
+ };
128
+ this.keycloak.onActionUpdate = () => {
129
+ this.updateLocalStorage();
130
+ };
131
+ this.keycloak.onReady = () => {
132
+ this.updateLocalStorage();
133
+ };
134
+ }
135
+ }
136
+ updateLocalStorage() {
137
+ if (this.keycloak) {
138
+ if (this.keycloak.token) {
139
+ localStorage.setItem(KC_TOKEN_LS, this.keycloak.token);
140
+ }
141
+ else {
142
+ localStorage.removeItem(KC_TOKEN_LS);
143
+ }
144
+ if (this.keycloak.idToken) {
145
+ localStorage.setItem(KC_ID_TOKEN_LS, this.keycloak.idToken);
146
+ }
147
+ else {
148
+ localStorage.removeItem(KC_ID_TOKEN_LS);
149
+ }
150
+ if (this.keycloak.refreshToken) {
151
+ localStorage.setItem(KC_REFRESH_TOKEN_LS, this.keycloak.refreshToken);
152
+ }
153
+ else {
154
+ localStorage.removeItem(KC_REFRESH_TOKEN_LS);
155
+ }
156
+ }
157
+ }
158
+ clearKCStateFromLocalstorage() {
159
+ localStorage.removeItem(KC_ID_TOKEN_LS);
160
+ localStorage.removeItem(KC_TOKEN_LS);
161
+ localStorage.removeItem(KC_REFRESH_TOKEN_LS);
162
+ }
163
+ getSilentSSOUrl() {
164
+ let currentBase = document.getElementsByTagName('base')[0].href;
165
+ if (currentBase === '/') {
166
+ currentBase = '';
167
+ }
168
+ return `${currentBase}/assets/silent-check-sso.html`;
169
+ }
170
+ getIdToken() {
171
+ return this.keycloak?.idToken ?? null;
172
+ }
173
+ getAccessToken() {
174
+ return this.keycloak?.token ?? null;
175
+ }
176
+ logout() {
177
+ this.keycloak?.logout();
178
+ }
179
+ async updateTokenIfNeeded() {
180
+ if (!this.keycloak?.authenticated) {
181
+ return this.keycloak?.login(this.config).then(() => false) ?? Promise.reject('Keycloak not initialized!');
182
+ }
183
+ else {
184
+ return this.keycloak.updateToken();
185
+ }
186
+ }
187
+ getAuthProviderName() {
188
+ return 'keycloak-auth';
189
+ }
190
+ hasRole(_role) {
191
+ return false;
192
+ }
193
+ getUserRoles() {
194
+ return [];
195
+ }
196
+ getHeaderValues() {
197
+ return { 'apm-principal-token': this.getIdToken() ?? '', Authorization: `Bearer ${this.getAccessToken()}` };
198
+ }
199
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: KeycloakAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
200
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: KeycloakAuthService }); }
201
+ }
202
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: KeycloakAuthService, decorators: [{
203
+ type: Injectable
204
+ }] });
205
+
206
+ var globalThis$1 = globalThis;
207
+
208
+ class DisabledAuthService {
209
+ async init(_config) {
210
+ return Promise.resolve(true);
211
+ }
212
+ getIdToken() {
213
+ return "";
214
+ }
215
+ getAccessToken() {
216
+ return "";
217
+ }
218
+ logout() {
219
+ window.location.href = "https://github.com/onecx/";
220
+ }
221
+ async updateTokenIfNeeded() {
222
+ return Promise.resolve(true);
223
+ }
224
+ getHeaderValues() {
225
+ return {};
226
+ }
227
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: DisabledAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
228
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: DisabledAuthService }); }
229
+ }
230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: DisabledAuthService, decorators: [{
231
+ type: Injectable
232
+ }] });
233
+
234
+ class AuthServiceWrapper {
235
+ constructor() {
236
+ this.configService = inject(ConfigurationService);
237
+ this.appStateService = inject(AppStateService);
238
+ this.injector = inject(Injector);
239
+ this.eventsTopic$ = new EventsTopic();
240
+ this.eventsTopic$
241
+ .pipe(filter((e) => e.type === EventType.AUTH_LOGOUT_BUTTON_CLICKED))
242
+ .subscribe(() => this.authService?.logout());
243
+ // Shell defines these properties to support older library versions
244
+ window.onecxAngularAuth ??= {};
245
+ window.onecxAngularAuth.authServiceProxy ??= {};
246
+ window.onecxAngularAuth.authServiceProxy.v1 ??= {
247
+ updateTokenIfNeeded: () => {
248
+ return this.updateTokenIfNeeded();
249
+ },
250
+ getHeaderValues: () => {
251
+ return this.getHeaderValues();
252
+ },
253
+ };
254
+ window.onecxAuth ??= {};
255
+ window.onecxAuth.authServiceProxy ??= {};
256
+ window.onecxAuth.authServiceProxy.v1 ??= {
257
+ updateTokenIfNeeded: () => {
258
+ return this.updateTokenIfNeeded();
259
+ },
260
+ getHeaderValues: () => {
261
+ return this.getHeaderValues();
262
+ },
263
+ };
264
+ }
265
+ async init() {
266
+ await this.configService.isInitialized;
267
+ await this.initializeAuthService();
268
+ const initResult = this.getInitResult();
269
+ return initResult;
270
+ }
271
+ async getInitResult() {
272
+ const initResult = await this.authService?.init();
273
+ if (initResult) {
274
+ await this.appStateService.isAuthenticated$.publish();
275
+ }
276
+ return initResult;
277
+ }
278
+ getHeaderValues() {
279
+ return this.authService?.getHeaderValues() ?? {};
280
+ }
281
+ updateTokenIfNeeded() {
282
+ return this.authService?.updateTokenIfNeeded() ?? Promise.reject();
283
+ }
284
+ async initializeAuthService() {
285
+ const serviceTypeConfig = (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE)) ?? 'keycloak';
286
+ switch (serviceTypeConfig) {
287
+ case 'keycloak':
288
+ this.authService = this.injector.get(KeycloakAuthService);
289
+ break;
290
+ case 'custom': {
291
+ // remote module is exposing function as default export (this is a convention)
292
+ // this function is responsible for creating the custom auth service
293
+ // to have access to the dependency mechanism of the shell
294
+ // the function gets a callback which is returning the requested injectable
295
+ const factory = await this.getAuthServiceFactory();
296
+ this.authService = await Promise.resolve(factory((injectable) => this.retrieveInjectables(injectable)));
297
+ break;
298
+ }
299
+ case 'disabled':
300
+ this.authService = this.injector.get(DisabledAuthService);
301
+ break;
302
+ default:
303
+ throw new Error('Configured AuthService not found');
304
+ }
305
+ }
306
+ async retrieveInjectables(injectable) {
307
+ if (injectable === Injectables.KEYCLOAK_AUTH_SERVICE) {
308
+ return this.injector.get(KeycloakAuthService);
309
+ }
310
+ else if (injectable === Injectables.CONFIG) {
311
+ return this.configService.getConfig();
312
+ }
313
+ throw new Error('unknown injectable type');
314
+ }
315
+ async getAuthServiceFactory() {
316
+ if (await !this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) {
317
+ throw new Error('URL of the custom auth service is not defined');
318
+ }
319
+ const module = await loadRemoteModule({
320
+ type: 'module',
321
+ remoteEntry: (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) ?? '',
322
+ exposedModule: (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_MODULE_NAME)) ?? './CustomAuth',
323
+ });
324
+ return module.default;
325
+ }
326
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthServiceWrapper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
327
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthServiceWrapper }); }
328
+ }
329
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthServiceWrapper, decorators: [{
330
+ type: Injectable
331
+ }], ctorParameters: () => [] });
332
+
333
+ function provideAuthServices() {
334
+ return [AuthServiceWrapper, KeycloakAuthService, DisabledAuthService];
335
+ }
336
+ function provideAuthService() {
337
+ return [
338
+ provideAuthServices(),
339
+ provideAppInitializer(async () => {
340
+ const configService = inject(ConfigurationService);
341
+ const authServiceWrapper = inject(AuthServiceWrapper);
342
+ await configService.isInitialized;
343
+ await authServiceWrapper.init();
344
+ }),
345
+ ];
346
+ }
347
+
348
+ /**
349
+ * Generated bundle index. Do not edit.
350
+ */
351
+
352
+ export { AuthServiceWrapper, provideAuthService };
353
+ //# sourceMappingURL=onecx-shell-auth.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onecx-shell-auth.mjs","sources":["../../../../libs/shell-auth/src/lib/auth.service.ts","../../../../libs/shell-auth/src/lib/utils/logger.utils.ts","../../../../libs/shell-auth/src/lib/auth_services/keycloak-auth.service.ts","../../../../libs/shell-auth/src/lib/declarations.ts","../../../../libs/shell-auth/src/lib/auth_services/disabled-auth.service.ts","../../../../libs/shell-auth/src/lib/auth-service-wrapper.ts","../../../../libs/shell-auth/src/lib/provide-auth-service.ts","../../../../libs/shell-auth/src/onecx-shell-auth.ts"],"sourcesContent":["export interface AuthService {\n init(config?: Record<string, unknown>): Promise<boolean>\n\n getHeaderValues(): Record<string, string>\n\n logout(): void\n\n updateTokenIfNeeded(): Promise<boolean>\n}\n\nexport enum Injectables {\n KEYCLOAK_AUTH_SERVICE = 'KEYCLOAK_AUTH_SERVICE',\n CONFIG = 'CONFIG',\n}\n\nexport type AuthServiceFactory = (\n injectorFunction: (injectable: Injectables) => Promise<unknown> | unknown\n) => AuthService | Promise<AuthService>\n","// This file is not planned to be in the index.ts so it is private to this lib\nimport { createLoggerFactory } from '@onecx/accelerator'\n\nexport const createLogger = createLoggerFactory('@onecx/shell-auth')\n","import { Injectable, inject } from '@angular/core'\nimport { CONFIG_KEY, ConfigurationService } from '@onecx/angular-integration-interface'\nimport Keycloak, { KeycloakServerConfig } from 'keycloak-js'\nimport { AuthService } from '../auth.service'\nimport { createLogger } from '../utils/logger.utils'\n\nconst KC_REFRESH_TOKEN_LS = 'onecx_kc_refreshToken'\nconst KC_ID_TOKEN_LS = 'onecx_kc_idToken'\nconst KC_TOKEN_LS = 'onecx_kc_token'\n\n@Injectable()\nexport class KeycloakAuthService implements AuthService {\n private readonly logger = createLogger('KeycloakAuthService')\n private configService = inject(ConfigurationService)\n private keycloak: Keycloak | undefined\n\n config?: Record<string, unknown>\n\n public async init(config?: Record<string, unknown>): Promise<boolean> {\n this.config = config\n let token = localStorage.getItem(KC_TOKEN_LS)\n let idToken = localStorage.getItem(KC_ID_TOKEN_LS)\n let refreshToken = localStorage.getItem(KC_REFRESH_TOKEN_LS)\n if (token && refreshToken) {\n const parsedToken = JSON.parse(atob(refreshToken.split('.')[1]))\n if (parsedToken.exp * 1000 < new Date().getTime()) {\n token = null\n refreshToken = null\n idToken = null\n this.clearKCStateFromLocalstorage()\n }\n }\n\n let kcConfig: KeycloakServerConfig | string\n const validKCConfig = await this.getValidKCConfig()\n kcConfig = { ...validKCConfig, ...(config ?? {}) }\n \n if (!kcConfig.clientId || !kcConfig.realm || !kcConfig.url) {\n kcConfig = './assets/keycloak.json'\n }\n\n const enableSilentSSOCheck =\n (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_ENABLE_SILENT_SSO)) === 'true'\n\n try {\n await import('keycloak-js').then(({ default: Keycloak }) => {\n this.keycloak = new Keycloak(kcConfig)\n })\n } catch (err) {\n const errorMessage = 'Keycloak initialization failed! Could not load keycloak-js library which is required in the current environment.'\n this.logger.error(\n errorMessage,\n err\n )\n throw new Error(\n errorMessage\n )\n }\n\n if (!this.keycloak) {\n throw new Error('Keycloak initialization failed!')\n }\n\n this.setupEventListener()\n\n return this.keycloak\n .init({\n onLoad: 'check-sso',\n checkLoginIframe: false,\n silentCheckSsoRedirectUri: enableSilentSSOCheck ? this.getSilentSSOUrl() : undefined,\n idToken: idToken || undefined,\n refreshToken: refreshToken || undefined,\n token: token || undefined,\n })\n .catch((err) => {\n this.logger.warn(`Keycloak err: ${err}, try force login`)\n return this.keycloak?.login(this.config)\n })\n .then((loginOk) => {\n if (loginOk) {\n return this.keycloak?.token\n } else {\n return this.keycloak?.login(this.config).then(() => 'login')\n }\n })\n .then(() => {\n return true\n })\n .catch((err) => {\n this.logger.error(`KC ERROR ${err} as json ${JSON.stringify(err)}`)\n throw err\n })\n }\n\n protected async getValidKCConfig(): Promise<KeycloakServerConfig> {\n const clientId = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_CLIENT_ID)\n if (!clientId) {\n throw new Error('Invalid KC config, missing clientId')\n }\n const realm = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_REALM)\n if (!realm) {\n throw new Error('Invalid KC config, missing realm')\n }\n const url = (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_URL)) ?? ''\n return {\n url,\n clientId,\n realm,\n }\n }\n\n private setupEventListener() {\n if (this.keycloak) {\n this.keycloak.onAuthError = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onAuthLogout = () => {\n this.logger.info('SSO logout nav to root')\n this.clearKCStateFromLocalstorage()\n this.keycloak?.login(this.config)\n }\n this.keycloak.onAuthRefreshSuccess = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onAuthRefreshError = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onAuthSuccess = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onTokenExpired = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onActionUpdate = () => {\n this.updateLocalStorage()\n }\n this.keycloak.onReady = () => {\n this.updateLocalStorage()\n }\n }\n }\n\n private updateLocalStorage() {\n if (this.keycloak) {\n if (this.keycloak.token) {\n localStorage.setItem(KC_TOKEN_LS, this.keycloak.token)\n } else {\n localStorage.removeItem(KC_TOKEN_LS)\n }\n if (this.keycloak.idToken) {\n localStorage.setItem(KC_ID_TOKEN_LS, this.keycloak.idToken)\n } else {\n localStorage.removeItem(KC_ID_TOKEN_LS)\n }\n if (this.keycloak.refreshToken) {\n localStorage.setItem(KC_REFRESH_TOKEN_LS, this.keycloak.refreshToken)\n } else {\n localStorage.removeItem(KC_REFRESH_TOKEN_LS)\n }\n }\n }\n\n private clearKCStateFromLocalstorage() {\n localStorage.removeItem(KC_ID_TOKEN_LS)\n localStorage.removeItem(KC_TOKEN_LS)\n localStorage.removeItem(KC_REFRESH_TOKEN_LS)\n }\n\n private getSilentSSOUrl() {\n let currentBase = document.getElementsByTagName('base')[0].href\n if (currentBase === '/') {\n currentBase = ''\n }\n return `${currentBase}/assets/silent-check-sso.html`\n }\n\n getIdToken(): string | null {\n return this.keycloak?.idToken ?? null\n }\n getAccessToken(): string | null {\n return this.keycloak?.token ?? null\n }\n\n logout(): void {\n this.keycloak?.logout()\n }\n\n async updateTokenIfNeeded(): Promise<boolean> {\n if (!this.keycloak?.authenticated) {\n return this.keycloak?.login(this.config).then(() => false) ?? Promise.reject('Keycloak not initialized!')\n } else {\n return this.keycloak.updateToken()\n }\n }\n\n getAuthProviderName(): string {\n return 'keycloak-auth'\n }\n\n hasRole(_role: string): boolean {\n return false\n }\n\n getUserRoles(): string[] {\n return []\n }\n\n getHeaderValues(): Record<string, string> {\n return { 'apm-principal-token': this.getIdToken() ?? '', Authorization: `Bearer ${this.getAccessToken()}` }\n }\n}\n","declare global {\n interface Window {\n onecxAuth?: {\n authServiceProxy?: {\n v1?: {\n getHeaderValues: () => Record<string, string>\n updateTokenIfNeeded: () => Promise<boolean>\n }\n }\n }\n // Shell defines these properties to support older library versions\n onecxAngularAuth?: {\n authServiceProxy?: {\n v1?: {\n getHeaderValues: () => Record<string, string>\n updateTokenIfNeeded: () => Promise<boolean>\n }\n }\n }\n }\n}\n\nexport default globalThis\n","import { Injectable } from '@angular/core';\nimport { AuthService } from '../auth.service';\n\n@Injectable()\nexport class DisabledAuthService implements AuthService {\n\n public async init(_config?: Record<string, unknown>): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n getIdToken(): string | null {\n return \"\";\n }\n getAccessToken(): string | null {\n return \"\";\n }\n\n logout(): void {\n window.location.href = \"https://github.com/onecx/\";\n }\n\n async updateTokenIfNeeded(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n getHeaderValues(): Record<string, string> {\n return {};\n }\n}\n","import { loadRemoteModule } from '@angular-architects/module-federation'\nimport { Injectable, Injector, inject } from '@angular/core'\nimport { AppStateService, CONFIG_KEY, ConfigurationService } from '@onecx/angular-integration-interface'\nimport { Config, EventsTopic, EventType } from '@onecx/integration-interface'\nimport { filter } from 'rxjs/internal/operators/filter'\nimport { AuthService, AuthServiceFactory, Injectables } from './auth.service'\nimport { KeycloakAuthService } from './auth_services/keycloak-auth.service'\nimport './declarations'\nimport { DisabledAuthService } from './auth_services/disabled-auth.service'\n\n@Injectable()\nexport class AuthServiceWrapper {\n private configService = inject(ConfigurationService)\n private appStateService = inject(AppStateService)\n private injector = inject(Injector)\n\n private eventsTopic$ = new EventsTopic()\n private authService: AuthService | undefined\n\n constructor() {\n this.eventsTopic$\n .pipe(filter((e) => e.type === EventType.AUTH_LOGOUT_BUTTON_CLICKED))\n .subscribe(() => this.authService?.logout())\n // Shell defines these properties to support older library versions\n window.onecxAngularAuth ??= {}\n window.onecxAngularAuth.authServiceProxy ??= {}\n window.onecxAngularAuth.authServiceProxy.v1 ??= {\n updateTokenIfNeeded: (): Promise<boolean> => {\n return this.updateTokenIfNeeded()\n },\n getHeaderValues: (): Record<string, string> => {\n return this.getHeaderValues()\n },\n }\n window.onecxAuth ??= {}\n window.onecxAuth.authServiceProxy ??= {}\n window.onecxAuth.authServiceProxy.v1 ??= {\n updateTokenIfNeeded: (): Promise<boolean> => {\n return this.updateTokenIfNeeded()\n },\n getHeaderValues: (): Record<string, string> => {\n return this.getHeaderValues()\n },\n }\n }\n async init(): Promise<boolean | undefined> {\n await this.configService.isInitialized\n\n await this.initializeAuthService()\n const initResult = this.getInitResult()\n return initResult\n }\n async getInitResult(): Promise<boolean | undefined> {\n const initResult = await this.authService?.init()\n\n if (initResult) {\n await this.appStateService.isAuthenticated$.publish()\n }\n return initResult\n }\n getHeaderValues(): Record<string, string> {\n return this.authService?.getHeaderValues() ?? {}\n }\n updateTokenIfNeeded(): Promise<boolean> {\n return this.authService?.updateTokenIfNeeded() ?? Promise.reject()\n }\n\n async initializeAuthService(): Promise<void> {\n const serviceTypeConfig = (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE)) ?? 'keycloak'\n\n switch (serviceTypeConfig) {\n case 'keycloak':\n this.authService = this.injector.get(KeycloakAuthService)\n break\n case 'custom': {\n // remote module is exposing function as default export (this is a convention)\n // this function is responsible for creating the custom auth service\n // to have access to the dependency mechanism of the shell\n // the function gets a callback which is returning the requested injectable\n const factory = await this.getAuthServiceFactory()\n this.authService = await Promise.resolve(\n factory((injectable: Injectables) => this.retrieveInjectables(injectable))\n )\n break\n }\n case 'disabled':\n this.authService = this.injector.get(DisabledAuthService)\n break\n default:\n throw new Error('Configured AuthService not found')\n }\n }\n\n async retrieveInjectables(injectable: Injectables): Promise<KeycloakAuthService | Config | undefined> {\n if (injectable === Injectables.KEYCLOAK_AUTH_SERVICE) {\n return this.injector.get(KeycloakAuthService)\n } else if (injectable === Injectables.CONFIG) {\n return this.configService.getConfig()\n }\n throw new Error('unknown injectable type')\n }\n\n async getAuthServiceFactory(): Promise<AuthServiceFactory> {\n if (await !this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) {\n throw new Error('URL of the custom auth service is not defined')\n }\n const module = await loadRemoteModule({\n type: 'module',\n remoteEntry: (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) ?? '',\n exposedModule:\n (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_MODULE_NAME)) ?? './CustomAuth',\n })\n return module.default as AuthServiceFactory\n }\n}\n","import { inject, provideAppInitializer } from '@angular/core'\nimport { ConfigurationService } from '@onecx/angular-integration-interface'\nimport { AuthServiceWrapper } from './auth-service-wrapper'\nimport { DisabledAuthService } from './auth_services/disabled-auth.service'\nimport { KeycloakAuthService } from './auth_services/keycloak-auth.service'\n\nfunction provideAuthServices() {\n return [AuthServiceWrapper, KeycloakAuthService, DisabledAuthService]\n}\n\nexport function provideAuthService() {\n return [\n provideAuthServices(),\n provideAppInitializer(async () => {\n const configService = inject(ConfigurationService)\n const authServiceWrapper = inject(AuthServiceWrapper)\n await configService.isInitialized\n await authServiceWrapper.init()\n }),\n ]\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/shell-auth/migrations/index.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onecx/shell-auth",
3
- "version": "8.0.0-rc.4",
3
+ "version": "8.0.0-rc.5",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "peerDependencies": {
10
10
  "@angular-architects/module-federation": "^20.0.0",
11
- "@angular/core": "^20.3.16",
12
- "@onecx/accelerator": "^8.0.0-rc.4",
13
- "@onecx/angular-integration-interface": "^8.0.0-rc.4",
14
- "@onecx/integration-interface": "^8.0.0-rc.4",
11
+ "@angular/core": "^21.0.0",
12
+ "@onecx/accelerator": "^8.0.0-rc.5",
13
+ "@onecx/angular-integration-interface": "^8.0.0-rc.5",
14
+ "@onecx/integration-interface": "^8.0.0-rc.5",
15
15
  "keycloak-js": "^26.2.3",
16
16
  "rxjs": "~7.8.0"
17
17
  },
@@ -25,5 +25,20 @@
25
25
  },
26
26
  "nx-migrations": {
27
27
  "migrations": "./migrations.json"
28
+ },
29
+ "module": "fesm2022/onecx-shell-auth.mjs",
30
+ "typings": "types/onecx-shell-auth.d.ts",
31
+ "exports": {
32
+ "./package.json": {
33
+ "default": "./package.json"
34
+ },
35
+ ".": {
36
+ "types": "./types/onecx-shell-auth.d.ts",
37
+ "default": "./fesm2022/onecx-shell-auth.mjs"
38
+ }
39
+ },
40
+ "sideEffects": false,
41
+ "dependencies": {
42
+ "tslib": "^2.3.0"
28
43
  }
29
- }
44
+ }
@@ -0,0 +1,92 @@
1
+ import { Config } from '@onecx/integration-interface';
2
+ import { KeycloakServerConfig } from 'keycloak-js';
3
+ import * as i0 from '@angular/core';
4
+
5
+ interface AuthService {
6
+ init(config?: Record<string, unknown>): Promise<boolean>;
7
+ getHeaderValues(): Record<string, string>;
8
+ logout(): void;
9
+ updateTokenIfNeeded(): Promise<boolean>;
10
+ }
11
+ declare enum Injectables {
12
+ KEYCLOAK_AUTH_SERVICE = "KEYCLOAK_AUTH_SERVICE",
13
+ CONFIG = "CONFIG"
14
+ }
15
+ type AuthServiceFactory = (injectorFunction: (injectable: Injectables) => Promise<unknown> | unknown) => AuthService | Promise<AuthService>;
16
+
17
+ declare class KeycloakAuthService implements AuthService {
18
+ private readonly logger;
19
+ private configService;
20
+ private keycloak;
21
+ config?: Record<string, unknown>;
22
+ init(config?: Record<string, unknown>): Promise<boolean>;
23
+ protected getValidKCConfig(): Promise<KeycloakServerConfig>;
24
+ private setupEventListener;
25
+ private updateLocalStorage;
26
+ private clearKCStateFromLocalstorage;
27
+ private getSilentSSOUrl;
28
+ getIdToken(): string | null;
29
+ getAccessToken(): string | null;
30
+ logout(): void;
31
+ updateTokenIfNeeded(): Promise<boolean>;
32
+ getAuthProviderName(): string;
33
+ hasRole(_role: string): boolean;
34
+ getUserRoles(): string[];
35
+ getHeaderValues(): Record<string, string>;
36
+ static ɵfac: i0.ɵɵFactoryDeclaration<KeycloakAuthService, never>;
37
+ static ɵprov: i0.ɵɵInjectableDeclaration<KeycloakAuthService>;
38
+ }
39
+
40
+ declare global {
41
+ interface Window {
42
+ onecxAuth?: {
43
+ authServiceProxy?: {
44
+ v1?: {
45
+ getHeaderValues: () => Record<string, string>;
46
+ updateTokenIfNeeded: () => Promise<boolean>;
47
+ };
48
+ };
49
+ };
50
+ onecxAngularAuth?: {
51
+ authServiceProxy?: {
52
+ v1?: {
53
+ getHeaderValues: () => Record<string, string>;
54
+ updateTokenIfNeeded: () => Promise<boolean>;
55
+ };
56
+ };
57
+ };
58
+ }
59
+ }
60
+
61
+ declare class AuthServiceWrapper {
62
+ private configService;
63
+ private appStateService;
64
+ private injector;
65
+ private eventsTopic$;
66
+ private authService;
67
+ constructor();
68
+ init(): Promise<boolean | undefined>;
69
+ getInitResult(): Promise<boolean | undefined>;
70
+ getHeaderValues(): Record<string, string>;
71
+ updateTokenIfNeeded(): Promise<boolean>;
72
+ initializeAuthService(): Promise<void>;
73
+ retrieveInjectables(injectable: Injectables): Promise<KeycloakAuthService | Config | undefined>;
74
+ getAuthServiceFactory(): Promise<AuthServiceFactory>;
75
+ static ɵfac: i0.ɵɵFactoryDeclaration<AuthServiceWrapper, never>;
76
+ static ɵprov: i0.ɵɵInjectableDeclaration<AuthServiceWrapper>;
77
+ }
78
+
79
+ declare class DisabledAuthService implements AuthService {
80
+ init(_config?: Record<string, unknown>): Promise<boolean>;
81
+ getIdToken(): string | null;
82
+ getAccessToken(): string | null;
83
+ logout(): void;
84
+ updateTokenIfNeeded(): Promise<boolean>;
85
+ getHeaderValues(): Record<string, string>;
86
+ static ɵfac: i0.ɵɵFactoryDeclaration<DisabledAuthService, never>;
87
+ static ɵprov: i0.ɵɵInjectableDeclaration<DisabledAuthService>;
88
+ }
89
+
90
+ declare function provideAuthService(): ((typeof DisabledAuthService | typeof AuthServiceWrapper)[] | i0.EnvironmentProviders)[];
91
+
92
+ export { AuthServiceWrapper, provideAuthService };
package/.eslintrc.json DELETED
@@ -1,46 +0,0 @@
1
- {
2
- "extends": ["../../.eslintrc.json"],
3
- "ignorePatterns": ["!**/*"],
4
- "overrides": [
5
- {
6
- "files": ["*.ts"],
7
- "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
8
- "rules": {
9
- "@angular-eslint/directive-selector": [
10
- "error",
11
- {
12
- "type": "attribute",
13
- "prefix": "ocx",
14
- "style": "camelCase"
15
- }
16
- ],
17
- "@angular-eslint/component-selector": [
18
- "error",
19
- {
20
- "type": "element",
21
- "prefix": "ocx",
22
- "style": "kebab-case"
23
- }
24
- ],
25
- "no-restricted-syntax": [
26
- "off",
27
- {
28
- "selector": "CallExpression[callee.object.name=\"console\"][callee.property.name=/^(debug|info|time|timeEnd|trace)$/]"
29
- }
30
- ]
31
- }
32
- },
33
- {
34
- "files": ["*.html"],
35
- "extends": ["plugin:@nx/angular-template"],
36
- "rules": {}
37
- },
38
- {
39
- "files": ["*.json"],
40
- "parser": "jsonc-eslint-parser",
41
- "rules": {
42
- "@nx/dependency-checks": "error"
43
- }
44
- }
45
- ]
46
- }
package/jest.config.ts DELETED
@@ -1,27 +0,0 @@
1
- /** @jest-config-loader ts-node */
2
- // Without jest-config-loader, jest cannot load other ts files
3
-
4
- /* eslint-disable */
5
- import { createReportsConfig } from '../../jest-config-factory'
6
-
7
- export default {
8
- displayName: 'shell-auth',
9
- preset: '../../jest.preset.js',
10
- setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
11
- transform: {
12
- '^.+\\.(ts|mjs|js|html)$': [
13
- 'jest-preset-angular',
14
- {
15
- tsconfig: '<rootDir>/tsconfig.spec.json',
16
- stringifyContentPathRegex: '\\.(html|svg)$',
17
- },
18
- ],
19
- },
20
- transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
21
- snapshotSerializers: [
22
- 'jest-preset-angular/build/serializers/no-ng-attributes',
23
- 'jest-preset-angular/build/serializers/ng-snapshot',
24
- 'jest-preset-angular/build/serializers/html-comment',
25
- ],
26
- ...createReportsConfig('shell-auth'),
27
- }
@@ -1,19 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "module": "commonjs",
5
- "forceConsistentCasingInFileNames": true,
6
- "strict": true,
7
- "noImplicitOverride": true,
8
- "noPropertyAccessFromIndexSignature": true,
9
- "noImplicitReturns": true,
10
- "noFallthroughCasesInSwitch": true
11
- },
12
- "files": [],
13
- "include": [],
14
- "references": [
15
- {
16
- "path": "./tsconfig.migrations.json"
17
- }
18
- ]
19
- }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../../dist",
5
- "declaration": true,
6
- "types": ["node"]
7
- },
8
- "include": ["**/*.ts"],
9
- "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10
- }
package/ng-package.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
- "dest": "../../dist/libs/shell-auth",
4
- "lib": {
5
- "entryFile": "src/index.ts"
6
- },
7
- "assets": [
8
- "CHANGELOG.md",
9
- "./assets/**",
10
- "./migrations.json"
11
- ]
12
- }
package/project.json DELETED
@@ -1,64 +0,0 @@
1
- {
2
- "name": "shell-auth",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "libs/shell-auth/src",
5
- "prefix": "ocx",
6
- "projectType": "library",
7
- "tags": [],
8
- "targets": {
9
- "build-migrations": {
10
- "dependsOn": ["build"],
11
- "executor": "nx:run-commands",
12
- "options": {
13
- "commands": ["tsc -p libs/shell-auth/migrations/tsconfig.migrations.json"]
14
- }
15
- },
16
- "build": {
17
- "executor": "@nx/angular:package",
18
- "outputs": ["{workspaceRoot}/dist/{projectRoot}"],
19
- "options": {
20
- "project": "libs/shell-auth/ng-package.json"
21
- },
22
- "configurations": {
23
- "production": {
24
- "tsConfig": "libs/shell-auth/tsconfig.lib.prod.json"
25
- },
26
- "development": {
27
- "tsConfig": "libs/shell-auth/tsconfig.lib.json"
28
- }
29
- },
30
- "defaultConfiguration": "production"
31
- },
32
- "test": {
33
- "executor": "@nx/jest:jest",
34
- "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
35
- "options": {
36
- "jestConfig": "libs/shell-auth/jest.config.ts",
37
- "passWithNoTests": true
38
- },
39
- "configurations": {
40
- "ci": {
41
- "ci": true,
42
- "codeCoverage": true
43
- }
44
- }
45
- },
46
- "lint": {
47
- "executor": "@nx/eslint:lint",
48
- "outputs": ["{options.outputFile}"],
49
- "options": {
50
- "lintFilePatterns": [
51
- "libs/shell-auth/**/*.ts",
52
- "libs/shell-auth/**/*.html",
53
- "libs/shell-auth/package.json"
54
- ]
55
- }
56
- },
57
- "release": {
58
- "executor": "@onecx/release:update-build-publish",
59
- "options": {
60
- "buildTarget": "build-migrations"
61
- }
62
- }
63
- }
64
- }
@@ -1,37 +0,0 @@
1
- # sonar.verbose=true
2
- # run locally:
3
- # docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest
4
- # user/pwd: admin/admin
5
- # generate project token and use it in sonar.token!
6
- # start:
7
- # npm run sonar
8
- #
9
- sonar.host.url=http://localhost:9000
10
- sonar.token=<SONAR_TOKEN>
11
- sonar.verbose=false
12
- #
13
- sonar.organization=onecx
14
- sonar.projectKey=onecx-portal-ui-libs-shell-auth
15
- sonar.projectName=onecx-portal-ui-libs-shell-auth
16
- #
17
- sonar.scm.disabled=true
18
- sonar.sources=src
19
- sonar.tests=src
20
- sonar-language="js"
21
- sonar.sourceEncoding=UTF-8
22
- #
23
- # reporting
24
- sonar.javascript.coveragePlugin=lcov
25
- sonar.javascript.lcov.reportPaths=../../reports/shell-auth/coverage/lcov.info
26
- sonar.testExecutionReportPaths=../../reports/shell-auth/sonarqube_report.xml
27
- sonar.working.directory=../../reports/shell-auth/.scannerwork
28
- # files
29
- sonar.exclusions=src/assets/**/*,src/migrations/**/*,src/mocks/**/*
30
- sonar.cpd.exclusions=src/**/*.ts,src/**/*.html
31
- sonar.coverage.exclusions=*.ts,*.js,src/*.ts,**/*.spec.ts,**/*.test.ts,**/*.stories.ts,**/*.harness.ts,**/environments/**,**/assets/**,**/generated/**,**/*.module.ts,**/*.main.ts
32
- sonar.test.inclusions=src/**/*.spec.ts, src/**/*.test.ts
33
- # issue exceptions
34
- sonar.issue.ignore.multicriteria=e1
35
- # ignore rule to allow async actions inside constructors
36
- sonar.issue.ignore.multicriteria.e1.ruleKey=typescript:S7059
37
- sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.ts
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './lib/auth-service-wrapper'
2
- export * from './lib/provide-auth-service'
@@ -1,115 +0,0 @@
1
- import { loadRemoteModule } from '@angular-architects/module-federation'
2
- import { Injectable, Injector, inject } from '@angular/core'
3
- import { AppStateService, CONFIG_KEY, ConfigurationService } from '@onecx/angular-integration-interface'
4
- import { Config, EventsTopic, EventType } from '@onecx/integration-interface'
5
- import { filter } from 'rxjs/internal/operators/filter'
6
- import { AuthService, AuthServiceFactory, Injectables } from './auth.service'
7
- import { KeycloakAuthService } from './auth_services/keycloak-auth.service'
8
- import './declarations'
9
- import { DisabledAuthService } from './auth_services/disabled-auth.service'
10
-
11
- @Injectable()
12
- export class AuthServiceWrapper {
13
- private configService = inject(ConfigurationService)
14
- private appStateService = inject(AppStateService)
15
- private injector = inject(Injector)
16
-
17
- private eventsTopic$ = new EventsTopic()
18
- private authService: AuthService | undefined
19
-
20
- constructor() {
21
- this.eventsTopic$
22
- .pipe(filter((e) => e.type === EventType.AUTH_LOGOUT_BUTTON_CLICKED))
23
- .subscribe(() => this.authService?.logout())
24
- // Shell defines these properties to support older library versions
25
- window.onecxAngularAuth ??= {}
26
- window.onecxAngularAuth.authServiceProxy ??= {}
27
- window.onecxAngularAuth.authServiceProxy.v1 ??= {
28
- updateTokenIfNeeded: (): Promise<boolean> => {
29
- return this.updateTokenIfNeeded()
30
- },
31
- getHeaderValues: (): Record<string, string> => {
32
- return this.getHeaderValues()
33
- },
34
- }
35
- window.onecxAuth ??= {}
36
- window.onecxAuth.authServiceProxy ??= {}
37
- window.onecxAuth.authServiceProxy.v1 ??= {
38
- updateTokenIfNeeded: (): Promise<boolean> => {
39
- return this.updateTokenIfNeeded()
40
- },
41
- getHeaderValues: (): Record<string, string> => {
42
- return this.getHeaderValues()
43
- },
44
- }
45
- }
46
- async init(): Promise<boolean | undefined> {
47
- await this.configService.isInitialized
48
-
49
- await this.initializeAuthService()
50
- const initResult = this.getInitResult()
51
- return initResult
52
- }
53
- async getInitResult(): Promise<boolean | undefined> {
54
- const initResult = await this.authService?.init()
55
-
56
- if (initResult) {
57
- await this.appStateService.isAuthenticated$.publish()
58
- }
59
- return initResult
60
- }
61
- getHeaderValues(): Record<string, string> {
62
- return this.authService?.getHeaderValues() ?? {}
63
- }
64
- updateTokenIfNeeded(): Promise<boolean> {
65
- return this.authService?.updateTokenIfNeeded() ?? Promise.reject()
66
- }
67
-
68
- async initializeAuthService(): Promise<void> {
69
- const serviceTypeConfig = (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE)) ?? 'keycloak'
70
-
71
- switch (serviceTypeConfig) {
72
- case 'keycloak':
73
- this.authService = this.injector.get(KeycloakAuthService)
74
- break
75
- case 'custom': {
76
- // remote module is exposing function as default export (this is a convention)
77
- // this function is responsible for creating the custom auth service
78
- // to have access to the dependency mechanism of the shell
79
- // the function gets a callback which is returning the requested injectable
80
- const factory = await this.getAuthServiceFactory()
81
- this.authService = await Promise.resolve(
82
- factory((injectable: Injectables) => this.retrieveInjectables(injectable))
83
- )
84
- break
85
- }
86
- case 'disabled':
87
- this.authService = this.injector.get(DisabledAuthService)
88
- break
89
- default:
90
- throw new Error('Configured AuthService not found')
91
- }
92
- }
93
-
94
- async retrieveInjectables(injectable: Injectables): Promise<KeycloakAuthService | Config | undefined> {
95
- if (injectable === Injectables.KEYCLOAK_AUTH_SERVICE) {
96
- return this.injector.get(KeycloakAuthService)
97
- } else if (injectable === Injectables.CONFIG) {
98
- return this.configService.getConfig()
99
- }
100
- throw new Error('unknown injectable type')
101
- }
102
-
103
- async getAuthServiceFactory(): Promise<AuthServiceFactory> {
104
- if (await !this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) {
105
- throw new Error('URL of the custom auth service is not defined')
106
- }
107
- const module = await loadRemoteModule({
108
- type: 'module',
109
- remoteEntry: (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_URL)) ?? '',
110
- exposedModule:
111
- (await this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE_CUSTOM_MODULE_NAME)) ?? './CustomAuth',
112
- })
113
- return module.default as AuthServiceFactory
114
- }
115
- }
@@ -1,18 +0,0 @@
1
- export interface AuthService {
2
- init(config?: Record<string, unknown>): Promise<boolean>
3
-
4
- getHeaderValues(): Record<string, string>
5
-
6
- logout(): void
7
-
8
- updateTokenIfNeeded(): Promise<boolean>
9
- }
10
-
11
- export enum Injectables {
12
- KEYCLOAK_AUTH_SERVICE = 'KEYCLOAK_AUTH_SERVICE',
13
- CONFIG = 'CONFIG',
14
- }
15
-
16
- export type AuthServiceFactory = (
17
- injectorFunction: (injectable: Injectables) => Promise<unknown> | unknown
18
- ) => AuthService | Promise<AuthService>
@@ -1,29 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { AuthService } from '../auth.service';
3
-
4
- @Injectable()
5
- export class DisabledAuthService implements AuthService {
6
-
7
- public async init(_config?: Record<string, unknown>): Promise<boolean> {
8
- return Promise.resolve(true);
9
- }
10
-
11
- getIdToken(): string | null {
12
- return "";
13
- }
14
- getAccessToken(): string | null {
15
- return "";
16
- }
17
-
18
- logout(): void {
19
- window.location.href = "https://github.com/onecx/";
20
- }
21
-
22
- async updateTokenIfNeeded(): Promise<boolean> {
23
- return Promise.resolve(true);
24
- }
25
-
26
- getHeaderValues(): Record<string, string> {
27
- return {};
28
- }
29
- }
@@ -1,211 +0,0 @@
1
- import { Injectable, inject } from '@angular/core'
2
- import { CONFIG_KEY, ConfigurationService } from '@onecx/angular-integration-interface'
3
- import Keycloak, { KeycloakServerConfig } from 'keycloak-js'
4
- import { AuthService } from '../auth.service'
5
- import { createLogger } from '../utils/logger.utils'
6
-
7
- const KC_REFRESH_TOKEN_LS = 'onecx_kc_refreshToken'
8
- const KC_ID_TOKEN_LS = 'onecx_kc_idToken'
9
- const KC_TOKEN_LS = 'onecx_kc_token'
10
-
11
- @Injectable()
12
- export class KeycloakAuthService implements AuthService {
13
- private readonly logger = createLogger('KeycloakAuthService')
14
- private configService = inject(ConfigurationService)
15
- private keycloak: Keycloak | undefined
16
-
17
- config?: Record<string, unknown>
18
-
19
- public async init(config?: Record<string, unknown>): Promise<boolean> {
20
- this.config = config
21
- let token = localStorage.getItem(KC_TOKEN_LS)
22
- let idToken = localStorage.getItem(KC_ID_TOKEN_LS)
23
- let refreshToken = localStorage.getItem(KC_REFRESH_TOKEN_LS)
24
- if (token && refreshToken) {
25
- const parsedToken = JSON.parse(atob(refreshToken.split('.')[1]))
26
- if (parsedToken.exp * 1000 < new Date().getTime()) {
27
- token = null
28
- refreshToken = null
29
- idToken = null
30
- this.clearKCStateFromLocalstorage()
31
- }
32
- }
33
-
34
- let kcConfig: KeycloakServerConfig | string
35
- const validKCConfig = await this.getValidKCConfig()
36
- kcConfig = { ...validKCConfig, ...(config ?? {}) }
37
-
38
- if (!kcConfig.clientId || !kcConfig.realm || !kcConfig.url) {
39
- kcConfig = './assets/keycloak.json'
40
- }
41
-
42
- const enableSilentSSOCheck =
43
- (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_ENABLE_SILENT_SSO)) === 'true'
44
-
45
- try {
46
- await import('keycloak-js').then(({ default: Keycloak }) => {
47
- this.keycloak = new Keycloak(kcConfig)
48
- })
49
- } catch (err) {
50
- const errorMessage = 'Keycloak initialization failed! Could not load keycloak-js library which is required in the current environment.'
51
- this.logger.error(
52
- errorMessage,
53
- err
54
- )
55
- throw new Error(
56
- errorMessage
57
- )
58
- }
59
-
60
- if (!this.keycloak) {
61
- throw new Error('Keycloak initialization failed!')
62
- }
63
-
64
- this.setupEventListener()
65
-
66
- return this.keycloak
67
- .init({
68
- onLoad: 'check-sso',
69
- checkLoginIframe: false,
70
- silentCheckSsoRedirectUri: enableSilentSSOCheck ? this.getSilentSSOUrl() : undefined,
71
- idToken: idToken || undefined,
72
- refreshToken: refreshToken || undefined,
73
- token: token || undefined,
74
- })
75
- .catch((err) => {
76
- this.logger.warn(`Keycloak err: ${err}, try force login`)
77
- return this.keycloak?.login(this.config)
78
- })
79
- .then((loginOk) => {
80
- if (loginOk) {
81
- return this.keycloak?.token
82
- } else {
83
- return this.keycloak?.login(this.config).then(() => 'login')
84
- }
85
- })
86
- .then(() => {
87
- return true
88
- })
89
- .catch((err) => {
90
- this.logger.error(`KC ERROR ${err} as json ${JSON.stringify(err)}`)
91
- throw err
92
- })
93
- }
94
-
95
- protected async getValidKCConfig(): Promise<KeycloakServerConfig> {
96
- const clientId = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_CLIENT_ID)
97
- if (!clientId) {
98
- throw new Error('Invalid KC config, missing clientId')
99
- }
100
- const realm = await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_REALM)
101
- if (!realm) {
102
- throw new Error('Invalid KC config, missing realm')
103
- }
104
- const url = (await this.configService.getProperty(CONFIG_KEY.KEYCLOAK_URL)) ?? ''
105
- return {
106
- url,
107
- clientId,
108
- realm,
109
- }
110
- }
111
-
112
- private setupEventListener() {
113
- if (this.keycloak) {
114
- this.keycloak.onAuthError = () => {
115
- this.updateLocalStorage()
116
- }
117
- this.keycloak.onAuthLogout = () => {
118
- this.logger.info('SSO logout nav to root')
119
- this.clearKCStateFromLocalstorage()
120
- this.keycloak?.login(this.config)
121
- }
122
- this.keycloak.onAuthRefreshSuccess = () => {
123
- this.updateLocalStorage()
124
- }
125
- this.keycloak.onAuthRefreshError = () => {
126
- this.updateLocalStorage()
127
- }
128
- this.keycloak.onAuthSuccess = () => {
129
- this.updateLocalStorage()
130
- }
131
- this.keycloak.onTokenExpired = () => {
132
- this.updateLocalStorage()
133
- }
134
- this.keycloak.onActionUpdate = () => {
135
- this.updateLocalStorage()
136
- }
137
- this.keycloak.onReady = () => {
138
- this.updateLocalStorage()
139
- }
140
- }
141
- }
142
-
143
- private updateLocalStorage() {
144
- if (this.keycloak) {
145
- if (this.keycloak.token) {
146
- localStorage.setItem(KC_TOKEN_LS, this.keycloak.token)
147
- } else {
148
- localStorage.removeItem(KC_TOKEN_LS)
149
- }
150
- if (this.keycloak.idToken) {
151
- localStorage.setItem(KC_ID_TOKEN_LS, this.keycloak.idToken)
152
- } else {
153
- localStorage.removeItem(KC_ID_TOKEN_LS)
154
- }
155
- if (this.keycloak.refreshToken) {
156
- localStorage.setItem(KC_REFRESH_TOKEN_LS, this.keycloak.refreshToken)
157
- } else {
158
- localStorage.removeItem(KC_REFRESH_TOKEN_LS)
159
- }
160
- }
161
- }
162
-
163
- private clearKCStateFromLocalstorage() {
164
- localStorage.removeItem(KC_ID_TOKEN_LS)
165
- localStorage.removeItem(KC_TOKEN_LS)
166
- localStorage.removeItem(KC_REFRESH_TOKEN_LS)
167
- }
168
-
169
- private getSilentSSOUrl() {
170
- let currentBase = document.getElementsByTagName('base')[0].href
171
- if (currentBase === '/') {
172
- currentBase = ''
173
- }
174
- return `${currentBase}/assets/silent-check-sso.html`
175
- }
176
-
177
- getIdToken(): string | null {
178
- return this.keycloak?.idToken ?? null
179
- }
180
- getAccessToken(): string | null {
181
- return this.keycloak?.token ?? null
182
- }
183
-
184
- logout(): void {
185
- this.keycloak?.logout()
186
- }
187
-
188
- async updateTokenIfNeeded(): Promise<boolean> {
189
- if (!this.keycloak?.authenticated) {
190
- return this.keycloak?.login(this.config).then(() => false) ?? Promise.reject('Keycloak not initialized!')
191
- } else {
192
- return this.keycloak.updateToken()
193
- }
194
- }
195
-
196
- getAuthProviderName(): string {
197
- return 'keycloak-auth'
198
- }
199
-
200
- hasRole(_role: string): boolean {
201
- return false
202
- }
203
-
204
- getUserRoles(): string[] {
205
- return []
206
- }
207
-
208
- getHeaderValues(): Record<string, string> {
209
- return { 'apm-principal-token': this.getIdToken() ?? '', Authorization: `Bearer ${this.getAccessToken()}` }
210
- }
211
- }
@@ -1,23 +0,0 @@
1
- declare global {
2
- interface Window {
3
- onecxAuth?: {
4
- authServiceProxy?: {
5
- v1?: {
6
- getHeaderValues: () => Record<string, string>
7
- updateTokenIfNeeded: () => Promise<boolean>
8
- }
9
- }
10
- }
11
- // Shell defines these properties to support older library versions
12
- onecxAngularAuth?: {
13
- authServiceProxy?: {
14
- v1?: {
15
- getHeaderValues: () => Record<string, string>
16
- updateTokenIfNeeded: () => Promise<boolean>
17
- }
18
- }
19
- }
20
- }
21
- }
22
-
23
- export default globalThis
@@ -1,21 +0,0 @@
1
- import { inject, provideAppInitializer } from '@angular/core'
2
- import { ConfigurationService } from '@onecx/angular-integration-interface'
3
- import { AuthServiceWrapper } from './auth-service-wrapper'
4
- import { DisabledAuthService } from './auth_services/disabled-auth.service'
5
- import { KeycloakAuthService } from './auth_services/keycloak-auth.service'
6
-
7
- function provideAuthServices() {
8
- return [AuthServiceWrapper, KeycloakAuthService, DisabledAuthService]
9
- }
10
-
11
- export function provideAuthService() {
12
- return [
13
- provideAuthServices(),
14
- provideAppInitializer(async () => {
15
- const configService = inject(ConfigurationService)
16
- const authServiceWrapper = inject(AuthServiceWrapper)
17
- await configService.isInitialized
18
- await authServiceWrapper.init()
19
- }),
20
- ]
21
- }
@@ -1,4 +0,0 @@
1
- // This file is not planned to be in the index.ts so it is private to this lib
2
- import { createLoggerFactory } from '@onecx/accelerator'
3
-
4
- export const createLogger = createLoggerFactory('@onecx/shell-auth')
package/src/test-setup.ts DELETED
@@ -1,6 +0,0 @@
1
- import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'
2
-
3
- setupZoneTestEnv({
4
- errorOnUnknownElements: true,
5
- errorOnUnknownProperties: true,
6
- })
package/tsconfig.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "moduleResolution": "bundler",
4
- "target": "es2022",
5
- "forceConsistentCasingInFileNames": true,
6
- "strict": true,
7
- "noImplicitOverride": true,
8
- "noPropertyAccessFromIndexSignature": true,
9
- "noImplicitReturns": true,
10
- "noFallthroughCasesInSwitch": true,
11
- "esModuleInterop": true
12
- },
13
- "files": [],
14
- "include": [],
15
- "references": [
16
- {
17
- "path": "./tsconfig.lib.json"
18
- },
19
- {
20
- "path": "./tsconfig.lib.prod.json"
21
- },
22
- {
23
- "path": "./tsconfig.spec.json"
24
- }
25
- ],
26
- "extends": "../../tsconfig.base.json",
27
- "angularCompilerOptions": {
28
- "strictInjectionParameters": true,
29
- "strictInputAccessModifiers": true,
30
- "strictTemplates": true
31
- }
32
- }
package/tsconfig.lib.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../dist/out-tsc",
5
- "declaration": true,
6
- "declarationMap": true,
7
- "inlineSources": true,
8
- "types": []
9
- },
10
- "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
11
- "include": ["src/**/*.ts"]
12
- }
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "./tsconfig.lib.json",
3
- "compilerOptions": {
4
- "declarationMap": false,
5
- "target": "es2022",
6
- "useDefineForClassFields": false
7
- },
8
- "angularCompilerOptions": {
9
- "compilationMode": "partial"
10
- }
11
- }
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../dist/out-tsc",
5
- "module": "commonjs",
6
- "moduleResolution": "node",
7
- "target": "es2016",
8
- "types": ["jest", "node"]
9
- },
10
- "files": ["src/test-setup.ts"],
11
- "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
12
- }
File without changes