@axa-fr/react-oidc 6.12.0 → 6.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/bin/copy.js +12 -9
  2. package/dist/OidcProvider.d.ts +1 -1
  3. package/dist/OidcProvider.d.ts.map +1 -1
  4. package/dist/OidcSecure.d.ts +1 -1
  5. package/dist/OidcSecure.d.ts.map +1 -1
  6. package/dist/ReactOidc.d.ts +1 -1
  7. package/dist/ReactOidc.d.ts.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/vanilla/checkSession.d.ts +5 -0
  12. package/dist/vanilla/checkSession.d.ts.map +1 -0
  13. package/dist/vanilla/checkSession.js +68 -0
  14. package/dist/vanilla/checkSession.js.map +1 -0
  15. package/dist/vanilla/events.d.ts +29 -0
  16. package/dist/vanilla/events.d.ts.map +1 -0
  17. package/dist/vanilla/events.js +32 -0
  18. package/dist/vanilla/events.js.map +1 -0
  19. package/dist/vanilla/initSession.d.ts +3 -3
  20. package/dist/vanilla/initSession.d.ts.map +1 -1
  21. package/dist/vanilla/initSession.js +19 -23
  22. package/dist/vanilla/initSession.js.map +1 -1
  23. package/dist/vanilla/initWorker.d.ts +4 -4
  24. package/dist/vanilla/initWorker.d.ts.map +1 -1
  25. package/dist/vanilla/initWorker.js +11 -15
  26. package/dist/vanilla/initWorker.js.map +1 -1
  27. package/dist/vanilla/login.d.ts +4 -0
  28. package/dist/vanilla/login.d.ts.map +1 -0
  29. package/dist/vanilla/login.js +244 -0
  30. package/dist/vanilla/login.js.map +1 -0
  31. package/dist/vanilla/oidc.d.ts +4 -37
  32. package/dist/vanilla/oidc.d.ts.map +1 -1
  33. package/dist/vanilla/oidc.js +99 -519
  34. package/dist/vanilla/oidc.js.map +1 -1
  35. package/dist/vanilla/renewTokens.d.ts +4 -0
  36. package/dist/vanilla/renewTokens.d.ts.map +1 -0
  37. package/dist/vanilla/renewTokens.js +50 -0
  38. package/dist/vanilla/renewTokens.js.map +1 -0
  39. package/dist/vanilla/requests.d.ts +2 -0
  40. package/dist/vanilla/requests.d.ts.map +1 -1
  41. package/dist/vanilla/requests.js +20 -1
  42. package/dist/vanilla/requests.js.map +1 -1
  43. package/dist/vanilla/route-utils.js +1 -1
  44. package/dist/vanilla/route-utils.js.map +1 -1
  45. package/dist/vanilla/silentLogin.d.ts +9 -0
  46. package/dist/vanilla/silentLogin.d.ts.map +1 -0
  47. package/dist/vanilla/silentLogin.js +145 -0
  48. package/dist/vanilla/silentLogin.js.map +1 -0
  49. package/dist/vanilla/types.d.ts +33 -0
  50. package/dist/vanilla/types.d.ts.map +1 -0
  51. package/dist/vanilla/types.js +3 -0
  52. package/dist/vanilla/types.js.map +1 -0
  53. package/dist/vanilla/user.d.ts +2 -0
  54. package/dist/vanilla/user.d.ts.map +1 -0
  55. package/dist/vanilla/user.js +48 -0
  56. package/dist/vanilla/user.js.map +1 -0
  57. package/dist/vanilla/vanillaOidc.d.ts +2 -1
  58. package/dist/vanilla/vanillaOidc.d.ts.map +1 -1
  59. package/dist/vanilla/vanillaOidc.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/oidc/OidcProvider.tsx +1 -1
  62. package/src/oidc/OidcSecure.tsx +1 -1
  63. package/src/oidc/ReactOidc.tsx +1 -1
  64. package/src/oidc/index.ts +1 -1
  65. package/src/oidc/vanilla/checkSession.ts +55 -0
  66. package/src/oidc/vanilla/events.ts +29 -0
  67. package/src/oidc/vanilla/index.ts +1 -1
  68. package/src/oidc/vanilla/initSession.ts +19 -25
  69. package/src/oidc/vanilla/initWorker.ts +12 -18
  70. package/src/oidc/vanilla/login.ts +242 -0
  71. package/src/oidc/vanilla/oidc.ts +53 -554
  72. package/src/oidc/vanilla/renewTokens.ts +36 -0
  73. package/src/oidc/vanilla/requests.ts +24 -0
  74. package/src/oidc/vanilla/route-utils.ts +1 -1
  75. package/src/oidc/vanilla/silentLogin.ts +143 -0
  76. package/src/oidc/vanilla/types.ts +35 -0
  77. package/src/oidc/vanilla/user.ts +39 -0
  78. package/src/oidc/vanilla/vanillaOidc.ts +2 -1
