oidc-spa 3.0.3 → 4.0.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 +11 -3
- package/oidc.d.ts +21 -9
- package/oidc.js +82 -45
- package/oidc.js.map +1 -1
- package/package.json +14 -9
- package/react.d.ts +16 -24
- package/react.js +54 -27
- package/react.js.map +1 -1
- package/src/oidc.ts +149 -62
- package/src/react.tsx +118 -85
- package/src/tools/powerhooks/useGuaranteedMemo.ts +18 -0
- package/tools/powerhooks/useGuaranteedMemo.d.ts +1 -0
- package/tools/powerhooks/useGuaranteedMemo.js +43 -0
- package/tools/powerhooks/useGuaranteedMemo.js.map +1 -0
package/react.js
CHANGED
|
@@ -27,17 +27,18 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
27
27
|
return ar;
|
|
28
28
|
};
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.
|
|
30
|
+
exports.createReactOidc = void 0;
|
|
31
31
|
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
32
32
|
var react_1 = require("react");
|
|
33
33
|
var oidc_1 = require("./oidc");
|
|
34
34
|
var assert_1 = require("tsafe/assert");
|
|
35
|
-
var decodeJwt_1 = require("./tools/decodeJwt");
|
|
36
35
|
var id_1 = require("tsafe/id");
|
|
36
|
+
var useGuaranteedMemo_1 = require("./tools/powerhooks/useGuaranteedMemo");
|
|
37
37
|
var oidcContext = (0, react_1.createContext)(undefined);
|
|
38
38
|
/** @see: https://github.com/garronej/oidc-spa#option-2-usage-directly-within-react */
|
|
39
|
-
function
|
|
39
|
+
function createReactOidc(params) {
|
|
40
40
|
var prOidc = (0, oidc_1.createOidc)(params);
|
|
41
|
+
var decodedIdTokenSchema = params.decodedIdTokenSchema;
|
|
41
42
|
function OidcProvider(props) {
|
|
42
43
|
var children = props.children, fallback = props.fallback;
|
|
43
44
|
var _a = __read((0, react_1.useState)(undefined), 2), oidc = _a[0], setOidc = _a[1];
|
|
@@ -47,18 +48,16 @@ function createOidcProvider(params) {
|
|
|
47
48
|
if (oidc === undefined) {
|
|
48
49
|
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: fallback === undefined ? null : fallback });
|
|
49
50
|
}
|
|
50
|
-
return (0, jsx_runtime_1.jsx)(oidcContext.Provider, { value: oidc, children: children });
|
|
51
|
+
return ((0, jsx_runtime_1.jsx)(oidcContext.Provider, { value: { oidc: oidc, decodedIdTokenSchema: decodedIdTokenSchema }, children: children }));
|
|
51
52
|
}
|
|
52
|
-
return { OidcProvider: OidcProvider, prOidc: prOidc };
|
|
53
|
-
}
|
|
54
|
-
exports.createOidcProvider = createOidcProvider;
|
|
55
|
-
function createUseOidc(params) {
|
|
56
|
-
var decodedIdTokenSchema = (params !== null && params !== void 0 ? params : {}).decodedIdTokenSchema;
|
|
57
53
|
function useOidc(params) {
|
|
58
54
|
var _a = (params !== null && params !== void 0 ? params : {}).assertUserLoggedIn, assertUserLoggedIn = _a === void 0 ? false : _a;
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
var _b = (function useClosure() {
|
|
56
|
+
var context = (0, react_1.useContext)(oidcContext);
|
|
57
|
+
(0, assert_1.assert)(context !== undefined, "You must use useOidc inside a OidcProvider");
|
|
58
|
+
return context;
|
|
59
|
+
})(), oidc = _b.oidc, decodedIdTokenSchema_context = _b.decodedIdTokenSchema;
|
|
60
|
+
var _c = __read((0, react_1.useReducer)(function () { return []; }, []), 2), forceUpdate = _c[1];
|
|
62
61
|
(0, react_1.useEffect)(function () {
|
|
63
62
|
if (!oidc.isUserLoggedIn) {
|
|
64
63
|
return;
|
|
@@ -69,25 +68,53 @@ function createUseOidc(params) {
|
|
|
69
68
|
if (assertUserLoggedIn && !oidc.isUserLoggedIn) {
|
|
70
69
|
throw new Error("The user must be logged in to use this hook (assertUserLoggedIn was set to true)");
|
|
71
70
|
}
|
|
72
|
-
var
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
var oidcTokens = (function useClosure() {
|
|
72
|
+
var tokens = oidc.isUserLoggedIn ? oidc.getTokens() : undefined;
|
|
73
|
+
var oidcTokens = (0, useGuaranteedMemo_1.useGuaranteedMemo)(function () {
|
|
74
|
+
if (tokens === undefined) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
var oidcTokens = {
|
|
78
|
+
"accessToken": tokens.accessToken,
|
|
79
|
+
"accessTokenExpirationTime": tokens.accessTokenExpirationTime,
|
|
80
|
+
"idToken": tokens.idToken,
|
|
81
|
+
"refreshToken": tokens.refreshToken,
|
|
82
|
+
"refreshTokenExpirationTime": tokens.refreshTokenExpirationTime,
|
|
83
|
+
"decodedIdToken": null
|
|
84
|
+
};
|
|
85
|
+
var cache = undefined;
|
|
86
|
+
Object.defineProperty(oidcTokens, "decodedIdToken", {
|
|
87
|
+
"get": function () {
|
|
88
|
+
if (cache !== undefined) {
|
|
89
|
+
return cache.decodedIdToken;
|
|
90
|
+
}
|
|
91
|
+
var decodedIdToken = tokens.decodedIdToken;
|
|
92
|
+
if (decodedIdTokenSchema !== undefined &&
|
|
93
|
+
decodedIdTokenSchema !== decodedIdTokenSchema_context) {
|
|
94
|
+
decodedIdToken = decodedIdTokenSchema.parse(decodedIdToken);
|
|
95
|
+
}
|
|
96
|
+
cache = { decodedIdToken: decodedIdToken };
|
|
97
|
+
return decodedIdToken;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return oidcTokens;
|
|
101
|
+
}, [
|
|
102
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.accessToken,
|
|
103
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.accessTokenExpirationTime,
|
|
104
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.idToken,
|
|
105
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.refreshToken,
|
|
106
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.refreshTokenExpirationTime
|
|
107
|
+
]);
|
|
108
|
+
return { oidcTokens: oidcTokens };
|
|
109
|
+
})().oidcTokens;
|
|
83
110
|
var common = {
|
|
84
111
|
"params": oidc.params
|
|
85
112
|
};
|
|
86
113
|
return oidc.isUserLoggedIn
|
|
87
|
-
? (0, id_1.id)(
|
|
88
|
-
: (0, id_1.id)(__assign(__assign({}, common), { "isUserLoggedIn": false, "login": oidc.login
|
|
114
|
+
? (0, id_1.id)(((0, assert_1.assert)(oidcTokens !== undefined), __assign(__assign({}, common), { "isUserLoggedIn": true, oidcTokens: oidcTokens, "logout": oidc.logout, "renewTokens": oidc.renewTokens })))
|
|
115
|
+
: (0, id_1.id)(__assign(__assign({}, common), { "isUserLoggedIn": false, "login": oidc.login }));
|
|
89
116
|
}
|
|
90
|
-
return { useOidc: useOidc };
|
|
117
|
+
return { OidcProvider: OidcProvider, useOidc: useOidc, prOidc: prOidc };
|
|
91
118
|
}
|
|
92
|
-
exports.
|
|
119
|
+
exports.createReactOidc = createReactOidc;
|
|
93
120
|
//# sourceMappingURL=react.js.map
|
package/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sourceRoot":"","sources":["src/react.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["src/react.tsx"],"names":[],"mappings":"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"}
|
package/src/oidc.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { UserManager, type User } from "oidc-client-ts";
|
|
1
|
+
import { UserManager as OidcClientTsUserManager, type User as OidcClientTsUser } from "oidc-client-ts";
|
|
2
2
|
import { id } from "tsafe/id";
|
|
3
3
|
import { readExpirationTimeInJwt } from "./tools/readExpirationTimeInJwt";
|
|
4
4
|
import { assert, type Equals } from "tsafe/assert";
|
|
5
5
|
import { addQueryParamToUrl, retrieveQueryParamFromUrl } from "./tools/urlQueryParams";
|
|
6
6
|
import { fnv1aHashToHex } from "./tools/fnv1aHashToHex";
|
|
7
7
|
import { Deferred } from "./tools/Deferred";
|
|
8
|
+
import { decodeJwt } from "./tools/decodeJwt";
|
|
8
9
|
|
|
9
|
-
export declare type Oidc =
|
|
10
|
+
export declare type Oidc<DecodedIdToken extends Record<string, unknown> = Record<string, unknown>> =
|
|
11
|
+
| Oidc.LoggedIn<DecodedIdToken>
|
|
12
|
+
| Oidc.NotLoggedIn;
|
|
10
13
|
|
|
11
14
|
export declare namespace Oidc {
|
|
12
15
|
export type Common = {
|
|
@@ -24,33 +27,46 @@ export declare namespace Oidc {
|
|
|
24
27
|
}) => Promise<never>;
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
export type LoggedIn =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
export type LoggedIn<DecodedIdToken extends Record<string, unknown> = Record<string, unknown>> =
|
|
31
|
+
Common & {
|
|
32
|
+
isUserLoggedIn: true;
|
|
33
|
+
renewTokens(): Promise<void>;
|
|
34
|
+
getTokens: () => Tokens<DecodedIdToken>;
|
|
35
|
+
subscribeToTokensChange: (onTokenChange: () => void) => { unsubscribe: () => void };
|
|
36
|
+
logout: (
|
|
37
|
+
params:
|
|
38
|
+
| { redirectTo: "home" | "current page" }
|
|
39
|
+
| { redirectTo: "specific url"; url: string }
|
|
40
|
+
) => Promise<never>;
|
|
41
|
+
};
|
|
36
42
|
|
|
37
|
-
export type Tokens =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
export type Tokens<DecodedIdToken extends Record<string, unknown> = Record<string, unknown>> =
|
|
44
|
+
Readonly<{
|
|
45
|
+
accessToken: string;
|
|
46
|
+
accessTokenExpirationTime: number;
|
|
47
|
+
idToken: string;
|
|
48
|
+
refreshToken: string;
|
|
49
|
+
refreshTokenExpirationTime: number;
|
|
50
|
+
decodedIdToken: DecodedIdToken;
|
|
51
|
+
}>;
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
const paramsToRetrieveFromSuccessfulLogin = ["code", "state", "session_state", "iss"] as const;
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
export type ParamsOfCreateOidc<
|
|
57
|
+
DecodedIdToken extends Record<string, unknown> = Record<string, unknown>
|
|
58
|
+
> = {
|
|
50
59
|
issuerUri: string;
|
|
51
60
|
clientId: string;
|
|
52
61
|
transformUrlBeforeRedirect?: (url: string) => string;
|
|
53
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Extra query params to be added on the login url.
|
|
64
|
+
* You can provide a function that returns those extra query params, it will be called
|
|
65
|
+
* when login() is called.
|
|
66
|
+
*
|
|
67
|
+
* Example: extraQueryParams: ()=> ({ ui_locales: "fr" })
|
|
68
|
+
*/
|
|
69
|
+
extraQueryParams?: Record<string, string> | (() => Record<string, string>);
|
|
54
70
|
/**
|
|
55
71
|
* This parameter have to be provided if your App is not hosted at the origin of the subdomain.
|
|
56
72
|
* For example if your site is hosted by navigating to `https://www.example.com`
|
|
@@ -64,15 +80,34 @@ export async function createOidc(params: {
|
|
|
64
80
|
* you are supposed to have created in your `public/` directory.
|
|
65
81
|
*/
|
|
66
82
|
publicUrl?: string;
|
|
67
|
-
|
|
83
|
+
decodedIdTokenSchema?: { parse: (data: unknown) => DecodedIdToken };
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** @see: https://github.com/garronej/oidc-spa#option-1-usage-without-involving-the-ui-framework */
|
|
87
|
+
export async function createOidc<
|
|
88
|
+
DecodedIdToken extends Record<string, unknown> = Record<string, unknown>
|
|
89
|
+
>(params: ParamsOfCreateOidc<DecodedIdToken>): Promise<Oidc<DecodedIdToken>> {
|
|
68
90
|
const {
|
|
69
91
|
issuerUri,
|
|
70
92
|
clientId,
|
|
71
93
|
transformUrlBeforeRedirect = url => url,
|
|
72
|
-
|
|
73
|
-
publicUrl: publicUrl_params
|
|
94
|
+
extraQueryParams: extraQueryParamsOrGetter,
|
|
95
|
+
publicUrl: publicUrl_params,
|
|
96
|
+
decodedIdTokenSchema
|
|
74
97
|
} = params;
|
|
75
98
|
|
|
99
|
+
const getExtraQueryParams = (() => {
|
|
100
|
+
if (typeof extraQueryParamsOrGetter === "function") {
|
|
101
|
+
return extraQueryParamsOrGetter;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (extraQueryParamsOrGetter !== undefined) {
|
|
105
|
+
return () => extraQueryParamsOrGetter;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return undefined;
|
|
109
|
+
})();
|
|
110
|
+
|
|
76
111
|
const publicUrl = (() => {
|
|
77
112
|
if (publicUrl_params === undefined) {
|
|
78
113
|
return window.location.origin;
|
|
@@ -88,7 +123,7 @@ export async function createOidc(params: {
|
|
|
88
123
|
const configHash = fnv1aHashToHex(`${issuerUri} ${clientId}`);
|
|
89
124
|
const configHashKey = "configHash";
|
|
90
125
|
|
|
91
|
-
const
|
|
126
|
+
const oidcClientTsUserManager = new OidcClientTsUserManager({
|
|
92
127
|
"authority": issuerUri,
|
|
93
128
|
"client_id": clientId,
|
|
94
129
|
"redirect_uri": "" /* provided when calling login */,
|
|
@@ -181,14 +216,14 @@ export async function createOidc(params: {
|
|
|
181
216
|
document.addEventListener("visibilitychange", callback);
|
|
182
217
|
}
|
|
183
218
|
|
|
184
|
-
await
|
|
219
|
+
await oidcClientTsUserManager.signinRedirect({
|
|
185
220
|
redirect_uri,
|
|
186
221
|
"redirectMethod": doesCurrentHrefRequiresAuth ? "replace" : "assign"
|
|
187
222
|
});
|
|
188
223
|
return new Promise<never>(() => {});
|
|
189
224
|
};
|
|
190
225
|
|
|
191
|
-
const
|
|
226
|
+
const initialTokens = await (async function getUser() {
|
|
192
227
|
read_successful_login_query_params: {
|
|
193
228
|
let url = window.location.href;
|
|
194
229
|
|
|
@@ -233,33 +268,33 @@ export async function createOidc(params: {
|
|
|
233
268
|
|
|
234
269
|
window.history.pushState(null, "", url);
|
|
235
270
|
|
|
236
|
-
let
|
|
271
|
+
let oidcClientTsUser: OidcClientTsUser | undefined = undefined;
|
|
237
272
|
|
|
238
273
|
try {
|
|
239
|
-
|
|
274
|
+
oidcClientTsUser = await oidcClientTsUserManager.signinRedirectCallback(loginSuccessUrl);
|
|
240
275
|
} catch {
|
|
241
276
|
//NOTE: The user has likely pressed the back button just after logging in.
|
|
242
277
|
return undefined;
|
|
243
278
|
}
|
|
244
279
|
|
|
245
|
-
return
|
|
280
|
+
return oidcClientTsUser;
|
|
246
281
|
}
|
|
247
282
|
|
|
248
283
|
restore_from_session: {
|
|
249
|
-
const
|
|
284
|
+
const oidcClientTsUser = await oidcClientTsUserManager.getUser();
|
|
250
285
|
|
|
251
|
-
if (
|
|
286
|
+
if (oidcClientTsUser === null) {
|
|
252
287
|
break restore_from_session;
|
|
253
288
|
}
|
|
254
289
|
|
|
255
290
|
// The server might have restarted and the session might have been lost.
|
|
256
291
|
try {
|
|
257
|
-
await
|
|
292
|
+
await oidcClientTsUserManager.signinSilent();
|
|
258
293
|
} catch {
|
|
259
294
|
return undefined;
|
|
260
295
|
}
|
|
261
296
|
|
|
262
|
-
return
|
|
297
|
+
return oidcClientTsUser;
|
|
263
298
|
}
|
|
264
299
|
|
|
265
300
|
restore_from_http_only_cookie: {
|
|
@@ -334,7 +369,7 @@ export async function createOidc(params: {
|
|
|
334
369
|
|
|
335
370
|
window.addEventListener("message", listener, false);
|
|
336
371
|
|
|
337
|
-
|
|
372
|
+
oidcClientTsUserManager
|
|
338
373
|
.signinSilent({ "silentRequestTimeoutInSeconds": timeoutDelayMs / 1000 })
|
|
339
374
|
.catch(() => {
|
|
340
375
|
/* error expected */
|
|
@@ -346,19 +381,24 @@ export async function createOidc(params: {
|
|
|
346
381
|
break restore_from_http_only_cookie;
|
|
347
382
|
}
|
|
348
383
|
|
|
349
|
-
const
|
|
384
|
+
const oidcClientTsUser = await oidcClientTsUserManager.signinRedirectCallback(
|
|
385
|
+
loginSuccessUrl
|
|
386
|
+
);
|
|
350
387
|
|
|
351
|
-
return
|
|
388
|
+
return oidcClientTsUser;
|
|
352
389
|
}
|
|
353
390
|
|
|
354
391
|
return undefined;
|
|
355
392
|
})().then(
|
|
356
|
-
|
|
357
|
-
if (
|
|
393
|
+
oidcClientTsUser => {
|
|
394
|
+
if (oidcClientTsUser === undefined) {
|
|
358
395
|
return undefined;
|
|
359
396
|
}
|
|
360
397
|
|
|
361
|
-
const tokens =
|
|
398
|
+
const tokens = oidcClientTsUserToTokens({
|
|
399
|
+
oidcClientTsUser,
|
|
400
|
+
decodedIdTokenSchema
|
|
401
|
+
});
|
|
362
402
|
|
|
363
403
|
if (tokens.refreshTokenExpirationTime < tokens.accessTokenExpirationTime) {
|
|
364
404
|
console.warn(
|
|
@@ -385,8 +425,8 @@ export async function createOidc(params: {
|
|
|
385
425
|
}
|
|
386
426
|
};
|
|
387
427
|
|
|
388
|
-
if (
|
|
389
|
-
const error =
|
|
428
|
+
if (initialTokens instanceof Error) {
|
|
429
|
+
const error = initialTokens;
|
|
390
430
|
|
|
391
431
|
console.error(`The OIDC server is down or misconfigured: ${error.message}`);
|
|
392
432
|
|
|
@@ -400,7 +440,7 @@ export async function createOidc(params: {
|
|
|
400
440
|
});
|
|
401
441
|
}
|
|
402
442
|
|
|
403
|
-
if (
|
|
443
|
+
if (initialTokens === undefined) {
|
|
404
444
|
return id<Oidc.NotLoggedIn>({
|
|
405
445
|
...common,
|
|
406
446
|
"isUserLoggedIn": false,
|
|
@@ -408,20 +448,16 @@ export async function createOidc(params: {
|
|
|
408
448
|
});
|
|
409
449
|
}
|
|
410
450
|
|
|
451
|
+
let currentTokens = initialTokens;
|
|
452
|
+
|
|
411
453
|
const onTokenChanges = new Set<() => void>();
|
|
412
454
|
|
|
413
|
-
const oidc = id<Oidc.LoggedIn
|
|
455
|
+
const oidc = id<Oidc.LoggedIn<DecodedIdToken>>({
|
|
414
456
|
...common,
|
|
415
457
|
"isUserLoggedIn": true,
|
|
416
|
-
"getTokens": () =>
|
|
417
|
-
"accessToken": currentTokens.accessToken,
|
|
418
|
-
"idToken": currentTokens.idToken,
|
|
419
|
-
"refreshToken": currentTokens.refreshToken,
|
|
420
|
-
"refreshTokenExpirationTime": currentTokens.refreshTokenExpirationTime,
|
|
421
|
-
"accessTokenExpirationTime": currentTokens.accessTokenExpirationTime
|
|
422
|
-
}),
|
|
458
|
+
"getTokens": () => currentTokens,
|
|
423
459
|
"logout": async params => {
|
|
424
|
-
await
|
|
460
|
+
await oidcClientTsUserManager.signoutRedirect({
|
|
425
461
|
"post_logout_redirect_uri": (() => {
|
|
426
462
|
switch (params.redirectTo) {
|
|
427
463
|
case "current page":
|
|
@@ -437,11 +473,24 @@ export async function createOidc(params: {
|
|
|
437
473
|
return new Promise<never>(() => {});
|
|
438
474
|
},
|
|
439
475
|
"renewTokens": async () => {
|
|
440
|
-
const
|
|
476
|
+
const oidcClientTsUser = await oidcClientTsUserManager.signinSilent();
|
|
477
|
+
|
|
478
|
+
assert(oidcClientTsUser !== null);
|
|
441
479
|
|
|
442
|
-
|
|
480
|
+
const decodedIdTokenPropertyDescriptor = Object.getOwnPropertyDescriptor(
|
|
481
|
+
currentTokens,
|
|
482
|
+
"decodedIdToken"
|
|
483
|
+
);
|
|
443
484
|
|
|
444
|
-
|
|
485
|
+
assert(decodedIdTokenPropertyDescriptor !== undefined);
|
|
486
|
+
|
|
487
|
+
currentTokens = oidcClientTsUserToTokens({
|
|
488
|
+
oidcClientTsUser,
|
|
489
|
+
decodedIdTokenSchema
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// NOTE: We do that to preserve the cache and the object reference.
|
|
493
|
+
Object.defineProperty(currentTokens, "decodedIdToken", decodedIdTokenPropertyDescriptor);
|
|
445
494
|
|
|
446
495
|
onTokenChanges.forEach(onTokenChange => onTokenChange());
|
|
447
496
|
},
|
|
@@ -475,12 +524,17 @@ export async function createOidc(params: {
|
|
|
475
524
|
return oidc;
|
|
476
525
|
}
|
|
477
526
|
|
|
478
|
-
function
|
|
479
|
-
|
|
527
|
+
function oidcClientTsUserToTokens<DecodedIdToken extends Record<string, unknown>>(params: {
|
|
528
|
+
oidcClientTsUser: OidcClientTsUser;
|
|
529
|
+
decodedIdTokenSchema?: { parse: (data: unknown) => DecodedIdToken };
|
|
530
|
+
}): Oidc.Tokens<DecodedIdToken> {
|
|
531
|
+
const { oidcClientTsUser, decodedIdTokenSchema } = params;
|
|
532
|
+
|
|
533
|
+
const accessToken = oidcClientTsUser.access_token;
|
|
480
534
|
|
|
481
535
|
const accessTokenExpirationTime = (() => {
|
|
482
536
|
read_from_metadata: {
|
|
483
|
-
const { expires_at } =
|
|
537
|
+
const { expires_at } = oidcClientTsUser;
|
|
484
538
|
|
|
485
539
|
if (expires_at === undefined) {
|
|
486
540
|
break read_from_metadata;
|
|
@@ -502,7 +556,7 @@ function userToTokens(user: User): Oidc.Tokens {
|
|
|
502
556
|
assert(false, "Failed to get access token expiration time");
|
|
503
557
|
})();
|
|
504
558
|
|
|
505
|
-
const refreshToken =
|
|
559
|
+
const refreshToken = oidcClientTsUser.refresh_token;
|
|
506
560
|
|
|
507
561
|
assert(refreshToken !== undefined, "No refresh token provided by the oidc server");
|
|
508
562
|
|
|
@@ -520,15 +574,48 @@ function userToTokens(user: User): Oidc.Tokens {
|
|
|
520
574
|
assert(false, "Failed to get refresh token expiration time");
|
|
521
575
|
})();
|
|
522
576
|
|
|
523
|
-
const idToken =
|
|
577
|
+
const idToken = oidcClientTsUser.id_token;
|
|
524
578
|
|
|
525
579
|
assert(idToken !== undefined, "No id token provided by the oidc server");
|
|
526
580
|
|
|
527
|
-
|
|
581
|
+
const tokens: Oidc.Tokens<DecodedIdToken> = {
|
|
528
582
|
accessToken,
|
|
529
583
|
accessTokenExpirationTime,
|
|
530
584
|
refreshToken,
|
|
531
585
|
refreshTokenExpirationTime,
|
|
532
|
-
idToken
|
|
586
|
+
idToken,
|
|
587
|
+
"decodedIdToken": null as any
|
|
533
588
|
};
|
|
589
|
+
|
|
590
|
+
let cache:
|
|
591
|
+
| {
|
|
592
|
+
idToken: string;
|
|
593
|
+
decodedIdToken: DecodedIdToken;
|
|
594
|
+
}
|
|
595
|
+
| undefined = undefined;
|
|
596
|
+
|
|
597
|
+
Object.defineProperty(tokens, "decodedIdToken", {
|
|
598
|
+
"get": function (this: Oidc.Tokens<DecodedIdToken>) {
|
|
599
|
+
if (cache !== undefined && cache.idToken === this.idToken) {
|
|
600
|
+
return cache.decodedIdToken;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
let decodedIdToken = decodeJwt(this.idToken) as DecodedIdToken;
|
|
604
|
+
|
|
605
|
+
if (decodedIdTokenSchema !== undefined) {
|
|
606
|
+
decodedIdToken = decodedIdTokenSchema.parse(decodedIdToken);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
cache = {
|
|
610
|
+
"idToken": this.idToken,
|
|
611
|
+
decodedIdToken
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
return decodedIdToken;
|
|
615
|
+
},
|
|
616
|
+
"configurable": true,
|
|
617
|
+
"enumerable": true
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
return tokens;
|
|
534
621
|
}
|