@axa-fr/oidc-client 7.22.18 → 7.22.19

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 (73) hide show
  1. package/README.md +31 -39
  2. package/bin/copy-service-worker-files.mjs +24 -17
  3. package/dist/OidcTrustedDomains.js +14 -12
  4. package/dist/cache.d.ts.map +1 -1
  5. package/dist/checkSession.d.ts +1 -1
  6. package/dist/checkSession.d.ts.map +1 -1
  7. package/dist/checkSessionIFrame.d.ts.map +1 -1
  8. package/dist/crypto.d.ts.map +1 -1
  9. package/dist/fetch.d.ts +2 -1
  10. package/dist/fetch.d.ts.map +1 -1
  11. package/dist/index.d.ts +5 -5
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +935 -601
  14. package/dist/index.umd.cjs +2 -2
  15. package/dist/initSession.d.ts +1 -1
  16. package/dist/initSession.d.ts.map +1 -1
  17. package/dist/initWorker.d.ts +2 -2
  18. package/dist/initWorker.d.ts.map +1 -1
  19. package/dist/initWorkerOption.d.ts.map +1 -1
  20. package/dist/jwt.d.ts +2 -2
  21. package/dist/jwt.d.ts.map +1 -1
  22. package/dist/keepSession.d.ts.map +1 -1
  23. package/dist/location.d.ts.map +1 -1
  24. package/dist/login.d.ts +1 -1
  25. package/dist/login.d.ts.map +1 -1
  26. package/dist/logout.d.ts +1 -1
  27. package/dist/logout.d.ts.map +1 -1
  28. package/dist/oidc.d.ts +1 -1
  29. package/dist/oidc.d.ts.map +1 -1
  30. package/dist/oidcClient.d.ts +2 -2
  31. package/dist/oidcClient.d.ts.map +1 -1
  32. package/dist/parseTokens.d.ts.map +1 -1
  33. package/dist/renewTokens.d.ts.map +1 -1
  34. package/dist/requests.d.ts +1 -1
  35. package/dist/requests.d.ts.map +1 -1
  36. package/dist/silentLogin.d.ts.map +1 -1
  37. package/dist/timer.d.ts.map +1 -1
  38. package/dist/types.d.ts +1 -1
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/user.d.ts.map +1 -1
  41. package/dist/version.d.ts +1 -1
  42. package/package.json +2 -2
  43. package/src/cache.ts +21 -18
  44. package/src/checkSession.ts +89 -54
  45. package/src/checkSessionIFrame.ts +70 -69
  46. package/src/crypto.ts +27 -25
  47. package/src/events.ts +28 -28
  48. package/src/fetch.ts +40 -21
  49. package/src/index.ts +6 -17
  50. package/src/iniWorker.spec.ts +26 -16
  51. package/src/initSession.ts +115 -113
  52. package/src/initWorker.ts +299 -212
  53. package/src/initWorkerOption.ts +121 -114
  54. package/src/jwt.ts +150 -136
  55. package/src/keepSession.ts +100 -81
  56. package/src/location.ts +24 -26
  57. package/src/login.ts +246 -189
  58. package/src/logout.spec.ts +131 -76
  59. package/src/logout.ts +130 -115
  60. package/src/oidc.ts +426 -337
  61. package/src/oidcClient.ts +129 -105
  62. package/src/parseTokens.spec.ts +198 -179
  63. package/src/parseTokens.ts +221 -186
  64. package/src/renewTokens.ts +397 -284
  65. package/src/requests.spec.ts +5 -7
  66. package/src/requests.ts +142 -114
  67. package/src/route-utils.spec.ts +17 -19
  68. package/src/route-utils.ts +29 -26
  69. package/src/silentLogin.ts +145 -127
  70. package/src/timer.ts +10 -11
  71. package/src/types.ts +56 -46
  72. package/src/user.ts +17 -12
  73. package/src/version.ts +1 -1