@@ -1,42 +1,28 @@
1
1
  import {
2
- AuthorizationNotifier,
3
- AuthorizationRequest,
4
2
  AuthorizationServiceConfiguration,
5
- BaseTokenRequestHandler,
6
- DefaultCrypto,
7
- FetchRequestor,
8
- GRANT_TYPE_AUTHORIZATION_CODE,
9
3
  GRANT_TYPE_REFRESH_TOKEN,
10
- RedirectRequestHandler,
11
- TokenRequest,
12
4
  } from '@openid/appauth';
13
5
  import { AuthorizationServiceConfigurationJson } from '@openid/appauth/src/authorization_service_configuration';
14
6
 
15
- import { getFromCache, setCache } from './cache';
7
+ import { startCheckSessionAsync as defaultStartCheckSessionAsync } from './checkSession';
16
8
  import { CheckSessionIFrame } from './checkSessionIFrame';
9
+ import { eventNames } from './events';
17
10
  import { initSession } from './initSession';
18
11
  import { initWorkerAsync, sleepAsync } from './initWorker';
19
- import { MemoryStorageBackend } from './memoryStorageBackend';
20
- import { HashQueryStringUtils, NoHashQueryStringUtils } from './noHashQueryStringUtils';
12
+ import { defaultLoginAsync, loginCallbackAsync } from './login';
21
13
  import {
22
14
  computeTimeLeft,
23
15
  isTokensOidcValid,
24
- isTokensValid,
25
16
  setTokens, TokenRenewMode,
26
17
  Tokens,
27
18
  } from './parseTokens';
28
- import { performRevocationRequestAsync, performTokenRequestAsync, TOKEN_TYPE } from './requests';
19
+ import { autoRenewTokens, renewTokensAndStartTimerAsync } from './renewTokens';
20
+ import { fetchFromIssuer, performRevocationRequestAsync, performTokenRequestAsync, TOKEN_TYPE } from './requests';
29
21
  import { getParseQueryStringFromLocation } from './route-utils';
22
+ import defaultSilentLoginAsync, { _silentLoginAsync } from './silentLogin';
30
23
  import timer from './timer';
31
-
32
- const randomString = function(length) {
33
- let text = '';
34
- const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
35
- for (let i = 0; i < length; i++) {
36
- text += possible.charAt(Math.floor(Math.random() * possible.length));
37
- }
38
- return text;
39
- };
24
+ import { AuthorityConfiguration, OidcConfiguration, StringMap } from './types';
25
+ import { userInfoAsync } from './user';
40
26
 
41
27
  export interface OidcAuthorizationServiceConfigurationJson extends AuthorizationServiceConfigurationJson{
42
28
  check_session_iframe?: string;
@@ -58,41 +44,6 @@ export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceC
58
44
  }
59
45
  }
60
46
 
61
- export interface StringMap {
62
- [key: string]: string;
63
- }
64
-
65
- export interface AuthorityConfiguration {
66
- authorization_endpoint: string;
67
- token_endpoint: string;
68
- revocation_endpoint: string;
69
- end_session_endpoint?: string;
70
- userinfo_endpoint?: string;
71
- check_session_iframe?:string;
72
- issuer:string;
73
- }
74
-
75
- export type OidcConfiguration = {
76
- client_id: string;
77
- redirect_uri: string;
78
- silent_redirect_uri?:string;
79
- silent_login_uri?:string;
80
- silent_login_timeout?:number;
81
- scope: string;
82
- authority: string;
83
- authority_time_cache_wellknowurl_in_second?: number;
84
- authority_configuration?: AuthorityConfiguration;
85
- refresh_time_before_tokens_expiration_in_second?: number;
86
- token_request_timeout?: number;
87
- service_worker_relative_url?:string;
88
- service_worker_only?:boolean;
89
- extras?:StringMap;
90
- token_request_extras?:StringMap;
91
- storage?: Storage;
92
- monitor_session?: boolean;
93
- token_renew_mode?: string;
94
- };
95
-
96
47
  const oidcDatabase = {};
