oidc-spa 6.6.1 → 6.8.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 +52 -25
- package/mock/react.d.ts +5 -2
- package/oidc/Oidc.d.ts +2 -2
- package/oidc/StateData.d.ts +0 -3
- package/oidc/StateData.js +0 -1
- package/oidc/StateData.js.map +1 -1
- package/oidc/createOidc.d.ts +19 -4
- package/oidc/createOidc.js +34 -19
- package/oidc/createOidc.js.map +1 -1
- package/oidc/loginOrGoToAuthServer.d.ts +10 -2
- package/oidc/loginOrGoToAuthServer.js +67 -60
- package/oidc/loginOrGoToAuthServer.js.map +1 -1
- package/oidc/loginSilent.d.ts +9 -1
- package/oidc/loginSilent.js +65 -3
- package/oidc/loginSilent.js.map +1 -1
- package/package.json +1 -6
- package/react/react.d.ts +10 -3
- package/react/react.js +44 -5
- package/react/react.js.map +1 -1
- package/src/oidc/Oidc.ts +4 -2
- package/src/oidc/StateData.ts +1 -1
- package/src/oidc/createOidc.ts +55 -17
- package/src/oidc/loginOrGoToAuthServer.ts +77 -53
- package/src/oidc/loginSilent.ts +50 -5
- package/src/react/react.tsx +74 -10
- package/src/vendor/frontend/tsafe.ts +1 -0
- package/vendor/frontend/oidc-client-ts-and-jwt-decode.js +1 -1
- package/vendor/frontend/tsafe.d.ts +1 -0
- package/vendor/frontend/tsafe.js +1 -1
- package/src/tools/JSX.ts +0 -5
- package/tools/JSX.d.ts +0 -5
- package/tools/JSX.js +0 -3
- package/tools/JSX.js.map +0 -1
package/src/oidc/createOidc.ts
CHANGED
|
@@ -57,11 +57,22 @@ export type ParamsOfCreateOidc<
|
|
|
57
57
|
**/
|
|
58
58
|
scopes?: string[];
|
|
59
59
|
/**
|
|
60
|
-
* Transform the url before redirecting to the login pages.
|
|
60
|
+
* Transform the url of the authorization endpoint before redirecting to the login pages.
|
|
61
61
|
*/
|
|
62
62
|
transformUrlBeforeRedirect?: (url: string) => string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* NOTE: Will replace transformUrlBeforeRedirect in the next major version.
|
|
66
|
+
*
|
|
67
|
+
* Transform the url (authorization endpoint) before redirecting to the login pages.
|
|
68
|
+
*
|
|
69
|
+
* The isSilent parameter is true when the redirect is initiated in the background iframe for silent signin.
|
|
70
|
+
* This can be used to omit ui related query parameters (like `ui_locales`).
|
|
71
|
+
*/
|
|
72
|
+
transformUrlBeforeRedirect_next?: (params: { isSilent: boolean; url: string }) => string;
|
|
73
|
+
|
|
63
74
|
/**
|
|
64
|
-
* Extra query params to be added
|
|
75
|
+
* Extra query params to be added to the authorization endpoint url before redirecting or silent signing in.
|
|
65
76
|
* You can provide a function that returns those extra query params, it will be called
|
|
66
77
|
* when login() is called.
|
|
67
78
|
*
|
|
@@ -69,7 +80,9 @@ export type ParamsOfCreateOidc<
|
|
|
69
80
|
*
|
|
70
81
|
* This parameter can also be passed to login() directly.
|
|
71
82
|
*/
|
|
72
|
-
extraQueryParams?:
|
|
83
|
+
extraQueryParams?:
|
|
84
|
+
| Record<string, string | undefined>
|
|
85
|
+
| ((params: { isSilent: boolean; url: string }) => Record<string, string | undefined>);
|
|
73
86
|
/**
|
|
74
87
|
* Extra body params to be added to the /token POST request.
|
|
75
88
|
*
|
|
@@ -81,7 +94,7 @@ export type ParamsOfCreateOidc<
|
|
|
81
94
|
* Example: extraTokenParams: ()=> ({ selectedCustomer: "xxx" })
|
|
82
95
|
* extraTokenParams: { selectedCustomer: "xxx" }
|
|
83
96
|
*/
|
|
84
|
-
extraTokenParams?: Record<string, string> | (() => Record<string, string>);
|
|
97
|
+
extraTokenParams?: Record<string, string | undefined> | (() => Record<string, string | undefined>);
|
|
85
98
|
/**
|
|
86
99
|
* Where to redirect after successful login.
|
|
87
100
|
* Default: window.location.href (here)
|
|
@@ -246,6 +259,7 @@ export async function createOidc_nonMemoized<
|
|
|
246
259
|
}
|
|
247
260
|
): Promise<AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>> {
|
|
248
261
|
const {
|
|
262
|
+
transformUrlBeforeRedirect_next,
|
|
249
263
|
transformUrlBeforeRedirect,
|
|
250
264
|
extraQueryParams: extraQueryParamsOrGetter,
|
|
251
265
|
extraTokenParams: extraTokenParamsOrGetter,
|
|
@@ -261,19 +275,29 @@ export async function createOidc_nonMemoized<
|
|
|
261
275
|
|
|
262
276
|
const { issuerUri, clientId, scopes, configId, log } = preProcessedParams;
|
|
263
277
|
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (typeof valueOrGetter === "function") {
|
|
268
|
-
return valueOrGetter;
|
|
278
|
+
const getExtraQueryParams = (() => {
|
|
279
|
+
if (extraQueryParamsOrGetter === undefined) {
|
|
280
|
+
return undefined;
|
|
269
281
|
}
|
|
270
282
|
|
|
271
|
-
if (
|
|
272
|
-
return () =>
|
|
283
|
+
if (typeof extraQueryParamsOrGetter !== "function") {
|
|
284
|
+
return () => extraQueryParamsOrGetter;
|
|
273
285
|
}
|
|
274
286
|
|
|
275
|
-
return
|
|
276
|
-
});
|
|
287
|
+
return extraQueryParamsOrGetter;
|
|
288
|
+
})();
|
|
289
|
+
|
|
290
|
+
const getExtraTokenParams = (() => {
|
|
291
|
+
if (extraTokenParamsOrGetter === undefined) {
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (typeof extraTokenParamsOrGetter !== "function") {
|
|
296
|
+
return () => extraTokenParamsOrGetter;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return extraTokenParamsOrGetter;
|
|
300
|
+
})();
|
|
277
301
|
|
|
278
302
|
const homeAndCallbackUrl = toFullyQualifiedUrl({
|
|
279
303
|
urlish: homeUrl_params,
|
|
@@ -369,8 +393,10 @@ export async function createOidc_nonMemoized<
|
|
|
369
393
|
const { loginOrGoToAuthServer } = createLoginOrGoToAuthServer({
|
|
370
394
|
configId,
|
|
371
395
|
oidcClientTsUserManager,
|
|
372
|
-
getExtraQueryParams,
|
|
373
396
|
transformUrlBeforeRedirect,
|
|
397
|
+
transformUrlBeforeRedirect_next,
|
|
398
|
+
getExtraQueryParams,
|
|
399
|
+
getExtraTokenParams,
|
|
374
400
|
homeAndCallbackUrl,
|
|
375
401
|
evtIsUserLoggedIn,
|
|
376
402
|
log
|
|
@@ -400,7 +426,13 @@ export async function createOidc_nonMemoized<
|
|
|
400
426
|
switch (stateData.action) {
|
|
401
427
|
case "login":
|
|
402
428
|
{
|
|
403
|
-
log?.(
|
|
429
|
+
log?.(
|
|
430
|
+
`Handling login redirect auth response ${JSON.stringify(
|
|
431
|
+
authResponse,
|
|
432
|
+
null,
|
|
433
|
+
2
|
|
434
|
+
)}`
|
|
435
|
+
);
|
|
404
436
|
|
|
405
437
|
const authResponseUrl = authResponseToUrl(authResponse);
|
|
406
438
|
|
|
@@ -540,6 +572,8 @@ export async function createOidc_nonMemoized<
|
|
|
540
572
|
oidcClientTsUserManager,
|
|
541
573
|
stateQueryParamValue_instance,
|
|
542
574
|
configId,
|
|
575
|
+
transformUrlBeforeRedirect_next,
|
|
576
|
+
getExtraQueryParams,
|
|
543
577
|
getExtraTokenParams
|
|
544
578
|
});
|
|
545
579
|
|
|
@@ -886,7 +920,9 @@ export async function createOidc_nonMemoized<
|
|
|
886
920
|
return new Promise<never>(() => {});
|
|
887
921
|
},
|
|
888
922
|
renewTokens: (() => {
|
|
889
|
-
async function renewTokens_nonMutexed(params: {
|
|
923
|
+
async function renewTokens_nonMutexed(params: {
|
|
924
|
+
extraTokenParams: Record<string, string | undefined>;
|
|
925
|
+
}) {
|
|
890
926
|
const { extraTokenParams } = params;
|
|
891
927
|
|
|
892
928
|
log?.("Renewing tokens");
|
|
@@ -897,6 +933,8 @@ export async function createOidc_nonMemoized<
|
|
|
897
933
|
oidcClientTsUserManager,
|
|
898
934
|
stateQueryParamValue_instance,
|
|
899
935
|
configId,
|
|
936
|
+
transformUrlBeforeRedirect_next,
|
|
937
|
+
getExtraQueryParams,
|
|
900
938
|
getExtraTokenParams: () => extraTokenParams
|
|
901
939
|
});
|
|
902
940
|
|
|
@@ -999,7 +1037,7 @@ export async function createOidc_nonMemoized<
|
|
|
999
1037
|
let ongoingCall:
|
|
1000
1038
|
| {
|
|
1001
1039
|
pr: Promise<void>;
|
|
1002
|
-
extraTokenParams: Record<string, string>;
|
|
1040
|
+
extraTokenParams: Record<string, string | undefined>;
|
|
1003
1041
|
}
|
|
1004
1042
|
| undefined = undefined;
|
|
1005
1043
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { UserManager as OidcClientTsUserManager } from "../vendor/frontend/oidc-client-ts-and-jwt-decode";
|
|
2
2
|
import { toFullyQualifiedUrl } from "../tools/toFullyQualifiedUrl";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { assert, type Equals, noUndefined } from "../vendor/frontend/tsafe";
|
|
4
|
+
import { StateData } from "./StateData";
|
|
5
5
|
import type { NonPostableEvt } from "../tools/Evt";
|
|
6
6
|
import { type StatefulEvt, createStatefulEvt } from "../tools/StatefulEvt";
|
|
7
7
|
import { Deferred } from "../tools/Deferred";
|
|
@@ -27,7 +27,7 @@ type Params = Params.Login | Params.GoToAuthServer;
|
|
|
27
27
|
namespace Params {
|
|
28
28
|
type Common = {
|
|
29
29
|
redirectUrl: string;
|
|
30
|
-
extraQueryParams_local: Record<string, string> | undefined;
|
|
30
|
+
extraQueryParams_local: Record<string, string | undefined> | undefined;
|
|
31
31
|
transformUrlBeforeRedirect_local: ((url: string) => string) | undefined;
|
|
32
32
|
};
|
|
33
33
|
|
|
@@ -59,8 +59,15 @@ export function getPrSafelyRestoredFromBfCacheAfterLoginBackNavigation() {
|
|
|
59
59
|
export function createLoginOrGoToAuthServer(params: {
|
|
60
60
|
configId: string;
|
|
61
61
|
oidcClientTsUserManager: OidcClientTsUserManager;
|
|
62
|
-
getExtraQueryParams: (() => Record<string, string>) | undefined;
|
|
63
62
|
transformUrlBeforeRedirect: ((url: string) => string) | undefined;
|
|
63
|
+
transformUrlBeforeRedirect_next: ((params: { isSilent: false; url: string }) => string) | undefined;
|
|
64
|
+
|
|
65
|
+
getExtraQueryParams:
|
|
66
|
+
| ((params: { isSilent: false; url: string }) => Record<string, string | undefined>)
|
|
67
|
+
| undefined;
|
|
68
|
+
|
|
69
|
+
getExtraTokenParams: (() => Record<string, string | undefined>) | undefined;
|
|
70
|
+
|
|
64
71
|
homeAndCallbackUrl: string;
|
|
65
72
|
evtIsUserLoggedIn: NonPostableEvt<boolean>;
|
|
66
73
|
log: typeof console.log | undefined;
|
|
@@ -68,8 +75,13 @@ export function createLoginOrGoToAuthServer(params: {
|
|
|
68
75
|
const {
|
|
69
76
|
configId,
|
|
70
77
|
oidcClientTsUserManager,
|
|
71
|
-
|
|
78
|
+
|
|
72
79
|
transformUrlBeforeRedirect,
|
|
80
|
+
transformUrlBeforeRedirect_next,
|
|
81
|
+
getExtraQueryParams,
|
|
82
|
+
|
|
83
|
+
getExtraTokenParams,
|
|
84
|
+
|
|
73
85
|
homeAndCallbackUrl,
|
|
74
86
|
evtIsUserLoggedIn,
|
|
75
87
|
log
|
|
@@ -83,7 +95,7 @@ export function createLoginOrGoToAuthServer(params: {
|
|
|
83
95
|
const {
|
|
84
96
|
redirectUrl: redirectUrl_params,
|
|
85
97
|
extraQueryParams_local,
|
|
86
|
-
transformUrlBeforeRedirect_local,
|
|
98
|
+
transformUrlBeforeRedirect_local: transformUrl,
|
|
87
99
|
...rest
|
|
88
100
|
} = params;
|
|
89
101
|
|
|
@@ -152,33 +164,82 @@ export function createLoginOrGoToAuthServer(params: {
|
|
|
152
164
|
|
|
153
165
|
log?.(`redirectUrl: ${redirectUrl}`);
|
|
154
166
|
|
|
167
|
+
const stateData: StateData = {
|
|
168
|
+
context: "redirect",
|
|
169
|
+
redirectUrl,
|
|
170
|
+
extraQueryParams: {},
|
|
171
|
+
hasBeenProcessedByCallback: false,
|
|
172
|
+
configId,
|
|
173
|
+
action: "login",
|
|
174
|
+
redirectUrl_consentRequiredCase: (() => {
|
|
175
|
+
switch (rest.action) {
|
|
176
|
+
case "login":
|
|
177
|
+
return lastPublicUrl ?? homeAndCallbackUrl;
|
|
178
|
+
case "go to auth server":
|
|
179
|
+
return redirectUrl;
|
|
180
|
+
}
|
|
181
|
+
})()
|
|
182
|
+
};
|
|
183
|
+
|
|
155
184
|
const transformUrl_oidcClientTs = (url: string) => {
|
|
156
185
|
(
|
|
157
186
|
[
|
|
158
|
-
[
|
|
159
|
-
|
|
187
|
+
[
|
|
188
|
+
undefined,
|
|
189
|
+
transformUrlBeforeRedirect_next === undefined
|
|
190
|
+
? undefined
|
|
191
|
+
: (url: string) => transformUrlBeforeRedirect_next({ url, isSilent: false })
|
|
192
|
+
],
|
|
193
|
+
[getExtraQueryParams, transformUrlBeforeRedirect],
|
|
194
|
+
[extraQueryParams_local, transformUrl]
|
|
160
195
|
] as const
|
|
161
|
-
).forEach(([
|
|
196
|
+
).forEach(([extraQueryParamsMaybeGetter, transformUrlBeforeRedirect], i) => {
|
|
197
|
+
const urlObj_before = i !== 2 ? undefined : new URL(url);
|
|
198
|
+
|
|
162
199
|
add_extra_query_params: {
|
|
163
|
-
if (
|
|
200
|
+
if (extraQueryParamsMaybeGetter === undefined) {
|
|
164
201
|
break add_extra_query_params;
|
|
165
202
|
}
|
|
166
203
|
|
|
204
|
+
const extraQueryParams =
|
|
205
|
+
typeof extraQueryParamsMaybeGetter === "function"
|
|
206
|
+
? extraQueryParamsMaybeGetter({ isSilent: false, url })
|
|
207
|
+
: extraQueryParamsMaybeGetter;
|
|
208
|
+
|
|
167
209
|
const url_obj = new URL(url);
|
|
168
210
|
|
|
169
211
|
for (const [name, value] of Object.entries(extraQueryParams)) {
|
|
212
|
+
if (value === undefined) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
170
215
|
url_obj.searchParams.set(name, value);
|
|
171
216
|
}
|
|
172
217
|
|
|
173
218
|
url = url_obj.href;
|
|
174
219
|
}
|
|
175
220
|
|
|
176
|
-
|
|
221
|
+
apply_transform_url: {
|
|
177
222
|
if (transformUrlBeforeRedirect === undefined) {
|
|
178
|
-
break
|
|
223
|
+
break apply_transform_url;
|
|
179
224
|
}
|
|
180
225
|
url = transformUrlBeforeRedirect(url);
|
|
181
226
|
}
|
|
227
|
+
|
|
228
|
+
update_state: {
|
|
229
|
+
if (urlObj_before === undefined) {
|
|
230
|
+
break update_state;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (const [name, value] of new URL(url).searchParams.entries()) {
|
|
234
|
+
const value_before = urlObj_before.searchParams.get(name);
|
|
235
|
+
|
|
236
|
+
if (value_before === value) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
stateData.extraQueryParams[name] = value;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
182
243
|
});
|
|
183
244
|
|
|
184
245
|
return url;
|
|
@@ -197,48 +258,9 @@ export function createLoginOrGoToAuthServer(params: {
|
|
|
197
258
|
|
|
198
259
|
log?.(`redirectMethod: ${redirectMethod}`);
|
|
199
260
|
|
|
200
|
-
const { extraQueryParams } = (() => {
|
|
201
|
-
const extraQueryParams: Record<string, string> = extraQueryParams_local ?? {};
|
|
202
|
-
|
|
203
|
-
read_query_params_added_by_transform_before_redirect: {
|
|
204
|
-
if (transformUrlBeforeRedirect_local === undefined) {
|
|
205
|
-
break read_query_params_added_by_transform_before_redirect;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
let url_afterTransform;
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
url_afterTransform = transformUrlBeforeRedirect_local("https://dummy.com");
|
|
212
|
-
} catch {
|
|
213
|
-
break read_query_params_added_by_transform_before_redirect;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
for (const [name, value] of new URL(url_afterTransform).searchParams) {
|
|
217
|
-
extraQueryParams[name] = value;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return { extraQueryParams };
|
|
222
|
-
})();
|
|
223
|
-
|
|
224
261
|
return oidcClientTsUserManager
|
|
225
262
|
.signinRedirect({
|
|
226
|
-
state:
|
|
227
|
-
context: "redirect",
|
|
228
|
-
redirectUrl,
|
|
229
|
-
extraQueryParams,
|
|
230
|
-
hasBeenProcessedByCallback: false,
|
|
231
|
-
configId,
|
|
232
|
-
action: "login",
|
|
233
|
-
redirectUrl_consentRequiredCase: (() => {
|
|
234
|
-
switch (rest.action) {
|
|
235
|
-
case "login":
|
|
236
|
-
return lastPublicUrl ?? homeAndCallbackUrl;
|
|
237
|
-
case "go to auth server":
|
|
238
|
-
return redirectUrl;
|
|
239
|
-
}
|
|
240
|
-
})()
|
|
241
|
-
}),
|
|
263
|
+
state: stateData,
|
|
242
264
|
redirectMethod,
|
|
243
265
|
prompt: (() => {
|
|
244
266
|
switch (rest.action) {
|
|
@@ -249,7 +271,9 @@ export function createLoginOrGoToAuthServer(params: {
|
|
|
249
271
|
}
|
|
250
272
|
assert<Equals<typeof rest, never>>;
|
|
251
273
|
})(),
|
|
252
|
-
transformUrl: transformUrl_oidcClientTs
|
|
274
|
+
transformUrl: transformUrl_oidcClientTs,
|
|
275
|
+
extraTokenParams:
|
|
276
|
+
getExtraTokenParams === undefined ? undefined : noUndefined(getExtraTokenParams())
|
|
253
277
|
})
|
|
254
278
|
.then(() => new Promise<never>(() => {}));
|
|
255
279
|
}
|
package/src/oidc/loginSilent.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UserManager as OidcClientTsUserManager } from "../vendor/frontend/oidc-client-ts-and-jwt-decode";
|
|
2
2
|
import { Deferred } from "../tools/Deferred";
|
|
3
|
-
import { id, assert } from "../vendor/frontend/tsafe";
|
|
3
|
+
import { id, assert, noUndefined } from "../vendor/frontend/tsafe";
|
|
4
4
|
import { getStateData, clearStateStore, type StateData } from "./StateData";
|
|
5
5
|
import { getDownlinkAndRtt } from "../tools/getDownlinkAndRtt";
|
|
6
6
|
import { getIsDev } from "../tools/isDev";
|
|
@@ -25,10 +25,23 @@ export async function loginSilent(params: {
|
|
|
25
25
|
oidcClientTsUserManager: OidcClientTsUserManager;
|
|
26
26
|
stateQueryParamValue_instance: string;
|
|
27
27
|
configId: string;
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
transformUrlBeforeRedirect_next: ((params: { isSilent: true; url: string }) => string) | undefined;
|
|
30
|
+
|
|
31
|
+
getExtraQueryParams:
|
|
32
|
+
| ((params: { isSilent: true; url: string }) => Record<string, string | undefined>)
|
|
33
|
+
| undefined;
|
|
34
|
+
|
|
35
|
+
getExtraTokenParams: (() => Record<string, string | undefined>) | undefined;
|
|
29
36
|
}): Promise<ResultOfLoginSilent> {
|
|
30
|
-
const {
|
|
31
|
-
|
|
37
|
+
const {
|
|
38
|
+
oidcClientTsUserManager,
|
|
39
|
+
stateQueryParamValue_instance,
|
|
40
|
+
configId,
|
|
41
|
+
transformUrlBeforeRedirect_next,
|
|
42
|
+
getExtraQueryParams,
|
|
43
|
+
getExtraTokenParams
|
|
44
|
+
} = params;
|
|
32
45
|
|
|
33
46
|
const dResult = new Deferred<ResultOfLoginSilent>();
|
|
34
47
|
|
|
@@ -88,6 +101,36 @@ export async function loginSilent(params: {
|
|
|
88
101
|
|
|
89
102
|
window.addEventListener("message", listener, false);
|
|
90
103
|
|
|
104
|
+
const transformUrl_oidcClientTs = (url: string) => {
|
|
105
|
+
add_extra_query_params: {
|
|
106
|
+
if (getExtraQueryParams === undefined) {
|
|
107
|
+
break add_extra_query_params;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const extraQueryParams = getExtraQueryParams({ isSilent: true, url });
|
|
111
|
+
|
|
112
|
+
const url_obj = new URL(url);
|
|
113
|
+
|
|
114
|
+
for (const [name, value] of Object.entries(extraQueryParams)) {
|
|
115
|
+
if (value === undefined) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
url_obj.searchParams.set(name, value);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
url = url_obj.href;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
apply_transform_url: {
|
|
125
|
+
if (transformUrlBeforeRedirect_next === undefined) {
|
|
126
|
+
break apply_transform_url;
|
|
127
|
+
}
|
|
128
|
+
url = transformUrlBeforeRedirect_next({ url, isSilent: true });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return url;
|
|
132
|
+
};
|
|
133
|
+
|
|
91
134
|
oidcClientTsUserManager
|
|
92
135
|
.signinSilent({
|
|
93
136
|
state: id<StateData.IFrame>({
|
|
@@ -95,7 +138,9 @@ export async function loginSilent(params: {
|
|
|
95
138
|
configId
|
|
96
139
|
}),
|
|
97
140
|
silentRequestTimeoutInSeconds: timeoutDelayMs / 1000,
|
|
98
|
-
extraTokenParams:
|
|
141
|
+
extraTokenParams:
|
|
142
|
+
getExtraTokenParams === undefined ? undefined : noUndefined(getExtraTokenParams()),
|
|
143
|
+
transformUrl: transformUrl_oidcClientTs
|
|
99
144
|
})
|
|
100
145
|
.then(
|
|
101
146
|
oidcClientTsUser => {
|
package/src/react/react.tsx
CHANGED
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
useContext,
|
|
6
6
|
useReducer,
|
|
7
7
|
useRef,
|
|
8
|
-
type ReactNode
|
|
8
|
+
type ReactNode,
|
|
9
|
+
type ComponentType,
|
|
10
|
+
type FC,
|
|
11
|
+
JSX
|
|
9
12
|
} from "react";
|
|
10
|
-
import type { JSX } from "../tools/JSX";
|
|
11
13
|
import { type Oidc, createOidc, type ParamsOfCreateOidc, OidcInitializationError } from "../oidc";
|
|
12
|
-
import { assert, type Equals } from "../vendor/frontend/tsafe";
|
|
14
|
+
import { assert, type Equals, type Param0 } from "../vendor/frontend/tsafe";
|
|
13
15
|
import { id } from "../vendor/frontend/tsafe";
|
|
14
16
|
import type { ValueOrAsyncGetter } from "../tools/ValueOrAsyncGetter";
|
|
15
17
|
import { Deferred } from "../tools/Deferred";
|
|
@@ -23,7 +25,12 @@ export namespace OidcReact {
|
|
|
23
25
|
|
|
24
26
|
export type NotLoggedIn = Common & {
|
|
25
27
|
isUserLoggedIn: false;
|
|
26
|
-
login:
|
|
28
|
+
login: (params?: {
|
|
29
|
+
extraQueryParams?: Record<string, string | undefined>;
|
|
30
|
+
redirectUrl?: string;
|
|
31
|
+
transformUrlBeforeRedirect?: (url: string) => string;
|
|
32
|
+
doesCurrentHrefRequiresAuth?: boolean;
|
|
33
|
+
}) => Promise<never>;
|
|
27
34
|
initializationError: OidcInitializationError | undefined;
|
|
28
35
|
|
|
29
36
|
/** @deprecated: Use `const { decodedIdToken, tokens} = useOidc();` */
|
|
@@ -67,6 +74,14 @@ export namespace OidcReact {
|
|
|
67
74
|
isNewBrowserSession: boolean;
|
|
68
75
|
};
|
|
69
76
|
}
|
|
77
|
+
{
|
|
78
|
+
type Actual = Param0<OidcReact.NotLoggedIn["login"]>;
|
|
79
|
+
type Expected = Omit<Param0<Oidc.NotLoggedIn["login"]>, "doesCurrentHrefRequiresAuth"> & {
|
|
80
|
+
doesCurrentHrefRequiresAuth?: boolean;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
assert<Equals<Actual, Expected>>();
|
|
84
|
+
}
|
|
70
85
|
|
|
71
86
|
type OidcReactApi<DecodedIdToken extends Record<string, unknown>, AutoLogin extends boolean> = {
|
|
72
87
|
OidcProvider: AutoLogin extends true
|
|
@@ -88,6 +103,12 @@ type OidcReactApi<DecodedIdToken extends Record<string, unknown>, AutoLogin exte
|
|
|
88
103
|
getOidc: () => Promise<
|
|
89
104
|
AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>
|
|
90
105
|
>;
|
|
106
|
+
withAuthenticationRequired: <Props extends Record<string, unknown>>(
|
|
107
|
+
Component: ComponentType<Props>,
|
|
108
|
+
params?: {
|
|
109
|
+
onRedirecting: () => JSX.Element | null;
|
|
110
|
+
}
|
|
111
|
+
) => FC<Props>;
|
|
91
112
|
};
|
|
92
113
|
|
|
93
114
|
export function createOidcReactApi_dependencyInjection<
|
|
@@ -109,7 +130,9 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
109
130
|
> {
|
|
110
131
|
const dReadyToCreate = new Deferred<void>();
|
|
111
132
|
|
|
112
|
-
const oidcContext = createContext<Oidc<DecodedIdToken
|
|
133
|
+
const oidcContext = createContext<{ oidc: Oidc<DecodedIdToken>; fallback: ReactNode } | undefined>(
|
|
134
|
+
undefined
|
|
135
|
+
);
|
|
113
136
|
|
|
114
137
|
// NOTE: It can be InitializationError only if autoLogin is true
|
|
115
138
|
const prOidcOrInitializationError = (async () => {
|
|
@@ -183,7 +206,11 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
183
206
|
|
|
184
207
|
const oidc = oidcOrInitializationError;
|
|
185
208
|
|
|
186
|
-
return
|
|
209
|
+
return (
|
|
210
|
+
<oidcContext.Provider value={{ oidc, fallback: fallback ?? null }}>
|
|
211
|
+
{children}
|
|
212
|
+
</oidcContext.Provider>
|
|
213
|
+
);
|
|
187
214
|
}
|
|
188
215
|
|
|
189
216
|
function useOidc(params?: {
|
|
@@ -191,9 +218,11 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
191
218
|
}): OidcReact<DecodedIdToken> {
|
|
192
219
|
const { assert: assert_params } = params ?? {};
|
|
193
220
|
|
|
194
|
-
const
|
|
221
|
+
const contextValue = useContext(oidcContext);
|
|
195
222
|
|
|
196
|
-
assert(
|
|
223
|
+
assert(contextValue !== undefined, "You must use useOidc inside the corresponding OidcProvider");
|
|
224
|
+
|
|
225
|
+
const { oidc } = contextValue;
|
|
197
226
|
|
|
198
227
|
check_assertion: {
|
|
199
228
|
if (assert_params === undefined) {
|
|
@@ -289,7 +318,8 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
289
318
|
return id<OidcReact.NotLoggedIn>({
|
|
290
319
|
...common,
|
|
291
320
|
isUserLoggedIn: false,
|
|
292
|
-
login:
|
|
321
|
+
login: ({ doesCurrentHrefRequiresAuth = false, ...rest } = {}) =>
|
|
322
|
+
oidc.login({ doesCurrentHrefRequiresAuth, ...rest }),
|
|
293
323
|
initializationError: oidc.initializationError
|
|
294
324
|
});
|
|
295
325
|
}
|
|
@@ -315,6 +345,39 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
315
345
|
return oidcReact;
|
|
316
346
|
}
|
|
317
347
|
|
|
348
|
+
function withAuthenticationRequired<Props extends Record<string, unknown>>(
|
|
349
|
+
Component: ComponentType<Props>,
|
|
350
|
+
params?: {
|
|
351
|
+
onRedirecting?: () => JSX.Element | null;
|
|
352
|
+
}
|
|
353
|
+
): FC<Props> {
|
|
354
|
+
const { onRedirecting } = params ?? {};
|
|
355
|
+
|
|
356
|
+
function ComponentWithAuthenticationRequired(props: Props) {
|
|
357
|
+
const contextValue = useContext(oidcContext);
|
|
358
|
+
|
|
359
|
+
assert(contextValue !== undefined);
|
|
360
|
+
|
|
361
|
+
const { oidc, fallback } = contextValue;
|
|
362
|
+
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
if (oidc.isUserLoggedIn) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
oidc.login({ doesCurrentHrefRequiresAuth: true });
|
|
369
|
+
}, []);
|
|
370
|
+
|
|
371
|
+
if (!oidc.isUserLoggedIn) {
|
|
372
|
+
return onRedirecting === undefined ? fallback : onRedirecting();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return <Component {...props} />;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return ComponentWithAuthenticationRequired;
|
|
379
|
+
}
|
|
380
|
+
|
|
318
381
|
const prOidc = prOidcOrInitializationError.then(oidcOrInitializationError => {
|
|
319
382
|
if (oidcOrInitializationError instanceof OidcInitializationError) {
|
|
320
383
|
return new Promise<never>(() => {});
|
|
@@ -341,7 +404,8 @@ export function createOidcReactApi_dependencyInjection<
|
|
|
341
404
|
}
|
|
342
405
|
|
|
343
406
|
return oidc;
|
|
344
|
-
}
|
|
407
|
+
},
|
|
408
|
+
withAuthenticationRequired
|
|
345
409
|
};
|
|
346
410
|
}
|
|
347
411
|
|
|
@@ -2,4 +2,5 @@ export { id } from "tsafe/id";
|
|
|
2
2
|
export { assert, is, type Equals } from "tsafe/assert";
|
|
3
3
|
export { typeGuard } from "tsafe/typeGuard";
|
|
4
4
|
export { overwriteReadonlyProp } from "tsafe/lab/overwriteReadonlyProp";
|
|
5
|
+
export { noUndefined } from "tsafe/noUndefined";
|
|
5
6
|
export type { Param0 } from "tsafe";
|