@@ -1,9 +1,7 @@
1
- 
2
- import { describe, expect,it } from 'vitest';
3
-
1
+ import { describe, expect, it } from 'vitest';
4
2
 
5
3
  describe('Requests test Suite', () => {
6
- it('performAuthorizationRequestAsync', async () => {
7
- expect(true).toBe(true);
8
- });
9
- });
4
+ it('performAuthorizationRequestAsync', async () => {
5
+ expect(true).toBe(true);
6
+ });
7
+ });
package/src/requests.ts CHANGED
@@ -1,159 +1,183 @@
1
1
  import { getFromCache, setCache } from './cache.js';
2
2
  import { deriveChallengeAsync, generateRandom } from './crypto.js';
3
+ import { ILOidcLocation } from './location';
3
4
  import { OidcAuthorizationServiceConfiguration } from './oidc.js';
4
5
  import { parseOriginalTokens } from './parseTokens.js';
5
6
  import { Fetch, StringMap } from './types.js';
6
- import {ILOidcLocation} from "./location";
7
7
 
8
8
  const oneHourSecond = 60 * 60;
9
- export const fetchFromIssuer = (fetch) => async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage = window.sessionStorage, timeoutMs = 10000):
10
- Promise<OidcAuthorizationServiceConfiguration> => {
9
+ export const fetchFromIssuer =
10
+ fetch =>
11
+ async (
12
+ openIdIssuerUrl: string,
13
+ timeCacheSecond = oneHourSecond,
14
+ storage = window.sessionStorage,
15
+ timeoutMs = 10000,
16
+ ): Promise<OidcAuthorizationServiceConfiguration> => {
11
17
  const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
12
18
 
13
19
  const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
14
20
  const data = getFromCache(localStorageKey, storage, timeCacheSecond);
15
21
  if (data) {
16
- return new OidcAuthorizationServiceConfiguration(data);
22
+ return new OidcAuthorizationServiceConfiguration(data);
17
23
  }
18
24
  const response = await internalFetch(fetch)(fullUrl, {}, timeoutMs);
19
25
 
20
26
  if (response.status !== 200) {
21
- return null;
27
+ return null;
22
28
  }
23
29
 
24
30
  const result = await response.json();
25
31
 
26
32
  setCache(localStorageKey, result, storage);
27
33
  return new OidcAuthorizationServiceConfiguration(result);
28
- };
34
+ };
29
35
 