97
48
  const oidcFactory = (configuration: OidcConfiguration, name = 'default') => {
98
49
  if (oidcDatabase[name]) {
@@ -116,135 +67,17 @@ const loginCallbackWithAutoTokensRenewAsync = async (oidc) : Promise<LoginCallba
116
67
  return { callbackPath };
117
68
  };
118
69
 
119
- async function renewTokensAndStartTimerAsync(oidc, refreshToken, forceRefresh = false, extras:StringMap = null) {
120
- const updateTokens = (tokens) => { oidc.tokens = tokens; };
121
- const { tokens, status } = await oidc.synchroniseTokensAsync(refreshToken, 0, forceRefresh, extras, updateTokens);
122
-
123
- const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName, oidc.configuration.redirect_uri);
124
- if (!serviceWorker) {
125
- const session = initSession(oidc.configurationName, oidc.configuration.redirect_uri, oidc.configuration.storage);
126
- await session.setTokens(oidc.tokens);
127
- }
128
-
129
- if (!oidc.tokens) {
130
- await oidc.destroyAsync(status);
131
- return;
132
- }
133
-
134
- if (oidc.timeoutId) {
135
- oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt, extras);
136
- }
137
- }
138
-
139
- const autoRenewTokens = (oidc, refreshToken, expiresAt, extras:StringMap = null) => {
140
- const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
141
- return timer.setTimeout(async () => {
142
- const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
143
- const timeInfo = { timeLeft };
144
- oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
145
- await renewTokensAndStartTimerAsync(oidc, refreshToken, false, extras);
146
- }, 1000);
147
- };
148
-
149
- const userInfoAsync = async (oidc) => {
150
- if (oidc.userInfo != null) {
151
- return oidc.userInfo;
152
- }
153
- if (!oidc.tokens) {
154
- return null;
155
- }
156
- const accessToken = oidc.tokens.accessToken;
157
- if (!accessToken) {
158
- return null;
159
- }
160
-
161
- // We wait the synchronisation before making a request
162
- while (oidc.tokens && !isTokensValid(oidc.tokens)) {
163
- await sleepAsync(200);
164
- }
165
-
166
- const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
167
- const url = oidcServerConfiguration.userInfoEndpoint;
168
- const fetchUserInfo = async (accessToken) => {
169
- const res = await fetch(url, {
170
- headers: {
171
- authorization: `Bearer ${accessToken}`,
172
- },
173
- });
174
-
175
- if (res.status !== 200) {
176
- return null;
177
- }
178
-
179
- return res.json();
180
- };
181
- const userInfo = await fetchUserInfo(accessToken);
182
- oidc.userInfo = userInfo;
183
- return userInfo;
184
- };
185
-
186
- const eventNames = {
187
- service_worker_not_supported_by_browser: 'service_worker_not_supported_by_browser',
188
- token_aquired: 'token_aquired',
189
- logout_from_another_tab: 'logout_from_another_tab',
190
- logout_from_same_tab: 'logout_from_same_tab',
191
- token_renewed: 'token_renewed',
192
- token_timer: 'token_timer',
193
- loginAsync_begin: 'loginAsync_begin',
194
- loginAsync_error: 'loginAsync_error',
195
- loginCallbackAsync_begin: 'loginCallbackAsync_begin',
196
- loginCallbackAsync_end: 'loginCallbackAsync_end',
197
- loginCallbackAsync_error: 'loginCallbackAsync_error',
198
- refreshTokensAsync_begin: 'refreshTokensAsync_begin',
199
- refreshTokensAsync: 'refreshTokensAsync',
200
- refreshTokensAsync_end: 'refreshTokensAsync_end',
201
- refreshTokensAsync_error: 'refreshTokensAsync_error',
202
- refreshTokensAsync_silent_error: 'refreshTokensAsync_silent_error',
203
- tryKeepExistingSessionAsync_begin: 'tryKeepExistingSessionAsync_begin',
204
- tryKeepExistingSessionAsync_end: 'tryKeepExistingSessionAsync_end',
205
- tryKeepExistingSessionAsync_error: 'tryKeepExistingSessionAsync_error',
206
- silentLoginAsync_begin: 'silentLoginAsync_begin',
207
- silentLoginAsync: 'silentLoginAsync',
208
- silentLoginAsync_end: 'silentLoginAsync_end',
209
- silentLoginAsync_error: 'silentLoginAsync_error',
210
- syncTokensAsync_begin: 'syncTokensAsync_begin',
211
- syncTokensAsync_end: 'syncTokensAsync_end',
212
- syncTokensAsync_error: 'syncTokensAsync_error',
213
- };
214
-
215
70
  const getRandomInt = (max) => {
216
71
  return Math.floor(Math.random() * max);
217
72
  };
218
73
 
