@axa-fr/react-oidc 6.13.3 → 6.14.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.
- package/README.md +1 -0
- package/dist/OidcServiceWorker.js +36 -8
- package/dist/vanilla/crypto.d.ts +4 -0
- package/dist/vanilla/crypto.d.ts.map +1 -0
- package/dist/vanilla/crypto.js +81 -0
- package/dist/vanilla/crypto.js.map +1 -0
- package/dist/vanilla/initSession.d.ts +6 -4
- package/dist/vanilla/initSession.d.ts.map +1 -1
- package/dist/vanilla/initSession.js +22 -15
- package/dist/vanilla/initSession.js.map +1 -1
- package/dist/vanilla/initWorker.d.ts +4 -2
- package/dist/vanilla/initWorker.d.ts.map +1 -1
- package/dist/vanilla/initWorker.js +39 -18
- package/dist/vanilla/initWorker.js.map +1 -1
- package/dist/vanilla/login.d.ts +5 -1
- package/dist/vanilla/login.d.ts.map +1 -1
- package/dist/vanilla/login.js +70 -143
- package/dist/vanilla/login.js.map +1 -1
- package/dist/vanilla/oidc.d.ts +10 -6
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +14 -7
- package/dist/vanilla/oidc.js.map +1 -1
- package/dist/vanilla/requests.d.ts +14 -0
- package/dist/vanilla/requests.d.ts.map +1 -1
- package/dist/vanilla/requests.js +56 -1
- package/dist/vanilla/requests.js.map +1 -1
- package/dist/vanilla/route-utils.js +2 -2
- package/dist/vanilla/route-utils.js.map +1 -1
- package/dist/vanilla/types.d.ts +1 -0
- package/dist/vanilla/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/oidc/vanilla/OidcServiceWorker.js +36 -8
- package/src/oidc/vanilla/crypto.ts +57 -0
- package/src/oidc/vanilla/initSession.ts +25 -15
- package/src/oidc/vanilla/initWorker.ts +43 -18
- package/src/oidc/vanilla/login.ts +76 -148
- package/src/oidc/vanilla/oidc.ts +22 -13
- package/src/oidc/vanilla/requests.spec.ts +4 -0
- package/src/oidc/vanilla/requests.ts +55 -0
- package/src/oidc/vanilla/route-utils.ts +2 -2
- package/src/oidc/vanilla/types.ts +1 -0
- package/dist/vanilla/memoryStorageBackend.d.ts +0 -11
- package/dist/vanilla/memoryStorageBackend.d.ts.map +0 -1
- package/dist/vanilla/memoryStorageBackend.js +0 -31
- package/dist/vanilla/memoryStorageBackend.js.map +0 -1
- package/dist/vanilla/noHashQueryStringUtils.d.ts +0 -8
- package/dist/vanilla/noHashQueryStringUtils.d.ts.map +0 -1
- package/dist/vanilla/noHashQueryStringUtils.js +0 -32
- package/dist/vanilla/noHashQueryStringUtils.js.map +0 -1
- package/src/oidc/vanilla/memoryStorageBackend.ts +0 -40
- package/src/oidc/vanilla/noHashQueryStringUtils.ts +0 -32
|
@@ -1,29 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AuthorizationNotifier,
|
|
3
|
-
AuthorizationRequest, BaseTokenRequestHandler,
|
|
4
|
-
DefaultCrypto, FetchRequestor, GRANT_TYPE_AUTHORIZATION_CODE,
|
|
5
|
-
RedirectRequestHandler,
|
|
6
|
-
TokenRequest,
|
|
7
|
-
} from '@openid/appauth';
|
|
8
|
-
|
|
1
|
+
import { generateRandom } from './crypto';
|
|
9
2
|
import { eventNames } from './events';
|
|
10
3
|
import { initSession } from './initSession';
|
|
11
4
|
import { initWorkerAsync } from './initWorker';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { isTokensOidcValid, setTokens } from './parseTokens';
|
|
5
|
+
import { isTokensOidcValid } from './parseTokens';
|
|
6
|
+
import { performAuthorizationRequestAsync, performFirstTokenRequestAsync } from './requests';
|
|
15
7
|
import { getParseQueryStringFromLocation } from './route-utils';
|
|
16
8
|
import { OidcConfiguration, StringMap } from './types';
|
|
17
9
|
|
|
18
|
-
const randomString = function(length) {
|
|
19
|
-
let text = '';
|
|
20
|
-
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
21
|
-
for (let i = 0; i < length; i++) {
|
|
22
|
-
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
23
|
-
}
|
|
24
|
-
return text;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
10
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
28
11
|
export const defaultLoginAsync = (window, configurationName, configuration:OidcConfiguration, publishEvent :(string, any)=>void, initAsync:Function) => (callbackPath:string = undefined, extras:StringMap = null, isSilentSignin = false, scope:string = undefined) => {
|
|
29
12
|
const originExtras = extras;
|
|
@@ -31,10 +14,9 @@ export const defaultLoginAsync = (window, configurationName, configuration:OidcC
|
|
|
31
14
|
const loginLocalAsync = async () => {
|
|
32
15
|
const location = window.location;
|
|
33
16
|
const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
state =
|
|
37
|
-
delete extras.state;
|
|
17
|
+
|
|
18
|
+
if (!('state' in extras)) {
|
|
19
|
+
extras.state = generateRandom(16);
|
|
38
20
|
}
|
|
39
21
|
|
|
40
22
|
publishEvent(eventNames.loginAsync_begin, {});
|
|
@@ -53,38 +35,34 @@ export const defaultLoginAsync = (window, configurationName, configuration:OidcC
|
|
|
53
35
|
|
|
54
36
|
const extraFinal = !configuration.extras ? extras : { ...configuration.extras, ...extras };
|
|
55
37
|
if (!extraFinal.nonce) {
|
|
56
|
-
extraFinal.nonce =
|
|
38
|
+
extraFinal.nonce = generateRandom(12);
|
|
57
39
|
}
|
|
58
40
|
const nonce = { nonce: extraFinal.nonce };
|
|
59
41
|
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
|
|
60
42
|
const oidcServerConfiguration = await initAsync(configuration.authority, configuration.authority_configuration);
|
|
61
43
|
let storage;
|
|
62
44
|
if (serviceWorker) {
|
|
63
|
-
serviceWorker.setLoginParams(configurationName, { callbackPath: url, extras: originExtras
|
|
45
|
+
serviceWorker.setLoginParams(configurationName, { callbackPath: url, extras: originExtras });
|
|
64
46
|
serviceWorker.startKeepAliveServiceWorker();
|
|
65
47
|
await serviceWorker.initAsync(oidcServerConfiguration, 'loginAsync', configuration);
|
|
66
48
|
await serviceWorker.setNonceAsync(nonce);
|
|
67
|
-
storage =
|
|
68
|
-
await storage.setItem('dummy', {});
|
|
49
|
+
storage = serviceWorker;
|
|
69
50
|
} else {
|
|
70
51
|
const session = initSession(configurationName, configuration.storage ?? sessionStorage);
|
|
71
|
-
session.setLoginParams(configurationName, { callbackPath: url, extras: originExtras
|
|
52
|
+
session.setLoginParams(configurationName, { callbackPath: url, extras: originExtras });
|
|
72
53
|
await session.setNonceAsync(nonce);
|
|
73
|
-
storage =
|
|
54
|
+
storage = session;
|
|
74
55
|
}
|
|
75
56
|
|
|
76
57
|
// @ts-ignore
|
|
77
|
-
const
|
|
78
|
-
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
|
|
79
|
-
const authRequest = new AuthorizationRequest({
|
|
58
|
+
const extraInternal = {
|
|
80
59
|
client_id: configuration.client_id,
|
|
81
60
|
redirect_uri: redirectUri,
|
|
82
61
|
scope,
|
|
83
|
-
response_type:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
|
|
62
|
+
response_type: 'code',
|
|
63
|
+
...extraFinal,
|
|
64
|
+
};
|
|
65
|
+
await performAuthorizationRequestAsync(storage)(oidcServerConfiguration.authorizationEndpoint, extraInternal);
|
|
88
66
|
} catch (exception) {
|
|
89
67
|
publishEvent(eventNames.loginAsync_error, exception);
|
|
90
68
|
throw exception;
|
|
@@ -105,134 +83,84 @@ export const loginCallbackAsync = (oidc) => async (isSilentSignin = false) => {
|
|
|
105
83
|
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
106
84
|
const sessionState = queryParams.session_state;
|
|
107
85
|
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, oidc.configurationName);
|
|
108
|
-
let storage
|
|
109
|
-
let nonceData
|
|
110
|
-
let getLoginParams
|
|
86
|
+
let storage;
|
|
87
|
+
let nonceData;
|
|
88
|
+
let getLoginParams;
|
|
89
|
+
let state;
|
|
111
90
|
if (serviceWorker) {
|
|
112
91
|
serviceWorker.startKeepAliveServiceWorker();
|
|
113
92
|
await serviceWorker.initAsync(oidcServerConfiguration, 'loginCallbackAsync', configuration);
|
|
114
|
-
const items = await serviceWorker.loadItemsAsync();
|
|
115
|
-
storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, items);
|
|
116
|
-
const dummy = await storage.getItem('dummy');
|
|
117
|
-
if (!dummy) {
|
|
118
|
-
throw new Error('Service Worker storage disapear');
|
|
119
|
-
}
|
|
120
|
-
await storage.removeItem('dummy');
|
|
121
93
|
await serviceWorker.setSessionStateAsync(sessionState);
|
|
122
94
|
nonceData = await serviceWorker.getNonceAsync();
|
|
123
95
|
getLoginParams = serviceWorker.getLoginParams(oidc.configurationName);
|
|
96
|
+
state = await serviceWorker.getStateAsync();
|
|
97
|
+
storage = serviceWorker;
|
|
124
98
|
} else {
|
|
125
99
|
const session = initSession(oidc.configurationName, configuration.storage ?? sessionStorage);
|
|
126
|
-
session.
|
|
127
|
-
const items = await session.loadItemsAsync();
|
|
128
|
-
storage = new MemoryStorageBackend(session.saveItemsAsync, items);
|
|
100
|
+
await session.setSessionStateAsync(sessionState);
|
|
129
101
|
nonceData = await session.getNonceAsync();
|
|
130
102
|
getLoginParams = session.getLoginParams(oidc.configurationName);
|
|
103
|
+
state = await session.getStateAsync();
|
|
104
|
+
storage = session;
|
|
131
105
|
}
|
|
132
106
|
|
|
133
|
-
|
|
134
|
-
let queryStringUtil = new NoHashQueryStringUtils();
|
|
135
|
-
if (redirectUri.includes('#')) {
|
|
136
|
-
const splithash = window.location.href.split('#');
|
|
137
|
-
if (splithash.length === 2 && splithash[1].includes('?')) {
|
|
138
|
-
queryStringUtil = new HashQueryStringUtils();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
|
|
142
|
-
const notifier = new AuthorizationNotifier();
|
|
143
|
-
authorizationHandler.setAuthorizationNotifier(notifier);
|
|
107
|
+
const params = getParseQueryStringFromLocation(window.location.toString());
|
|
144
108
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
109
|
+
if (params.iss && params.iss !== oidcServerConfiguration.issuer) {
|
|
110
|
+
throw new Error('issuer not valid');
|
|
111
|
+
}
|
|
112
|
+
if (params.state && params.state !== state) {
|
|
113
|
+
throw new Error('state not valid');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const data = {
|
|
117
|
+
code: params.code,
|
|
118
|
+
grant_type: 'authorization_code',
|
|
119
|
+
client_id: configuration.client_id,
|
|
120
|
+
redirect_uri: redirectUri,
|
|
121
|
+
};
|
|
154
122
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (key.endsWith(':token_request')) {
|
|
167
|
-
extras[key.replace(':token_request', '')] = value;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
123
|
+
const extras = {};
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
if (configuration.token_request_extras) {
|
|
126
|
+
for (const [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
127
|
+
extras[key] = value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (getLoginParams && getLoginParams.extras) {
|
|
131
|
+
for (const [key, value] of Object.entries(getLoginParams.extras)) {
|
|
132
|
+
if (key.endsWith(':token_request')) {
|
|
133
|
+
extras[key.replace(':token_request', '')] = value;
|
|
171
134
|
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
172
137
|
|
|
173
|
-
|
|
174
|
-
client_id: clientId,
|
|
175
|
-
redirect_uri: redirectUri, // @ts-ignore
|
|
176
|
-
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
|
|
177
|
-
code: response.code,
|
|
178
|
-
refresh_token: undefined,
|
|
179
|
-
extras,
|
|
180
|
-
});
|
|
138
|
+
const tokenResponse = await performFirstTokenRequestAsync(storage)(oidcServerConfiguration.tokenEndpoint, { ...data, ...extras }, oidc.configuration.token_renew_mode, tokenRequestTimeout);
|
|
181
139
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
} else {
|
|
199
|
-
const session = initSession(oidc.configurationName, configuration.storage);
|
|
200
|
-
loginParams = session.getLoginParams(oidc.configurationName);
|
|
201
|
-
formattedTokens = setTokens(tokenResponse, null, configuration.token_renew_mode);
|
|
202
|
-
}
|
|
203
|
-
if (!isTokensOidcValid(formattedTokens, nonceData.nonce, oidcServerConfiguration)) {
|
|
204
|
-
const exception = new Error('Tokens are not OpenID valid');
|
|
205
|
-
if (timeoutId) {
|
|
206
|
-
clearTimeout(timeoutId);
|
|
207
|
-
oidc.timeoutId = null;
|
|
208
|
-
oidc.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
|
209
|
-
console.error(exception);
|
|
210
|
-
reject(exception);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
140
|
+
let loginParams = null;
|
|
141
|
+
const formattedTokens = tokenResponse.data.tokens;
|
|
142
|
+
if (serviceWorker) {
|
|
143
|
+
await serviceWorker.initAsync(redirectUri, 'syncTokensAsync', configuration);
|
|
144
|
+
loginParams = serviceWorker.getLoginParams(oidc.configurationName);
|
|
145
|
+
} else {
|
|
146
|
+
const session = initSession(oidc.configurationName, configuration.storage);
|
|
147
|
+
loginParams = session.getLoginParams(oidc.configurationName);
|
|
148
|
+
}
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
if (tokenResponse.data.state !== extras.state) {
|
|
151
|
+
throw new Error('state is not valid');
|
|
152
|
+
}
|
|
153
|
+
if (!isTokensOidcValid(formattedTokens, nonceData.nonce, oidcServerConfiguration)) {
|
|
154
|
+
throw new Error('Tokens are not OpenID valid');
|
|
155
|
+
}
|
|
213
156
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
} catch (exception) {
|
|
225
|
-
if (timeoutId) {
|
|
226
|
-
clearTimeout(timeoutId);
|
|
227
|
-
oidc.timeoutId = null;
|
|
228
|
-
oidc.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
|
229
|
-
console.error(exception);
|
|
230
|
-
reject(exception);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
authorizationHandler.completeAuthorizationRequestIfPossible();
|
|
235
|
-
});
|
|
157
|
+
await oidc.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin);
|
|
158
|
+
oidc.publishEvent(eventNames.loginCallbackAsync_end, {});
|
|
159
|
+
return {
|
|
160
|
+
tokens: formattedTokens,
|
|
161
|
+
state: 'request.state',
|
|
162
|
+
callbackPath: loginParams.callbackPath,
|
|
163
|
+
};
|
|
236
164
|
} catch (exception) {
|
|
237
165
|
console.error(exception);
|
|
238
166
|
oidc.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
package/src/oidc/vanilla/oidc.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AuthorizationServiceConfiguration,
|
|
3
|
-
GRANT_TYPE_REFRESH_TOKEN,
|
|
4
|
-
} from '@openid/appauth';
|
|
5
|
-
import { AuthorizationServiceConfigurationJson } from '@openid/appauth/src/authorization_service_configuration';
|
|
6
1
|
|
|
7
2
|
import { startCheckSessionAsync as defaultStartCheckSessionAsync } from './checkSession';
|
|
8
3
|
import { CheckSessionIFrame } from './checkSessionIFrame';
|
|
@@ -24,23 +19,28 @@ import timer from './timer';
|
|
|
24
19
|
import { AuthorityConfiguration, OidcConfiguration, StringMap } from './types';
|
|
25
20
|
import { userInfoAsync } from './user';
|
|
26
21
|
|
|
27
|
-
export interface OidcAuthorizationServiceConfigurationJson
|
|
22
|
+
export interface OidcAuthorizationServiceConfigurationJson {
|
|
28
23
|
check_session_iframe?: string;
|
|
29
24
|
issuer:string;
|
|
30
25
|
}
|
|
31
26
|
|
|
32
|
-
export class OidcAuthorizationServiceConfiguration
|
|
33
|
-
private
|
|
27
|
+
export class OidcAuthorizationServiceConfiguration {
|
|
28
|
+
private checkSessionIframe: string;
|
|
34
29
|
private issuer: string;
|
|
30
|
+
private authorizationEndpoint: string;
|
|
31
|
+
private tokenEndpoint: string;
|
|
32
|
+
private revocationEndpoint: string;
|
|
33
|
+
private userInfoEndpoint: string;
|
|
34
|
+
private endSessionEndpoint: string;
|
|
35
35
|
|
|
36
36
|
constructor(request: any) {
|
|
37
|
-
super(request);
|
|
38
37
|
this.authorizationEndpoint = request.authorization_endpoint;
|
|
39
38
|
this.tokenEndpoint = request.token_endpoint;
|
|
40
39
|
this.revocationEndpoint = request.revocation_endpoint;
|
|
41
40
|
this.userInfoEndpoint = request.userinfo_endpoint;
|
|
42
|
-
this.
|
|
41
|
+
this.checkSessionIframe = request.check_session_iframe;
|
|
43
42
|
this.issuer = request.issuer;
|
|
43
|
+
this.endSessionEndpoint = request.end_session_endpoint;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -246,7 +246,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
246
246
|
const getLoginParams = session.getLoginParams(this.configurationName);
|
|
247
247
|
// @ts-ignore
|
|
248
248
|
this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt, getLoginParams.extras);
|
|
249
|
-
const sessionState = session.
|
|
249
|
+
const sessionState = await session.getSessionStateAsync();
|
|
250
250
|
// @ts-ignore
|
|
251
251
|
await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
|
|
252
252
|
this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
|
|
@@ -440,7 +440,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
440
440
|
const details = {
|
|
441
441
|
client_id: clientId,
|
|
442
442
|
redirect_uri: redirectUri,
|
|
443
|
-
grant_type:
|
|
443
|
+
grant_type: 'refresh_token',
|
|
444
444
|
refresh_token: tokens.refreshToken,
|
|
445
445
|
};
|
|
446
446
|
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
@@ -548,13 +548,22 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
548
548
|
});
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
renewTokensPromise:Promise<any> = null;
|
|
552
|
+
|
|
551
553
|
async renewTokensAsync (extras:StringMap = null) {
|
|
554
|
+
if (this.renewTokensPromise !== null) {
|
|
555
|
+
return this.renewTokensPromise;
|
|
556
|
+
}
|
|
552
557
|
if (!this.timeoutId) {
|
|
553
558
|
return;
|
|
554
559
|
}
|
|
555
560
|
timer.clearTimeout(this.timeoutId);
|
|
556
561
|
// @ts-ignore
|
|
557
|
-
|
|
562
|
+
this.renewTokensPromise = renewTokensAndStartTimerAsync(this, this.tokens.refreshToken, true, extras);
|
|
563
|
+
return this.renewTokensPromise.then(result => {
|
|
564
|
+
this.renewTokensPromise = null;
|
|
565
|
+
return result;
|
|
566
|
+
});
|
|
558
567
|
}
|
|
559
568
|
|
|
560
569
|
async destroyAsync(status) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getFromCache, setCache } from './cache';
|
|
2
|
+
import { deriveChallengeAsync, generateRandom } from './crypto';
|
|
2
3
|
import { OidcAuthorizationServiceConfiguration } from './oidc';
|
|
3
4
|
import { parseOriginalTokens } from './parseTokens';
|
|
5
|
+
import { StringMap } from './types';
|
|
4
6
|
|
|
5
7
|
const oneHourSecond = 60 * 60;
|
|
6
8
|
export const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage = window.sessionStorage):
|
|
@@ -112,3 +114,56 @@ export const performTokenRequestAsync = async (url, details, extras, oldTokens,
|
|
|
112
114
|
data: parseOriginalTokens(tokens, oldTokens, tokenRenewMode),
|
|
113
115
|
};
|
|
114
116
|
};
|
|
117
|
+
|
|
118
|
+
export const performAuthorizationRequestAsync = (storage: any) => async (url, extras: StringMap) => {
|
|
119
|
+
extras = extras ? { ...extras } : {};
|
|
120
|
+
const codeVerifier = generateRandom(128);
|
|
121
|
+
const codeChallenge = await deriveChallengeAsync(codeVerifier);
|
|
122
|
+
await storage.setCodeVerifierAsync(codeVerifier);
|
|
123
|
+
await storage.setStateAsync(extras.state);
|
|
124
|
+
extras.code_challenge = codeChallenge;
|
|
125
|
+
extras.code_challenge_method = 'S256';
|
|
126
|
+
let queryString = '';
|
|
127
|
+
if (extras) {
|
|
128
|
+
for (const [key, value] of Object.entries(extras)) {
|
|
129
|
+
if (queryString === '') {
|
|
130
|
+
queryString += '?';
|
|
131
|
+
} else {
|
|
132
|
+
queryString += '&';
|
|
133
|
+
}
|
|
134
|
+
queryString += `${key}=${encodeURIComponent(value)}`;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
window.location.href = `${url}${queryString}`;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const performFirstTokenRequestAsync = (storage:any) => async (url, extras, tokenRenewMode: string, timeoutMs = 10000) => {
|
|
141
|
+
extras = extras ? { ...extras } : {};
|
|
142
|
+
extras.code_verifier = await storage.getCodeVerifierAsync();
|
|
143
|
+
const formBody = [];
|
|
144
|
+
for (const property in extras) {
|
|
145
|
+
const encodedKey = encodeURIComponent(property);
|
|
146
|
+
const encodedValue = encodeURIComponent(extras[property]);
|
|
147
|
+
formBody.push(`${encodedKey}=${encodedValue}`);
|
|
148
|
+
}
|
|
149
|
+
const formBodyString = formBody.join('&');
|
|
150
|
+
const response = await internalFetch(url, {
|
|
151
|
+
method: 'POST',
|
|
152
|
+
headers: {
|
|
153
|
+
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
154
|
+
},
|
|
155
|
+
body: formBodyString,
|
|
156
|
+
}, timeoutMs);
|
|
157
|
+
await Promise.all([storage.setCodeVerifierAsync(null), storage.setStateAsync(null)]);
|
|
158
|
+
if (response.status !== 200) {
|
|
159
|
+
return { success: false, status: response.status };
|
|
160
|
+
}
|
|
161
|
+
const tokens = await response.json();
|
|
162
|
+
return {
|
|
163
|
+
success: true,
|
|
164
|
+
data: {
|
|
165
|
+
state: extras.state,
|
|
166
|
+
tokens: parseOriginalTokens(tokens, null, tokenRenewMode),
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
};
|
|
@@ -18,7 +18,7 @@ export const getLocation = (href: string) => {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
if (search) {
|
|
21
|
+
if (search.startsWith('?')) {
|
|
22
22
|
search = search.slice(1);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -72,7 +72,7 @@ const parseQueryString = (queryString:string) => {
|
|
|
72
72
|
// Convert the array of strings into an object
|
|
73
73
|
for (i = 0, l = queries.length; i < l; i++) {
|
|
74
74
|
temp = queries[i].split('=');
|
|
75
|
-
params[decodeURIComponent(temp[0])] = temp[1];
|
|
75
|
+
params[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
return params;
|
|
@@ -13,6 +13,7 @@ export type OidcConfiguration = {
|
|
|
13
13
|
token_request_timeout?: number;
|
|
14
14
|
service_worker_relative_url?:string;
|
|
15
15
|
service_worker_only?:boolean;
|
|
16
|
+
service_worker_convert_all_requests_to_cors?:boolean;
|
|
16
17
|
extras?:StringMap;
|
|
17
18
|
token_request_extras?:StringMap;
|
|
18
19
|
storage?: Storage;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare type ItemName = string | number;
|
|
2
|
-
export declare class MemoryStorageBackend {
|
|
3
|
-
items: any;
|
|
4
|
-
private saveItemsAsync;
|
|
5
|
-
constructor(saveItemsAsync: any, items?: {});
|
|
6
|
-
getItem(name: ItemName): Promise<any>;
|
|
7
|
-
removeItem(name: ItemName): Promise<any>;
|
|
8
|
-
clear(): Promise<any>;
|
|
9
|
-
setItem(name: ItemName, value: any): Promise<any>;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=memoryStorageBackend.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memoryStorageBackend.d.ts","sourceRoot":"","sources":["../../src/oidc/vanilla/memoryStorageBackend.ts"],"names":[],"mappings":"AAKA,oBAAY,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC,qBAAa,oBAAoB;IACtB,KAAK,EAAE,GAAG,CAAC;IAClB,OAAO,CAAC,cAAc,CAAc;gBAExB,cAAc,KAAA,EAAE,KAAK,KAAK;IAUtC,OAAO,CAAC,IAAI,EAAE,QAAQ;IAItB,UAAU,CAAC,IAAI,EAAE,QAAQ;IAKzB,KAAK;IAKL,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG;CAIrC"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MemoryStorageBackend = void 0;
|
|
4
|
-
class MemoryStorageBackend {
|
|
5
|
-
constructor(saveItemsAsync, items = {}) {
|
|
6
|
-
this.items = items;
|
|
7
|
-
this.saveItemsAsync = saveItemsAsync;
|
|
8
|
-
this.saveItemsAsync.bind(this);
|
|
9
|
-
this.getItem.bind(this);
|
|
10
|
-
this.removeItem.bind(this);
|
|
11
|
-
this.clear.bind(this);
|
|
12
|
-
this.setItem.bind(this);
|
|
13
|
-
}
|
|
14
|
-
getItem(name) {
|
|
15
|
-
return Promise.resolve(this.items[name]);
|
|
16
|
-
}
|
|
17
|
-
removeItem(name) {
|
|
18
|
-
delete this.items[name];
|
|
19
|
-
return this.saveItemsAsync(this.items);
|
|
20
|
-
}
|
|
21
|
-
clear() {
|
|
22
|
-
this.items = {};
|
|
23
|
-
return this.saveItemsAsync(this.items);
|
|
24
|
-
}
|
|
25
|
-
setItem(name, value) {
|
|
26
|
-
this.items[name] = value;
|
|
27
|
-
return this.saveItemsAsync(this.items);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.MemoryStorageBackend = MemoryStorageBackend;
|
|
31
|
-
//# sourceMappingURL=memoryStorageBackend.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memoryStorageBackend.js","sourceRoot":"","sources":["../../src/oidc/vanilla/memoryStorageBackend.ts"],"names":[],"mappings":";;;AAOA,MAAa,oBAAoB;IAI7B,YAAY,cAAc,EAAE,KAAK,GAAG,EAAE;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,IAAc;QAClB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,UAAU,CAAC,IAAc;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,IAAc,EAAE,KAAU;QAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACzB,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;CACJ;AAhCD,oDAgCC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { BasicQueryStringUtils, LocationLike } from '@openid/appauth';
|
|
2
|
-
export declare class NoHashQueryStringUtils extends BasicQueryStringUtils {
|
|
3
|
-
parse(input: LocationLike, _useHash: boolean): import("@openid/appauth").StringMap;
|
|
4
|
-
}
|
|
5
|
-
export declare class HashQueryStringUtils extends BasicQueryStringUtils {
|
|
6
|
-
parse(input: LocationLike, _useHash: boolean): import("@openid/appauth").StringMap;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=noHashQueryStringUtils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noHashQueryStringUtils.d.ts","sourceRoot":"","sources":["../../src/oidc/vanilla/noHashQueryStringUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEtE,qBAAa,sBAAuB,SAAQ,qBAAqB;IAC7D,KAAK,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO;CAG/C;AAID,qBAAa,oBAAqB,SAAQ,qBAAqB;IAC3D,KAAK,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO;CAoB/C"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HashQueryStringUtils = exports.NoHashQueryStringUtils = void 0;
|
|
4
|
-
const appauth_1 = require("@openid/appauth");
|
|
5
|
-
class NoHashQueryStringUtils extends appauth_1.BasicQueryStringUtils {
|
|
6
|
-
parse(input, _useHash) {
|
|
7
|
-
return super.parse(input, false /* never use hash */);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
exports.NoHashQueryStringUtils = NoHashQueryStringUtils;
|
|
11
|
-
const keys = ['code', 'session_state', 'state'];
|
|
12
|
-
class HashQueryStringUtils extends appauth_1.BasicQueryStringUtils {
|
|
13
|
-
parse(input, _useHash) {
|
|
14
|
-
const output = super.parse(input, true /* use hash */);
|
|
15
|
-
// Fix AppAuthJs behavior
|
|
16
|
-
let propertyToDelelete = null;
|
|
17
|
-
Object.entries(output).forEach(([key, value]) => {
|
|
18
|
-
keys.forEach(k => {
|
|
19
|
-
if (key.endsWith(`?${k}`)) {
|
|
20
|
-
output[k] = value;
|
|
21
|
-
propertyToDelelete = key;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
if (propertyToDelelete) {
|
|
26
|
-
delete output[propertyToDelelete];
|
|
27
|
-
}
|
|
28
|
-
return output;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
exports.HashQueryStringUtils = HashQueryStringUtils;
|
|
32
|
-
//# sourceMappingURL=noHashQueryStringUtils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noHashQueryStringUtils.js","sourceRoot":"","sources":["../../src/oidc/vanilla/noHashQueryStringUtils.ts"],"names":[],"mappings":";;;AAAA,6CAAsE;AAEtE,MAAa,sBAAuB,SAAQ,+BAAqB;IAC7D,KAAK,CAAC,KAAmB,EAAE,QAAiB;QACxC,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC1D,CAAC;CACJ;AAJD,wDAIC;AAED,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAa,oBAAqB,SAAQ,+BAAqB;IAC3D,KAAK,CAAC,KAAmB,EAAE,QAAiB;QACxC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAEvD,yBAAyB;QACzB,IAAI,kBAAkB,GAAG,IAAI,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC5C,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBACb,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;oBACvB,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;oBAClB,kBAAkB,GAAG,GAAG,CAAC;iBAC5B;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,IAAI,kBAAkB,EAAE;YACpB,OAAO,MAAM,CAAC,kBAAkB,CAAC,CAAC;SACrC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ;AArBD,oDAqBC"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
interface SaveItemsFn {
|
|
3
|
-
(items:any):Promise<any>;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export type ItemName = string | number;
|
|
7
|
-
|
|
8
|
-
export class MemoryStorageBackend {
|
|
9
|
-
public items: any;
|
|
10
|
-
private saveItemsAsync: SaveItemsFn;
|
|
11
|
-
|
|
12
|
-
constructor(saveItemsAsync, items = {}) {
|
|
13
|
-
this.items = items;
|
|
14
|
-
this.saveItemsAsync = saveItemsAsync;
|
|
15
|
-
this.saveItemsAsync.bind(this);
|
|
16
|
-
this.getItem.bind(this);
|
|
17
|
-
this.removeItem.bind(this);
|
|
18
|
-
this.clear.bind(this);
|
|
19
|
-
this.setItem.bind(this);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
getItem(name: ItemName) {
|
|
23
|
-
return Promise.resolve(this.items[name]);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
removeItem(name: ItemName) {
|
|
27
|
-
delete this.items[name];
|
|
28
|
-
return this.saveItemsAsync(this.items);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
clear() {
|
|
32
|
-
this.items = {};
|
|
33
|
-
return this.saveItemsAsync(this.items);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
setItem(name: ItemName, value: any) {
|
|
37
|
-
this.items[name] = value;
|
|
38
|
-
return this.saveItemsAsync(this.items);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { BasicQueryStringUtils, LocationLike } from '@openid/appauth';
|
|
2
|
-
|
|
3
|
-
export class NoHashQueryStringUtils extends BasicQueryStringUtils {
|
|
4
|
-
parse(input: LocationLike, _useHash: boolean) {
|
|
5
|
-
return super.parse(input, false /* never use hash */);
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const keys = ['code', 'session_state', 'state'];
|
|
10
|
-
|
|
11
|
-
export class HashQueryStringUtils extends BasicQueryStringUtils {
|
|
12
|
-
parse(input: LocationLike, _useHash: boolean) {
|
|
13
|
-
const output = super.parse(input, true /* use hash */);
|
|
14
|
-
|
|
15
|
-
// Fix AppAuthJs behavior
|
|
16
|
-
let propertyToDelelete = null;
|
|
17
|
-
Object.entries(output).forEach(([key, value]) => {
|
|
18
|
-
keys.forEach(k => {
|
|
19
|
-
if (key.endsWith(`?${k}`)) {
|
|
20
|
-
output[k] = value;
|
|
21
|
-
propertyToDelelete = key;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
if (propertyToDelelete) {
|
|
27
|
-
delete output[propertyToDelelete];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return output;
|
|
31
|
-
}
|
|
32
|
-
}
|