30
- const internalFetch = (fetch) => async (url:string, headers = {}, timeoutMs = 10000, numberRetry = 0) : Promise<Response> => {
36
+ const internalFetch =
37
+ fetch =>
38
+ async (url: string, headers = {}, timeoutMs = 10000, numberRetry = 0): Promise<Response> => {
31
39
  let response;
32
40
  try {
33
- const controller = new AbortController();
34
- setTimeout(() => controller.abort(), timeoutMs);
35
- response = await fetch(url, { ...headers, signal: controller.signal });
41
+ const controller = new AbortController();
42
+ setTimeout(() => controller.abort(), timeoutMs);
43
+ response = await fetch(url, { ...headers, signal: controller.signal });
36
44
  } catch (e: any) {
37
- if (e.name === 'AbortError' ||
38
- e.message === 'Network request failed') {
39
- if (numberRetry <= 1) {
40
- return await internalFetch(fetch)(url, headers, timeoutMs, numberRetry + 1);
41
- } else {
42
- throw e;
43
- }
45
+ if (e.name === 'AbortError' || e.message === 'Network request failed') {
46
+ if (numberRetry <= 1) {
47
+ return await internalFetch(fetch)(url, headers, timeoutMs, numberRetry + 1);
44
48
  } else {
45
- console.error(e.message);
46
- throw e; // rethrow other unexpected errors
49
+ throw e;
47
50
  }
51
+ } else {
52
+ console.error(e.message);
53
+ throw e; // rethrow other unexpected errors
54
+ }
48
55
  }
49
56
  return response;
50
- };
57
+ };
51
58
 
52
59
  export const TOKEN_TYPE = {
53
- refresh_token: 'refresh_token',
54
- access_token: 'access_token',
60
+ refresh_token: 'refresh_token',
61
+ access_token: 'access_token',
55
62
  };
56
63
 
57
- export const performRevocationRequestAsync = (fetch) => async (url,
58
- token,
59
- token_type = TOKEN_TYPE.refresh_token,
60
- client_id,
61
- extras:StringMap = {},
62
- timeoutMs = 10000) => {
64
+ export const performRevocationRequestAsync =
65
+ fetch =>
66
+ async (
67
+ url,
68
+ token,
69
+ token_type = TOKEN_TYPE.refresh_token,
70
+ client_id,
71
+ extras: StringMap = {},
72
+ timeoutMs = 10000,
73
+ ) => {
63
74
  const details = {
64
- token,
65
- token_type_hint: token_type,
66
- client_id,
75
+ token,
76
+ token_type_hint: token_type,
77
+ client_id,
67
78
  };
68
79
  for (const [key, value] of Object.entries(extras)) {
69
-
70
- if (details[key] === undefined) {
71
- details[key] = value;
72
- }
80
+ if (details[key] === undefined) {
81
+ details[key] = value;
82
+ }
73
83
  }
74
84
 
75
85
  const formBody = [];
76
86
  for (const property in details) {
77
- const encodedKey = encodeURIComponent(property);
78
- const encodedValue = encodeURIComponent(details[property]);
79
- formBody.push(`${encodedKey}=${encodedValue}`);
87
+ const encodedKey = encodeURIComponent(property);
88
+ const encodedValue = encodeURIComponent(details[property]);
89
+ formBody.push(`${encodedKey}=${encodedValue}`);
80
90
  }
81
91
  const formBodyString = formBody.join('&');
82
92
 
83
- const response = await internalFetch(fetch)(url, {
93
+ const response = await internalFetch(fetch)(
94
+ url,
95
+ {
84
96
  method: 'POST',
85
97
  headers: {
86
- 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
98
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
87
99
  },
88
100
  body: formBodyString,
89
- }, timeoutMs);
101
+ },
102
+ timeoutMs,
103
+ );
90
104
  if (response.status !== 200) {
91
- return { success: false };
105
+ return { success: false };
92
106
  }
93
107
  return {
94
- success: true,
108
+ success: true,
95
109
  };
96
- };
97
-
110
+ };
98
111
 
99
112
  type PerformTokenRequestResponse = {
100
- success: boolean;
101
- status?: number;
102
- data?: any;
103
- demonstratingProofOfPossessionNonce?: string;
104
- }
105
-
106
- export const performTokenRequestAsync = (fetch:Fetch) => async (url:string,
107
- details,
108
- extras,
109
- oldTokens,
110
- headersExtras = {},
111
- tokenRenewMode: string,
112
- timeoutMs = 10000):Promise<PerformTokenRequestResponse> => {
113
+ success: boolean;
114
+ status?: number;
115
+ data?: any;
116
+ demonstratingProofOfPossessionNonce?: string;
117
+ };
118
+
119
+ export const performTokenRequestAsync =
120
+ (fetch: Fetch) =>
121
+ async (
122
+ url: string,
123
+ details,
124
+ extras,
125
+ oldTokens,
126
+ headersExtras = {},
127
+ tokenRenewMode: string,
128
+ timeoutMs = 10000,
129
+ ): Promise<PerformTokenRequestResponse> => {
113
130
  for (const [key, value] of Object.entries(extras)) {
114
- if (details[key] === undefined) {
115
- details[key] = value;
116
- }
131
+ if (details[key] === undefined) {
132
+ details[key] = value;
133
+ }
117
134
  }
118
135
 
119
136
  const formBody = [];
120
137
  for (const property in details) {
121
- const encodedKey = encodeURIComponent(property);
122
- const encodedValue = encodeURIComponent(details[property]);
123
- formBody.push(`${encodedKey}=${encodedValue}`);
138
+ const encodedKey = encodeURIComponent(property);
139
+ const encodedValue = encodeURIComponent(details[property]);
140
+ formBody.push(`${encodedKey}=${encodedValue}`);
124
141
  }
125
142
  const formBodyString = formBody.join('&');
126
-
127
- const response = await internalFetch(fetch)(url, {
143
+
144
+ const response = await internalFetch(fetch)(
145
+ url,
146
+ {
128
147
  method: 'POST',
129
148
  headers: {
130
- 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
131
- ...headersExtras
149
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
150
+ ...headersExtras,
132
151
  },
133
152
  body: formBodyString,
134
- }, timeoutMs);
153
+ },
154
+ timeoutMs,
155
+ );
135
156
  if (response.status !== 200) {
136
- return {
137
- success: false,
138
- status: response.status,
139
- demonstratingProofOfPossessionNonce:null
140
- };
157
+ return {
158
+ success: false,
159
+ status: response.status,
160
+ demonstratingProofOfPossessionNonce: null,
161
+ };
141
162
  }
142
163
  const tokens = await response.json();
143
164
 
144
165
  let demonstratingProofOfPossessionNonce = null;
145
- if( response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)){
146
- demonstratingProofOfPossessionNonce = response.headers.get(demonstratingProofOfPossessionNonceResponseHeader);
166
+ if (response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)) {
167
+ demonstratingProofOfPossessionNonce = response.headers.get(
168
+ demonstratingProofOfPossessionNonceResponseHeader,
169
+ );
147
170
  }
148
171
  return {
149
- success: true,
150
- status: response.status,
151
- data: parseOriginalTokens(tokens, oldTokens, tokenRenewMode),
152
- demonstratingProofOfPossessionNonce: demonstratingProofOfPossessionNonce,
172
+ success: true,
173
+ status: response.status,
174
+ data: parseOriginalTokens(tokens, oldTokens, tokenRenewMode),
175
+ demonstratingProofOfPossessionNonce: demonstratingProofOfPossessionNonce,
153
176
  };
154
- };
177
+ };
155
178
 
