@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.
- package/fesm2022/onecx-shell-auth.mjs +353 -0
- package/fesm2022/onecx-shell-auth.mjs.map +1 -0
- package/migrations/index.js +2 -0
- package/migrations/index.js.map +1 -0
- package/package.json +21 -6
- package/types/onecx-shell-auth.d.ts +92 -0
- package/.eslintrc.json +0 -46
- package/jest.config.ts +0 -27
- package/migrations/tsconfig.json +0 -19
- package/migrations/tsconfig.migrations.json +0 -10
- package/ng-package.json +0 -12
- package/project.json +0 -64
- package/sonar-project.properties +0 -37
- package/src/index.ts +0 -2
- package/src/lib/auth-service-wrapper.ts +0 -115
- package/src/lib/auth.service.ts +0 -18
- package/src/lib/auth_services/disabled-auth.service.ts +0 -29
- package/src/lib/auth_services/keycloak-auth.service.ts +0 -211
- package/src/lib/declarations.ts +0 -23
- package/src/lib/provide-auth-service.ts +0 -21
- package/src/lib/utils/logger.utils.ts +0 -4
- package/src/test-setup.ts +0 -6
- package/tsconfig.json +0 -32
- package/tsconfig.lib.json +0 -12
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -12
- /package/migrations/{index.ts → index.d.ts} +0 -0
|
@@ -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 @@
|
|
|
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.
|
|
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": "^
|
|
12
|
-
"@onecx/accelerator": "^8.0.0-rc.
|
|
13
|
-
"@onecx/angular-integration-interface": "^8.0.0-rc.
|
|
14
|
-
"@onecx/integration-interface": "^8.0.0-rc.
|
|
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
|
-
}
|
package/migrations/tsconfig.json
DELETED
|
@@ -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
|
-
}
|
package/ng-package.json
DELETED
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
|
-
}
|
package/sonar-project.properties
DELETED
|
@@ -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,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
|
-
}
|
package/src/lib/auth.service.ts
DELETED
|
@@ -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
|
-
}
|
package/src/lib/declarations.ts
DELETED
|
@@ -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
|
-
}
|
package/src/test-setup.ts
DELETED
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
|
-
}
|
package/tsconfig.lib.prod.json
DELETED
package/tsconfig.spec.json
DELETED
|
@@ -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
|