219
- const oneHourSecond = 60 * 60;
220
- const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage = window.sessionStorage):
221
- Promise<OidcAuthorizationServiceConfiguration> => {
222
- const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
223
-
224
- const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
225
- const data = getFromCache(localStorageKey, storage, timeCacheSecond);
226
- if (data) {
227
- return new OidcAuthorizationServiceConfiguration(data);
228
- }
229
- const response = await fetch(fullUrl);
230
-
231
- if (response.status !== 200) {
232
- return null;
233
- }
234
-
235
- const result = await response.json();
236
-
237
- setCache(localStorageKey, result, storage);
238
- return new OidcAuthorizationServiceConfiguration(result);
239
- };
240
-
241
74
  export class Oidc {
242
75
  public configuration: OidcConfiguration;
243
76
  public userInfo: null;
244
77
  public tokens?: Tokens;
245
78
  public events: Array<any>;
246
79
  private timeoutId: NodeJS.Timeout;
247
- private configurationName: string;
80
+ public configurationName: string;
248
81
  private checkSessionIFrame: CheckSessionIFrame;
249
82
  constructor(configuration:OidcConfiguration, configurationName = 'default') {
250
83
  let silent_login_uri = configuration.silent_login_uri;
@@ -268,7 +101,6 @@ export class Oidc {
268
101
  this.loginCallbackWithAutoTokensRenewAsync.bind(this);
269
102
  this.initAsync.bind(this);
270
103
  this.loginCallbackAsync.bind(this);
271
- this._loginCallbackAsync.bind(this);
272
104
  this.subscribeEvents.bind(this);
273
105
  this.removeEventSubscription.bind(this);
274
106
  this.publishEvent.bind(this);
@@ -334,99 +166,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
334
166
  }
335
167
  }
336
168
 
337
- async silentLoginAsync(extras:StringMap = null, state:string = null, scope:string = null) {
338
- if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
339
- return Promise.resolve(null);
340
- }
341
-
342
- try {
343
- this.publishEvent(eventNames.silentLoginAsync_begin, {});
344
- const configuration = this.configuration;
345
- let queries = '';
346
-
347
- if (state) {
348
- if (extras == null) {
349
- extras = {};
350
- }
351
- extras.state = state;
352
- }
353
-
354
- if (scope) {
355
- if (extras == null) {
356
- extras = {};
357
- }
358
- extras.scope = scope;
359
- }
360
-
361
- if (extras != null) {
362
- for (const [key, value] of Object.entries(extras)) {
363
- if (queries === '') {
364
- queries = `?${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
365
- } else {
366
- queries += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
367
- }
368
- }
369
- }
370
- const link = configuration.silent_login_uri + queries;
371
- const idx = link.indexOf('/', link.indexOf('//') + 2);
372
- const iFrameOrigin = link.substr(0, idx);
373
- const iframe = document.createElement('iframe');
374
- iframe.width = '0px';
375
- iframe.height = '0px';
376
-
377
- iframe.id = `${this.configurationName}_oidc_iframe`;
378
- iframe.setAttribute('src', link);
379
- document.body.appendChild(iframe);
380
- return new Promise((resolve, reject) => {
381
- try {
382
- let isResolved = false;
383
- window.onmessage = (e: MessageEvent<any>) => {
384
- if (e.origin === iFrameOrigin &&
385
- e.source === iframe.contentWindow
386
- ) {
387
- const key = `${this.configurationName}_oidc_tokens:`;
388
- const key_error = `${this.configurationName}_oidc_error:`;
389
- const data = e.data;
390
- if (data && typeof (data) === 'string') {
391
- if (!isResolved) {
392
- if (data.startsWith(key)) {
393
- const result = JSON.parse(e.data.replace(key, ''));
394
- this.publishEvent(eventNames.silentLoginAsync_end, {});
395
- iframe.remove();
396
- isResolved = true;
397
- resolve(result);
398
- } else if (data.startsWith(key_error)) {
399
- const result = JSON.parse(e.data.replace(key_error, ''));
400
- this.publishEvent(eventNames.silentLoginAsync_error, result);
401
- iframe.remove();
402
- isResolved = true;
403
- reject(new Error('oidc_' + result.error));
404
- }
405
- }
406
- }
407
- }
408
- };
409
- const silentSigninTimeout = configuration.silent_login_timeout;
410
- setTimeout(() => {
411
- if (!isResolved) {
412
- this.publishEvent(eventNames.silentLoginAsync_error, { reason: 'timeout' });
413
- iframe.remove();
414
- isResolved = true;
415
- reject(new Error('timeout'));
416
- }
417
- }, silentSigninTimeout);
418
- } catch (e) {
419
- iframe.remove();
420
- this.publishEvent(eventNames.silentLoginAsync_error, e);
421
- reject(e);
422
- }
423
- });
424
- } catch (e) {
425
- this.publishEvent(eventNames.silentLoginAsync_error, e);
426
- throw e;
427
- }
428
- }
429
-
430
169
  initPromise = null;
431
170
  async initAsync(authority:string, authorityConfiguration:AuthorityConfiguration) {
432
171
  if (this.initPromise !== null) {
@@ -445,7 +184,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
445
184
  });
446
185
  }
447
186
 
448
- const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName, this.configuration.redirect_uri);
187
+ const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
449
188
  const storage = serviceWorker ? window.localStorage : null;
450
189
  return await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
451
190
  };
@@ -470,15 +209,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
470
209
  try {
471
210
  const configuration = this.configuration;
472
211
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
473
- serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, configuration.redirect_uri);
212
+ serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
474
213
  if (serviceWorker) {
475
214
  const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'tryKeepExistingSessionAsync', configuration);
476
215
  if (tokens) {
477
216
  serviceWorker.startKeepAliveServiceWorker();
478
217
  // @ts-ignore
479
218
  this.tokens = tokens;
219
+ const getLoginParams = serviceWorker.getLoginParams(this.configurationName);
480
220
  // @ts-ignore
481
- this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
221
+ this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, getLoginParams.extras);
482
222
  const sessionState = await serviceWorker.getSessionStateAsync();
483
223
  // @ts-ignore
484
224
  await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
@@ -498,13 +238,14 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
498
238
  message: 'service worker is not supported by this browser',
499
239
  });
500
240
  }
501
- const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
241
+ const session = initSession(this.configurationName, configuration.storage ?? sessionStorage);
502
242
  const { tokens } = await session.initAsync();
503
243
  if (tokens) {
504
244
  // @ts-ignore
505
245
  this.tokens = setTokens(tokens, null, configuration.token_renew_mode);
246
+ const getLoginParams = session.getLoginParams(this.configurationName);
506
247
  // @ts-ignore
507
- this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt);
248
+ this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt, getLoginParams.extras);
508
249
  const sessionState = session.getSessionState();
509
250
  // @ts-ignore
510
251
  await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
@@ -537,146 +278,31 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
537
278
  });
538
279
  }
539
280
 
281
+ async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin = false) {
282
+ const getCurrentTokens = () => this.tokens;
283
+
284
+ const silentLoginAsync = (extras, state, scope) => {
285
+ return _silentLoginAsync(this.configurationName, this.configuration, this.publishEvent.bind(this))(extras, state, scope);
286
+ };
287
+
288
+ this.checkSessionIFrame = await defaultStartCheckSessionAsync(oidcDatabase, this.configuration, this.checkSessionIFrame, silentLoginAsync.bind(this), getCurrentTokens)(checkSessionIFrameUri, clientId, sessionState, isSilentSignin);
289
+ }
290
+
540
291
  loginPromise: Promise<void> = null;
541
292
  async loginAsync(callbackPath:string = undefined, extras:StringMap = null, isSilentSignin = false, scope:string = undefined, silentLoginOnly = false) {
542
293
  if (this.loginPromise !== null) {
543
294
  return this.loginPromise;
544
295
  }
545
- const loginLocalAsync = async () => {
546
- const location = window.location;
547
- const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
548
- const configuration = this.configuration;
549
- let state;
550
- if (extras && 'state' in extras) {
551
- state = extras.state;
552
- delete extras.state;
553
- }
554
- if (silentLoginOnly) {
555
- try {
556
- const extraFinal = extras ?? configuration.extras ?? {};
557
- const silentResult = await this.silentLoginAsync({
558
- ...extraFinal,
559
- prompt: 'none',
560
- }, state, scope);
561
-
562
- if (silentResult) {
563
- this.tokens = silentResult.tokens;
564
- this.publishEvent(eventNames.token_aquired, {});
565
- // @ts-ignore
566
- this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, extras);
567
- return {};
568
- }
569
- } catch (e) {
570
- return e;
571
- }
572
- }
573
- this.publishEvent(eventNames.loginAsync_begin, {});
574
-
575
- try {
576
- const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
577
- if (!scope) {
578
- scope = configuration.scope;
579
- }
580
-
581
- const extraFinal = extras ?? configuration.extras ?? {};
582
- if (!extraFinal.nonce) {
583
- extraFinal.nonce = randomString(12);
584
- }
585
- const nonce = { nonce: extraFinal.nonce };
586
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, this.configuration.redirect_uri);
587
- const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
588
- let storage;
589
- if (serviceWorker) {
590
- serviceWorker.setLoginParams(this.configurationName, redirectUri, { callbackPath: url, extras, state });
591
- serviceWorker.startKeepAliveServiceWorker();
592
- await serviceWorker.initAsync(oidcServerConfiguration, 'loginAsync', configuration);
593
- await serviceWorker.setNonceAsync(nonce);
594
- storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, {});
595
- await storage.setItem('dummy', {});
596
- } else {
597
- const session = initSession(this.configurationName, redirectUri);
598
- session.setLoginParams(this.configurationName, redirectUri, { callbackPath: url, extras, state });
599
- await session.setNonceAsync(nonce);
600
- storage = new MemoryStorageBackend(session.saveItemsAsync, {});
601
- }
602
-
603
- // @ts-ignore
604
- const queryStringUtil = redirectUri.includes('#') ? new HashQueryStringUtils() : new NoHashQueryStringUtils();
605
- const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
606
- const authRequest = new AuthorizationRequest({
607
- client_id: configuration.client_id,
608
- redirect_uri: redirectUri,
609
- scope,
610
- response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
611
- state,
612
- extras: extraFinal,
613
- });
614
- authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
615
- } catch (exception) {
616
- this.publishEvent(eventNames.loginAsync_error, exception);
617
- throw exception;
618
- }
619
- };
620
- this.loginPromise = loginLocalAsync();
296
+ if (silentLoginOnly) {
297
+ return defaultSilentLoginAsync(window, this.configurationName, this.configuration, this.publishEvent.bind(this), this)(extras, scope);
298
+ }
299
+ this.loginPromise = defaultLoginAsync(window, this.configurationName, this.configuration, this.publishEvent.bind(this), this.initAsync.bind(this))(callbackPath, extras, isSilentSignin, scope);
621
300
  return this.loginPromise.then(result => {
622
301
  this.loginPromise = null;
623
302
  return result;
624
303
  });
625
304
  }
626
305
 
627
- async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin = false) {
628
- return new Promise<void>((resolve, reject): void => {
629
- if (this.configuration.silent_login_uri && this.configuration.silent_redirect_uri && this.configuration.monitor_session && checkSessionIFrameUri && sessionState && !isSilentSignin) {
630
- const checkSessionCallback = () => {
631
- this.checkSessionIFrame.stop();
632
-
633
- if (this.tokens === null) {
634
- return;
635
- }
636
- // @ts-ignore
637
- const idToken = this.tokens.idToken;
638
- // @ts-ignore
639
- const idTokenPayload = this.tokens.idTokenPayload;
640
- this.silentLoginAsync({
641
- prompt: 'none',
642
- id_token_hint: idToken,
643
- scope: 'openid',
644
- }).then((silentSigninResponse) => {
645
- const iFrameIdTokenPayload = silentSigninResponse.tokens.idTokenPayload;
646
- if (idTokenPayload.sub === iFrameIdTokenPayload.sub) {
647
- const sessionState = silentSigninResponse.sessionState;
648
- this.checkSessionIFrame.start(silentSigninResponse.sessionState);
649
- if (idTokenPayload.sid === iFrameIdTokenPayload.sid) {
650
- console.debug('SessionMonitor._callback: Same sub still logged in at OP, restarting check session iframe; session_state:', sessionState);
651
- } else {
652
- console.debug('SessionMonitor._callback: Same sub still logged in at OP, session state has changed, restarting check session iframe; session_state:', sessionState);
653
- }
654
- } else {
655
- console.debug('SessionMonitor._callback: Different subject signed into OP:', iFrameIdTokenPayload.sub);
656
- }
657
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
658
- }).catch(async (e) => {
659
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
660
- for (const [key, oidc] of Object.entries(oidcDatabase)) {
661
- // @ts-ignore
662
- await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
663
- }
664
- });
665
- };
666
-
667
- this.checkSessionIFrame = new CheckSessionIFrame(checkSessionCallback, clientId, checkSessionIFrameUri);
668
- this.checkSessionIFrame.load().then(() => {
669
- this.checkSessionIFrame.start(sessionState);
670
- resolve();
671
- }).catch((e) => {
672
- reject(e);
673
- });
674
- } else {
675
- resolve();
676
- }
677
- });
678
- }
679
-
680
306
  loginCallbackPromise : Promise<any> = null;
681
307
  async loginCallbackAsync(isSilenSignin = false) {
682
308
  if (this.loginCallbackPromise !== null) {
@@ -684,14 +310,14 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
684
310
  }
685
311
 
686
312
  const loginCallbackLocalAsync = async():Promise<InternalLoginCallback> => {
687
- const response = await this._loginCallbackAsync(isSilenSignin);
313
+ const response = await loginCallbackAsync(this)(isSilenSignin);
688
314
  // @ts-ignore
689
315
  const parsedTokens = response.tokens;
690
316
  // @ts-ignore
691
317
  this.tokens = response.tokens;
692
- const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName, this.configuration.redirect_uri);
318
+ const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
693
319
  if (!serviceWorker) {
694
- const session = initSession(this.configurationName, this.configuration.redirect_uri, this.configuration.storage);
320
+ const session = initSession(this.configurationName, this.configuration.storage);
695
321
  session.setTokens(parsedTokens);
696
322
  }
697
323
  this.publishEvent(Oidc.eventNames.token_aquired, parsedTokens);
@@ -705,143 +331,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
705
331
  });
706
332
  }
707
333
 
708
- async _loginCallbackAsync(isSilentSignin = false) {
709
- try {
710
- this.publishEvent(eventNames.loginCallbackAsync_begin, {});
711
- const configuration = this.configuration;
712
- const clientId = configuration.client_id;
713
- const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
714
- const authority = configuration.authority;
715
- const tokenRequestTimeout = configuration.token_request_timeout;
716
- const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
717
- const queryParams = getParseQueryStringFromLocation(window.location.href);
718
- const sessionState = queryParams.session_state;
719
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, configuration.redirect_uri);
720
- let storage = null;
721
- let nonceData = null;
722
- if (serviceWorker) {
723
- serviceWorker.startKeepAliveServiceWorker();
724
- await serviceWorker.initAsync(oidcServerConfiguration, 'loginCallbackAsync', configuration);
725
- const items = await serviceWorker.loadItemsAsync();
726
- storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, items);
727
- const dummy = await storage.getItem('dummy');
728
- if (!dummy) {
729
- throw new Error('Service Worker storage disapear');
730
- }
731
- await storage.removeItem('dummy');
732
- await serviceWorker.setSessionStateAsync(sessionState);
733
- nonceData = await serviceWorker.getNonceAsync();
734
- } else {
735
- const session = initSession(this.configurationName, redirectUri);
736
- session.setSessionState(sessionState);
737
- const items = await session.loadItemsAsync();
738
- storage = new MemoryStorageBackend(session.saveItemsAsync, items);
739
- nonceData = await session.getNonceAsync();
740
- }
741
-
742
- return new Promise((resolve, reject) => {
743
- let queryStringUtil = new NoHashQueryStringUtils();
744
- if (redirectUri.includes('#')) {
745
- const splithash = window.location.href.split('#');
746
- if (splithash.length === 2 && splithash[1].includes('?')) {
747
- queryStringUtil = new HashQueryStringUtils();
748
- }
749
- }
750
- const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
751
- const notifier = new AuthorizationNotifier();
752
- authorizationHandler.setAuthorizationNotifier(notifier);
753
-
754
- notifier.setAuthorizationListener((request, response, error) => {
755
- if (error) {
756
- reject(error);
757
- return;
758
- }
759
- if (!response) {
760
- reject(new Error('no response'));
761
- return;
762
- }
763
-
764
- let extras = null;
765
- if (request && request.internal) {
766
- extras = {};
767
- extras.code_verifier = request.internal.code_verifier;
768
- if (configuration.token_request_extras) {
769
- for (const [key, value] of Object.entries(configuration.token_request_extras)) {
770
- extras[key] = value;
771
- }
772
- }
773
- }
774
-
775
- const tokenRequest = new TokenRequest({
776
- client_id: clientId,
777
- redirect_uri: redirectUri,
778
- grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
779
- code: response.code,
780
- refresh_token: undefined,
781
- extras,
782
- });
783
-
784
- let timeoutId = setTimeout(() => {
785
- reject(new Error('performTokenRequest timeout'));
786
- timeoutId = null;
787
- }, tokenRequestTimeout ?? 12000);
788
- try {
789
- const tokenHandler = new BaseTokenRequestHandler(new FetchRequestor());
790
- tokenHandler.performTokenRequest(oidcServerConfiguration, tokenRequest).then(async (tokenResponse) => {
791
- if (timeoutId) {
792
- clearTimeout(timeoutId);
793
- this.timeoutId = null;
794
- let loginParams = null;
795
- let formattedTokens = null;
796
- if (serviceWorker) {
797
- const { tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'syncTokensAsync', configuration);
798
- loginParams = serviceWorker.getLoginParams(this.configurationName, redirectUri);
799
- formattedTokens = tokens;
800
- } else {
801
- const session = initSession(this.configurationName, redirectUri, configuration.storage);
802
- loginParams = session.getLoginParams(this.configurationName, redirectUri);
803
- formattedTokens = setTokens(tokenResponse, null, configuration.token_renew_mode);
804
- }
805
- if (!isTokensOidcValid(formattedTokens, nonceData.nonce, oidcServerConfiguration)) {
806
- const exception = new Error('Tokens are not OpenID valid');
807
- if (timeoutId) {
808
- clearTimeout(timeoutId);
809
- this.timeoutId = null;
810
- this.publishEvent(eventNames.loginCallbackAsync_error, exception);
811
- console.error(exception);
812
- reject(exception);
813
- }
814
- }
815
-
816
- this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin).then(() => {
817
- this.publishEvent(eventNames.loginCallbackAsync_end, {});
818
- resolve({
819
- tokens: formattedTokens,
820
- state: request.state,
821
- callbackPath: loginParams.callbackPath,
822
- });
823
- });
824
- }
825
- });
826
- } catch (exception) {
827
- if (timeoutId) {
828
- clearTimeout(timeoutId);
829
- this.timeoutId = null;
830
- this.publishEvent(eventNames.loginCallbackAsync_error, exception);
831
- console.error(exception);
832
- reject(exception);
833
- }
834
- }
835
- });
836
- authorizationHandler.completeAuthorizationRequestIfPossible();
837
- });
838
- } catch (exception) {
839
- console.error(exception);
840
- this.publishEvent(eventNames.loginCallbackAsync_error, exception);
841
- throw exception;
842
- }
843
- }
844
-
845
334
  async synchroniseTokensAsync(refreshToken, index = 0, forceRefresh = false, extras:StringMap = null, updateTokens) {
846
335
  while (!navigator.onLine && document.hidden) {
847
336
  await sleepAsync(1000);
@@ -865,17 +354,21 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
865
354
  extras = {};
866
355
  }
867
356
  const configuration = this.configuration;
357
+
358
+ const silentLoginAsync = (extras: StringMap, state:string, scope:string = null) => {
359
+ return _silentLoginAsync(this.configurationName, this.configuration, this.publishEvent.bind(this))(extras, state, scope);
360
+ };
868
361
  const localsilentLoginAsync = async () => {
869
362
  try {
870
363
  let loginParams = null;
871
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName, configuration.redirect_uri);
364
+ const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
872
365
  if (serviceWorker) {
873
- loginParams = serviceWorker.getLoginParams(this.configurationName, configuration.redirect_uri);
366
+ loginParams = serviceWorker.getLoginParams(this.configurationName);
874
367
  } else {
875
- const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage);
876
- loginParams = session.getLoginParams(this.configurationName, configuration.redirect_uri);
368
+ const session = initSession(this.configurationName, configuration.storage);
369
+ loginParams = session.getLoginParams(this.configurationName);
877
370
  }
878
- const silent_token_response = await this.silentLoginAsync({
371
+ const silent_token_response = await silentLoginAsync({
879
372
  ...loginParams.extras,
880
373
  ...extras,
881
374
  prompt: 'none',
@@ -936,7 +429,13 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
936
429
  const redirectUri = configuration.redirect_uri;
937
430
  const authority = configuration.authority;
938
431
  const tokenExtras = configuration.token_request_extras ? configuration.token_request_extras : {};
939
- const finalExtras = { ...tokenExtras, ...extras };
432
+ const finalExtras = { ...tokenExtras };
433
+
434
+ for (const [key, value] of Object.entries(extras)) {
435
+ if (key.endsWith(':token_request')) {
436
+ finalExtras[key.replace(':token_request', '')] = value;
437
+ }
438
+ }
940
439
  const localFunctionAsync = async () => {
941
440
  const details = {
942
441
  client_id: clientId,
@@ -985,7 +484,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
985
484
  }
986
485
  let nonce = nullNonce;
987
486
  const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
988
- const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName, configuration.redirect_uri);
487
+ const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
989
488
  if (serviceWorker) {
990
489
  const { status, tokens } = await serviceWorker.initAsync(oidcServerConfiguration, 'syncTokensAsync', configuration);
991
490
  if (status === 'LOGGED_OUT') {
@@ -1002,7 +501,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1002
501
  }
1003
502
  nonce = await serviceWorker.getNonceAsync();
1004
503
  } else {
1005
- const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
504
+ const session = initSession(configurationName, configuration.storage ?? sessionStorage);
1006
505
  const { tokens, status } = await session.initAsync();
1007
506
  if (!tokens) {
1008
507
  return { tokens: null, status: 'LOGOUT_FROM_ANOTHER_TAB', nonce: nullNonce };
@@ -1064,9 +563,9 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
1064
563
  if (this.checkSessionIFrame) {
1065
564
  this.checkSessionIFrame.stop();
1066
565
  }
1067
- const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName, this.configuration.redirect_uri);
566
+ const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
1068
567
  if (!serviceWorker) {
1069
- const session = initSession(this.configurationName, this.configuration.redirect_uri, this.configuration.storage);
568
+ const session = initSession(this.configurationName, this.configuration.storage);
1070
569
  await session.clearAsync(status);
1071
570
  } else {
1072
571
  await serviceWorker.clearAsync(status);