156
- export const performAuthorizationRequestAsync = (storage: any, oidcLocation: ILOidcLocation) => async (url, extras: StringMap) => {
179
+ export const performAuthorizationRequestAsync =
180
+ (storage: any, oidcLocation: ILOidcLocation) => async (url, extras: StringMap) => {
157
181
  extras = extras ? { ...extras } : {};
158
182
  const codeVerifier = generateRandom(128);
159
183
  const codeChallenge = await deriveChallengeAsync(codeVerifier);
@@ -163,56 +187,60 @@ export const performAuthorizationRequestAsync = (storage: any, oidcLocation: ILO
163
187
  extras.code_challenge_method = 'S256';
164
188
  let queryString = '';
165
189
  if (extras) {
166
- for (const [key, value] of Object.entries(extras)) {
167
- if (queryString === '') {
168
- queryString += '?';
169
- } else {
170
- queryString += '&';
171
- }
172
- queryString += `${key}=${encodeURIComponent(value)}`;
190
+ for (const [key, value] of Object.entries(extras)) {
191
+ if (queryString === '') {
192
+ queryString += '?';
193
+ } else {
194
+ queryString += '&';
173
195
  }
196
+ queryString += `${key}=${encodeURIComponent(value)}`;
197
+ }
174
198
  }
175
199
  oidcLocation.open(`${url}${queryString}`);
176
- };
200
+ };
177
201
 
178
- const demonstratingProofOfPossessionNonceResponseHeader = "DPoP-Nonce";
179
- export const performFirstTokenRequestAsync = (storage:any) => async (url,
180
- formBodyExtras,
181
- headersExtras,
182
- tokenRenewMode: string,
183
- timeoutMs = 10000) => {
202
+ const demonstratingProofOfPossessionNonceResponseHeader = 'DPoP-Nonce';
203
+ export const performFirstTokenRequestAsync =
204
+ (storage: any) =>
205
+ async (url, formBodyExtras, headersExtras, tokenRenewMode: string, timeoutMs = 10000) => {
184
206
  formBodyExtras = formBodyExtras ? { ...formBodyExtras } : {};
185
207
  formBodyExtras.code_verifier = await storage.getCodeVerifierAsync();
186
208
  const formBody = [];
187
209
  for (const property in formBodyExtras) {
188
- const encodedKey = encodeURIComponent(property);
189
- const encodedValue = encodeURIComponent(formBodyExtras[property]);
190
- formBody.push(`${encodedKey}=${encodedValue}`);
210
+ const encodedKey = encodeURIComponent(property);
211
+ const encodedValue = encodeURIComponent(formBodyExtras[property]);
212
+ formBody.push(`${encodedKey}=${encodedValue}`);
191
213
  }
192
214
  const formBodyString = formBody.join('&');
193
- const response = await internalFetch(fetch)(url, {
215
+ const response = await internalFetch(fetch)(
216
+ url,
217
+ {
194
218
  method: 'POST',
195
219
  headers: {
196
- 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
197
- ...headersExtras,
220
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
221
+ ...headersExtras,
198
222
  },
199
223
  body: formBodyString,
200
- }, timeoutMs);
224
+ },
225
+ timeoutMs,
226
+ );
201
227
  await Promise.all([storage.setCodeVerifierAsync(null), storage.setStateAsync(null)]);
202
228
  if (response.status !== 200) {
203
- return { success: false, status: response.status };
229
+ return { success: false, status: response.status };
204
230
  }
205
- let demonstratingProofOfPossessionNonce:string= null;
206
- if( response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)){
207
- demonstratingProofOfPossessionNonce = response.headers.get(demonstratingProofOfPossessionNonceResponseHeader);
231
+ let demonstratingProofOfPossessionNonce: string = null;
232
+ if (response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)) {
233
+ demonstratingProofOfPossessionNonce = response.headers.get(
234
+ demonstratingProofOfPossessionNonceResponseHeader,
235
+ );
208
236
  }
209
237
  const tokens = await response.json();
210
238
  return {
211
- success: true,
212
- data: {
213
- state: formBodyExtras.state,
214
- tokens: parseOriginalTokens(tokens, null, tokenRenewMode),
215
- demonstratingProofOfPossessionNonce,
216
- },
239
+ success: true,
240
+ data: {
241
+ state: formBodyExtras.state,
242
+ tokens: parseOriginalTokens(tokens, null, tokenRenewMode),
243
+ demonstratingProofOfPossessionNonce,
244
+ },
217
245
  };
218
- };
246
+ };
@@ -1,24 +1,22 @@
1
- import { describe, expect,it } from 'vitest';
1
+ import { describe, expect, it } from 'vitest';
2
2
 
3
3
  import { getPath } from './route-utils';
4
4
 
5
5
  describe('Route test Suite', () => {
6
- it.each([['http://example.com/pathname', '/pathname'],
7
- ['http://example.com:3000/pathname/?search=test#hash', '/pathname#hash'],
8
- ['http://example.com:3000/pathname/#hash?search=test', '/pathname#hash'],
9
- ['http://example.com:3000/pathname#hash?search=test', '/pathname#hash'],
10
- ['capacitor://localhost/index.html', '/index.html'],
11
- ['capacitor://localhost/pathname#hash?search=test', '/pathname#hash'],
12
- ['http://example.com:3000/', '']])(
13
- 'getPath should return the full path of an url',
14
- (uri, expected) => {
15
-
16
- const path = getPath(uri);
17
- expect(path).toBe(expected);
18
- },
19
- );
6
+ it.each([
7
+ ['http://example.com/pathname', '/pathname'],
8
+ ['http://example.com:3000/pathname/?search=test#hash', '/pathname#hash'],
9
+ ['http://example.com:3000/pathname/#hash?search=test', '/pathname#hash'],
10
+ ['http://example.com:3000/pathname#hash?search=test', '/pathname#hash'],
11
+ ['capacitor://localhost/index.html', '/index.html'],
12
+ ['capacitor://localhost/pathname#hash?search=test', '/pathname#hash'],
13
+ ['http://example.com:3000/', ''],
14
+ ])('getPath should return the full path of an url', (uri, expected) => {
15
+ const path = getPath(uri);
16
+ expect(path).toBe(expected);
17
+ });
20
18
 
21
- it('wrong uri format', () => {
22
- expect(() => getPath("urimybad/toto.com")).toThrowError();
23
- });
24
- });
19
+ it('wrong uri format', () => {
20
+ expect(() => getPath('urimybad/toto.com')).toThrowError();
21
+ });
22
+ });
@@ -1,26 +1,26 @@
1
1
  export const getLocation = (href: string) => {
2
2
  const match = href.match(
3
3
  // eslint-disable-next-line no-useless-escape
4
- /^([a-z][\w-]+\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/,
4
+ /^([a-z][\w-]+\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/,
5
5
  );
6
6
  if (!match) {
7
- throw new Error('Invalid URL');
7
+ throw new Error('Invalid URL');
8
8
  }
9
9
 
10
10
  let search = match[6];
11
11
  let hash = match[7];
12
12
 
13
- if (hash) {
14
- const splits = hash.split('?');
15
- if (splits.length === 2) {
16
- hash = splits[0];
17
- search = splits[1];
18
- }
13
+ if (hash) {
14
+ const splits = hash.split('?');
15
+ if (splits.length === 2) {
16
+ hash = splits[0];
17
+ search = splits[1];
19
18
  }
19
+ }
20
20
 
21
- if (search.startsWith('?')) {
22
- search = search.slice(1);
23
- }
21
+ if (search.startsWith('?')) {
22
+ search = search.slice(1);
23
+ }
24
24
 
25
25
  return (
26
26
  match && {
@@ -41,12 +41,12 @@ export const getPath = (href: string) => {
41
41
  let { path } = location;
42
42
 
43
43
  if (path.endsWith('/')) {
44
- path = path.slice(0, -1);
44
+ path = path.slice(0, -1);
45
45
  }
46
46
  let { hash } = location;
47
47
 
48
48
  if (hash === '#_=_') {
49
- hash = '';
49
+ hash = '';
50
50
  }
51
51
 
52
52
  if (hash) {
@@ -57,23 +57,26 @@ export const getPath = (href: string) => {
57
57
  };
58
58
 
59
59
  export const getParseQueryStringFromLocation = (href: string) => {
60
- const location = getLocation(href);
61
- const { search } = location;
60
+ const location = getLocation(href);
61
+ const { search } = location;
62
62
 
63
- return parseQueryString(search);
63
+ return parseQueryString(search);
64
64
  };
65
65
 
66
- const parseQueryString = (queryString:string) => {
67
- const params:any = {}; let temp; let i; let l;
66
+ const parseQueryString = (queryString: string) => {
67
+ const params: any = {};
68
+ let temp;
69
+ let i;
70
+ let l;
68
71
 
69
- // Split into key/value pairs
70
- const queries = queryString.split('&');
72
+ // Split into key/value pairs
73
+ const queries = queryString.split('&');
71
74
 
72
- // Convert the array of strings into an object
73
- for (i = 0, l = queries.length; i < l; i++) {
74
- temp = queries[i].split('=');
75
- params[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);
76
- }
75
+ // Convert the array of strings into an object
76
+ for (i = 0, l = queries.length; i < l; i++) {
77
+ temp = queries[i].split('=');
78
+ params[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);
79
+ }
77
80
 
78
- return params;
81
+ return params;
79
82
  };