@axa-fr/oidc-client 6.26.6
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/README.md +209 -0
- package/bin/post-install.mjs +58 -0
- package/dist/OidcServiceWorker.js +561 -0
- package/dist/OidcTrustedDomains.js +27 -0
- package/dist/cache.d.ts +3 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/checkSession.d.ts +4 -0
- package/dist/checkSession.d.ts.map +1 -0
- package/dist/checkSessionIFrame.d.ts +17 -0
- package/dist/checkSessionIFrame.d.ts.map +1 -0
- package/dist/crypto.d.ts +4 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/events.d.ts +29 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1236 -0
- package/dist/index.umd.cjs +2 -0
- package/dist/iniWorker.spec.d.ts +2 -0
- package/dist/iniWorker.spec.d.ts.map +1 -0
- package/dist/initSession.d.ts +22 -0
- package/dist/initSession.d.ts.map +1 -0
- package/dist/initWorker.d.ts +30 -0
- package/dist/initWorker.d.ts.map +1 -0
- package/dist/login.d.ts +8 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/logout.d.ts +8 -0
- package/dist/logout.d.ts.map +1 -0
- package/dist/logout.spec.d.ts +1 -0
- package/dist/logout.spec.d.ts.map +1 -0
- package/dist/oidc.d.ts +101 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/parseTokens.d.ts +37 -0
- package/dist/parseTokens.d.ts.map +1 -0
- package/dist/parseTokens.spec.d.ts +2 -0
- package/dist/parseTokens.spec.d.ts.map +1 -0
- package/dist/renewTokens.d.ts +4 -0
- package/dist/renewTokens.d.ts.map +1 -0
- package/dist/requests.d.ts +33 -0
- package/dist/requests.d.ts.map +1 -0
- package/dist/requests.spec.d.ts +2 -0
- package/dist/requests.spec.d.ts.map +1 -0
- package/dist/route-utils.d.ts +13 -0
- package/dist/route-utils.d.ts.map +1 -0
- package/dist/route-utils.spec.d.ts +2 -0
- package/dist/route-utils.spec.d.ts.map +1 -0
- package/dist/silentLogin.d.ts +10 -0
- package/dist/silentLogin.d.ts.map +1 -0
- package/dist/timer.d.ts +13 -0
- package/dist/timer.d.ts.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/user.d.ts +2 -0
- package/dist/user.d.ts.map +1 -0
- package/dist/vanillaOidc.d.ts +85 -0
- package/dist/vanillaOidc.d.ts.map +1 -0
- package/package.json +60 -0
- package/src/cache.ts +26 -0
- package/src/checkSession.ts +60 -0
- package/src/checkSessionIFrame.ts +83 -0
- package/src/crypto.ts +61 -0
- package/src/events.ts +28 -0
- package/src/index.ts +10 -0
- package/src/iniWorker.spec.ts +21 -0
- package/src/initSession.ts +89 -0
- package/src/initWorker.ts +321 -0
- package/src/login.ts +174 -0
- package/src/logout.spec.ts +65 -0
- package/src/logout.ts +101 -0
- package/src/oidc.ts +613 -0
- package/src/parseTokens.spec.ts +50 -0
- package/src/parseTokens.ts +194 -0
- package/src/renewTokens.ts +37 -0
- package/src/requests.spec.ts +9 -0
- package/src/requests.ts +169 -0
- package/src/route-utils.spec.ts +24 -0
- package/src/route-utils.ts +79 -0
- package/src/silentLogin.ts +144 -0
- package/src/timer.ts +163 -0
- package/src/types.ts +41 -0
- package/src/user.ts +40 -0
- package/src/vanillaOidc.ts +108 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vanillaOidc.d.ts","sourceRoot":"","sources":["../src/src/vanillaOidc.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@axa-fr/oidc-client",
|
|
3
|
+
"version": "6.26.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.umd.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"description": "OpenID Connect & OAuth authentication using native javascript only, compatible with angular, react, vue, svelte, next, etc.",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"bin",
|
|
13
|
+
"src",
|
|
14
|
+
"README.md",
|
|
15
|
+
"package.json",
|
|
16
|
+
"package-lock.json"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/AxaGuilDEv/react-oidc.git"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@axa-fr/oidc-client-service-worker": "6.26.6"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@testing-library/dom": "^9.3.1",
|
|
27
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
28
|
+
"@testing-library/react": "13.3.0",
|
|
29
|
+
"@vitest/coverage-v8": "^0.33.0",
|
|
30
|
+
"base64-js": "^1.5.1",
|
|
31
|
+
"cpy": "^10.1.0",
|
|
32
|
+
"cpy-cli": "^5.0.0",
|
|
33
|
+
"rimraf": "5.0.1",
|
|
34
|
+
"typescript": "5.1.6",
|
|
35
|
+
"vite": "^4.4.4",
|
|
36
|
+
"vite-plugin-dts": "^3.3.0",
|
|
37
|
+
"vitest": "^0.33.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"oidc",
|
|
41
|
+
"OpenID Connect",
|
|
42
|
+
"openid",
|
|
43
|
+
"oauth2",
|
|
44
|
+
"oauth",
|
|
45
|
+
"vanilla"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"clean": "rimraf dist",
|
|
49
|
+
"copy-service-worker": "cpy ./node_modules/@axa-fr/oidc-client-service-worker/dist/OidcTrustedDomains.js ./node_modules/@axa-fr/oidc-client-service-worker/dist/OidcServiceWorker.js ./dist",
|
|
50
|
+
"build": "tsc && vite build",
|
|
51
|
+
"test": "vitest --root . --coverage",
|
|
52
|
+
"prepare": "pnpm run clean && pnpm run copy-service-worker && pnpm run build",
|
|
53
|
+
"postinstall": "node ./bin/post-install.mjs"
|
|
54
|
+
},
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public",
|
|
58
|
+
"registry": "https://registry.npmjs.org/"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const fetchFromIssuerCache = {};
|
|
2
|
+
|
|
3
|
+
export const getFromCache = (localStorageKey, storage = window.sessionStorage, timeCacheSecond) => {
|
|
4
|
+
if (!fetchFromIssuerCache[localStorageKey]) {
|
|
5
|
+
if (storage) {
|
|
6
|
+
const cacheJson = storage.getItem(localStorageKey);
|
|
7
|
+
if (cacheJson) {
|
|
8
|
+
fetchFromIssuerCache[localStorageKey] = JSON.parse(cacheJson);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const oneHourMinisecond = 1000 * timeCacheSecond;
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
if (fetchFromIssuerCache[localStorageKey] && (fetchFromIssuerCache[localStorageKey].timestamp + oneHourMinisecond) > Date.now()) {
|
|
15
|
+
return fetchFromIssuerCache[localStorageKey].result;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const setCache = (localStorageKey, result, storage = window.sessionStorage) => {
|
|
21
|
+
const timestamp = Date.now();
|
|
22
|
+
fetchFromIssuerCache[localStorageKey] = { result, timestamp };
|
|
23
|
+
if (storage) {
|
|
24
|
+
storage.setItem(localStorageKey, JSON.stringify({ result, timestamp }));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CheckSessionIFrame } from './checkSessionIFrame.js';
|
|
2
|
+
import { _silentLoginAsync, SilentLoginResponse } from './silentLogin.js';
|
|
3
|
+
import { OidcConfiguration } from './types.js';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
6
|
+
export const startCheckSessionAsync = (oidc:any, oidcDatabase:any, configuration :OidcConfiguration) => (checkSessionIFrameUri, clientId, sessionState, isSilentSignin = false) => {
|
|
7
|
+
const silentLoginAsync = (extras, state = undefined, scope = undefined):Promise<SilentLoginResponse> => {
|
|
8
|
+
return _silentLoginAsync(oidc.configurationName, configuration, oidc.publishEvent.bind(oidc))(extras, state, scope);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return new Promise<CheckSessionIFrame>((resolve, reject): void => {
|
|
12
|
+
if (configuration.silent_login_uri && configuration.silent_redirect_uri && configuration.monitor_session && checkSessionIFrameUri && sessionState && !isSilentSignin) {
|
|
13
|
+
const checkSessionCallback = () => {
|
|
14
|
+
oidc.checkSessionIFrame.stop();
|
|
15
|
+
const tokens = oidc.tokens;
|
|
16
|
+
if (tokens === null) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const idToken = tokens.idToken;
|
|
20
|
+
const idTokenPayload = tokens.idTokenPayload;
|
|
21
|
+
return silentLoginAsync({
|
|
22
|
+
prompt: 'none',
|
|
23
|
+
id_token_hint: idToken,
|
|
24
|
+
scope: configuration.scope || 'openid',
|
|
25
|
+
}).then((silentSigninResponse) => {
|
|
26
|
+
const iFrameIdTokenPayload = silentSigninResponse.tokens.idTokenPayload;
|
|
27
|
+
if (idTokenPayload.sub === iFrameIdTokenPayload.sub) {
|
|
28
|
+
const sessionState = silentSigninResponse.sessionState;
|
|
29
|
+
oidc.checkSessionIFrame.start(silentSigninResponse.sessionState);
|
|
30
|
+
if (idTokenPayload.sid === iFrameIdTokenPayload.sid) {
|
|
31
|
+
console.debug('SessionMonitor._callback: Same sub still logged in at OP, restarting check session iframe; session_state:', sessionState);
|
|
32
|
+
} else {
|
|
33
|
+
console.debug('SessionMonitor._callback: Same sub still logged in at OP, session state has changed, restarting check session iframe; session_state:', sessionState);
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
console.debug('SessionMonitor._callback: Different subject signed into OP:', iFrameIdTokenPayload.sub);
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
+
}).catch(async (e) => {
|
|
40
|
+
console.warn('SessionMonitor._callback: Silent login failed, logging out other tabs:', e);
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
42
|
+
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
await oidc.logoutOtherTabAsync(configuration.client_id, idTokenPayload.sub);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
oidc.checkSessionIFrame = new CheckSessionIFrame(checkSessionCallback, clientId, checkSessionIFrameUri);
|
|
50
|
+
oidc.checkSessionIFrame.load().then(() => {
|
|
51
|
+
oidc.checkSessionIFrame.start(sessionState);
|
|
52
|
+
resolve(oidc.checkSessionIFrame);
|
|
53
|
+
}).catch((e) => {
|
|
54
|
+
reject(e);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
resolve(null);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const DefaultInterval = 2000;
|
|
2
|
+
|
|
3
|
+
const Log = console;
|
|
4
|
+
|
|
5
|
+
export class CheckSessionIFrame {
|
|
6
|
+
private readonly _client_id: any;
|
|
7
|
+
private readonly _callback: any;
|
|
8
|
+
private _url: any;
|
|
9
|
+
private readonly _interval: number;
|
|
10
|
+
private readonly _stopOnError: boolean;
|
|
11
|
+
private readonly _frame_origin: string;
|
|
12
|
+
private readonly _frame: HTMLIFrameElement;
|
|
13
|
+
private _boundMessageEvent: any;
|
|
14
|
+
private _timer: number;
|
|
15
|
+
constructor(callback, client_id, url, interval = DefaultInterval, stopOnError = true) {
|
|
16
|
+
this._callback = callback;
|
|
17
|
+
this._client_id = client_id;
|
|
18
|
+
this._url = url;
|
|
19
|
+
this._interval = interval || DefaultInterval;
|
|
20
|
+
this._stopOnError = stopOnError;
|
|
21
|
+
const idx = url.indexOf('/', url.indexOf('//') + 2);
|
|
22
|
+
this._frame_origin = url.substr(0, idx);
|
|
23
|
+
this._frame = window.document.createElement('iframe');
|
|
24
|
+
this._frame.style.visibility = 'hidden';
|
|
25
|
+
this._frame.style.position = 'absolute';
|
|
26
|
+
this._frame.style.display = 'none';
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
this._frame.width = 0;
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
this._frame.height = 0;
|
|
31
|
+
|
|
32
|
+
this._frame.src = url;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
load() {
|
|
36
|
+
return new Promise<void>((resolve) => {
|
|
37
|
+
this._frame.onload = () => {
|
|
38
|
+
resolve();
|
|
39
|
+
};
|
|
40
|
+
window.document.body.appendChild(this._frame);
|
|
41
|
+
this._boundMessageEvent = this._message.bind(this);
|
|
42
|
+
window.addEventListener('message', this._boundMessageEvent, false);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_message(e) {
|
|
47
|
+
if (e.origin === this._frame_origin &&
|
|
48
|
+
e.source === this._frame.contentWindow
|
|
49
|
+
) {
|
|
50
|
+
if (e.data === 'error') {
|
|
51
|
+
Log.error('CheckSessionIFrame: error message from check session op iframe');
|
|
52
|
+
if (this._stopOnError) {
|
|
53
|
+
this.stop();
|
|
54
|
+
}
|
|
55
|
+
} else if (e.data === 'changed') {
|
|
56
|
+
Log.debug(e);
|
|
57
|
+
Log.debug('CheckSessionIFrame: changed message from check session op iframe');
|
|
58
|
+
this.stop();
|
|
59
|
+
this._callback();
|
|
60
|
+
} else {
|
|
61
|
+
Log.debug('CheckSessionIFrame: ' + e.data + ' message from check session op iframe');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
start(session_state) {
|
|
67
|
+
Log.debug('CheckSessionIFrame.start :' + session_state);
|
|
68
|
+
this.stop();
|
|
69
|
+
const send = () => {
|
|
70
|
+
this._frame.contentWindow.postMessage(this._client_id + ' ' + session_state, this._frame_origin);
|
|
71
|
+
};
|
|
72
|
+
send();
|
|
73
|
+
this._timer = window.setInterval(send, this._interval);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
stop() {
|
|
77
|
+
if (this._timer) {
|
|
78
|
+
Log.debug('CheckSessionIFrame.stop');
|
|
79
|
+
window.clearInterval(this._timer);
|
|
80
|
+
this._timer = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/crypto.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as base64 from 'base64-js';
|
|
2
|
+
|
|
3
|
+
const cryptoInfo = () => {
|
|
4
|
+
const hasCrypto = typeof window !== 'undefined' && !!(window.crypto as any);
|
|
5
|
+
const hasSubtleCrypto = hasCrypto && !!(window.crypto.subtle as any);
|
|
6
|
+
return { hasCrypto, hasSubtleCrypto };
|
|
7
|
+
};
|
|
8
|
+
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
9
|
+
|
|
10
|
+
const bufferToString = (buffer: Uint8Array) => {
|
|
11
|
+
const state = [];
|
|
12
|
+
for (let i = 0; i < buffer.byteLength; i += 1) {
|
|
13
|
+
const index = buffer[i] % charset.length;
|
|
14
|
+
state.push(charset[index]);
|
|
15
|
+
}
|
|
16
|
+
return state.join('');
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const urlSafe = (buffer: Uint8Array): string => {
|
|
20
|
+
const encoded = base64.fromByteArray(new Uint8Array(buffer));
|
|
21
|
+
return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const generateRandom = (size: number) => {
|
|
25
|
+
const buffer = new Uint8Array(size);
|
|
26
|
+
const { hasCrypto } = cryptoInfo();
|
|
27
|
+
if (hasCrypto) {
|
|
28
|
+
window.crypto.getRandomValues(buffer);
|
|
29
|
+
} else {
|
|
30
|
+
// fall back to Math.random() if nothing else is available
|
|
31
|
+
for (let i = 0; i < size; i += 1) {
|
|
32
|
+
buffer[i] = (Math.random() * charset.length) | 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return bufferToString(buffer);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function textEncodeLite(str: string) {
|
|
39
|
+
const buf = new ArrayBuffer(str.length);
|
|
40
|
+
const bufView = new Uint8Array(buf);
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < str.length; i++) {
|
|
43
|
+
bufView[i] = str.charCodeAt(i);
|
|
44
|
+
}
|
|
45
|
+
return bufView;
|
|
46
|
+
}
|
|
47
|
+
export const deriveChallengeAsync = (code: string): Promise<string> => {
|
|
48
|
+
if (code.length < 43 || code.length > 128) {
|
|
49
|
+
return Promise.reject(new Error('Invalid code length.'));
|
|
50
|
+
}
|
|
51
|
+
const { hasSubtleCrypto } = cryptoInfo();
|
|
52
|
+
if (!hasSubtleCrypto) {
|
|
53
|
+
return Promise.reject(new Error('window.crypto.subtle is unavailable.'));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
crypto.subtle.digest('SHA-256', textEncodeLite(code)).then(buffer => {
|
|
58
|
+
return resolve(urlSafe(new Uint8Array(buffer)));
|
|
59
|
+
}, error => reject(error));
|
|
60
|
+
});
|
|
61
|
+
};
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const eventNames = {
|
|
2
|
+
service_worker_not_supported_by_browser: 'service_worker_not_supported_by_browser',
|
|
3
|
+
token_aquired: 'token_aquired',
|
|
4
|
+
logout_from_another_tab: 'logout_from_another_tab',
|
|
5
|
+
logout_from_same_tab: 'logout_from_same_tab',
|
|
6
|
+
token_renewed: 'token_renewed',
|
|
7
|
+
token_timer: 'token_timer',
|
|
8
|
+
loginAsync_begin: 'loginAsync_begin',
|
|
9
|
+
loginAsync_error: 'loginAsync_error',
|
|
10
|
+
loginCallbackAsync_begin: 'loginCallbackAsync_begin',
|
|
11
|
+
loginCallbackAsync_end: 'loginCallbackAsync_end',
|
|
12
|
+
loginCallbackAsync_error: 'loginCallbackAsync_error',
|
|
13
|
+
refreshTokensAsync_begin: 'refreshTokensAsync_begin',
|
|
14
|
+
refreshTokensAsync: 'refreshTokensAsync',
|
|
15
|
+
refreshTokensAsync_end: 'refreshTokensAsync_end',
|
|
16
|
+
refreshTokensAsync_error: 'refreshTokensAsync_error',
|
|
17
|
+
refreshTokensAsync_silent_error: 'refreshTokensAsync_silent_error',
|
|
18
|
+
tryKeepExistingSessionAsync_begin: 'tryKeepExistingSessionAsync_begin',
|
|
19
|
+
tryKeepExistingSessionAsync_end: 'tryKeepExistingSessionAsync_end',
|
|
20
|
+
tryKeepExistingSessionAsync_error: 'tryKeepExistingSessionAsync_error',
|
|
21
|
+
silentLoginAsync_begin: 'silentLoginAsync_begin',
|
|
22
|
+
silentLoginAsync: 'silentLoginAsync',
|
|
23
|
+
silentLoginAsync_end: 'silentLoginAsync_end',
|
|
24
|
+
silentLoginAsync_error: 'silentLoginAsync_error',
|
|
25
|
+
syncTokensAsync_begin: 'syncTokensAsync_begin',
|
|
26
|
+
syncTokensAsync_end: 'syncTokensAsync_end',
|
|
27
|
+
syncTokensAsync_error: 'syncTokensAsync_error',
|
|
28
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { getFetchDefault } from './oidc.js';
|
|
2
|
+
export { TokenRenewMode } from './parseTokens.js';
|
|
3
|
+
export { getParseQueryStringFromLocation, getPath } from './route-utils';
|
|
4
|
+
export type {
|
|
5
|
+
AuthorityConfiguration,
|
|
6
|
+
Fetch,
|
|
7
|
+
OidcConfiguration,
|
|
8
|
+
StringMap,
|
|
9
|
+
} from './types.js';
|
|
10
|
+
export { type OidcUserInfo, VanillaOidc } from './vanillaOidc.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect,it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { excludeOs, getOperatingSystem } from './initWorker';
|
|
4
|
+
|
|
5
|
+
describe('initWorker test Suite', () => {
|
|
6
|
+
|
|
7
|
+
it.each([['Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1', 'iOS', '12.1.0'],
|
|
8
|
+
['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1', 'Mac OS X', '10_15_6'],
|
|
9
|
+
])(
|
|
10
|
+
'getOperatingSystem should return OS for Version',
|
|
11
|
+
(userAgent, expectedOs, expectedVersion) => {
|
|
12
|
+
const operatingSystem = getOperatingSystem({ userAgent, appVersion: 'OS ' + expectedVersion.replaceAll('.', '_') });
|
|
13
|
+
expect(expectedOs).toBe(operatingSystem.os);
|
|
14
|
+
expect(expectedVersion).toBe(operatingSystem.osVersion);
|
|
15
|
+
|
|
16
|
+
const isExcluded = excludeOs(operatingSystem);
|
|
17
|
+
expect(isExcluded).toBe(true);
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const initSession = (configurationName, storage = sessionStorage) => {
|
|
2
|
+
const clearAsync = (status) => {
|
|
3
|
+
storage[`oidc.${configurationName}`] = JSON.stringify({ tokens: null, status });
|
|
4
|
+
return Promise.resolve();
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const initAsync = async () => {
|
|
8
|
+
if (!storage[`oidc.${configurationName}`]) {
|
|
9
|
+
storage[`oidc.${configurationName}`] = JSON.stringify({ tokens: null, status: null });
|
|
10
|
+
return { tokens: null, status: null };
|
|
11
|
+
}
|
|
12
|
+
const data = JSON.parse(storage[`oidc.${configurationName}`]);
|
|
13
|
+
return Promise.resolve({ tokens: data.tokens, status: data.status });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const setTokens = (tokens) => {
|
|
17
|
+
storage[`oidc.${configurationName}`] = JSON.stringify({ tokens });
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const setSessionStateAsync = async (sessionState) => {
|
|
21
|
+
storage[`oidc.session_state.${configurationName}`] = sessionState;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getSessionStateAsync = async () => {
|
|
25
|
+
return storage[`oidc.session_state.${configurationName}`];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const setNonceAsync = (nonce) => {
|
|
29
|
+
localStorage[`oidc.nonce.${configurationName}`] = nonce.nonce;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getNonceAsync = async () => {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
return { nonce: localStorage[`oidc.nonce.${configurationName}`] };
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const getTokens = () => {
|
|
38
|
+
if (!storage[`oidc.${configurationName}`]) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return JSON.stringify({ tokens: JSON.parse(storage[`oidc.${configurationName}`]).tokens });
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
let getLoginParamsCache = null;
|
|
45
|
+
const setLoginParams = (configurationName:string, data) => {
|
|
46
|
+
getLoginParamsCache = data;
|
|
47
|
+
storage[`oidc.login.${configurationName}`] = JSON.stringify(data);
|
|
48
|
+
};
|
|
49
|
+
const getLoginParams = (configurationName) => {
|
|
50
|
+
const dataString = storage[`oidc.login.${configurationName}`];
|
|
51
|
+
if (!getLoginParamsCache) {
|
|
52
|
+
getLoginParamsCache = JSON.parse(dataString);
|
|
53
|
+
}
|
|
54
|
+
return getLoginParamsCache;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const getStateAsync = async () => {
|
|
58
|
+
return storage[`oidc.state.${configurationName}`];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const setStateAsync = async (state:string) => {
|
|
62
|
+
storage[`oidc.state.${configurationName}`] = state;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getCodeVerifierAsync = async () => {
|
|
66
|
+
return storage[`oidc.code_verifier.${configurationName}`];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const setCodeVerifierAsync = async (codeVerifier) => {
|
|
70
|
+
storage[`oidc.code_verifier.${configurationName}`] = codeVerifier;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
clearAsync,
|
|
75
|
+
initAsync,
|
|
76
|
+
setTokens,
|
|
77
|
+
getTokens,
|
|
78
|
+
setSessionStateAsync,
|
|
79
|
+
getSessionStateAsync,
|
|
80
|
+
setNonceAsync,
|
|
81
|
+
getNonceAsync,
|
|
82
|
+
setLoginParams,
|
|
83
|
+
getLoginParams,
|
|
84
|
+
getStateAsync,
|
|
85
|
+
setStateAsync,
|
|
86
|
+
getCodeVerifierAsync,
|
|
87
|
+
setCodeVerifierAsync,
|
|
88
|
+
};
|
|
89
|
+
};
|