@crossauth/frontend 0.0.2

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/dist/index.js ADDED
@@ -0,0 +1,3005 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __typeError = (msg) => {
3
+ throw TypeError(msg);
4
+ };
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
8
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
+ var _accessToken, _refreshToken, _idTokenPayload, _accessTokenPayload, _refreshTokenPayload, _client_id, _client_secret;
12
+ var fe = Object.defineProperty;
13
+ var G = (e) => {
14
+ throw TypeError(e);
15
+ };
16
+ var pe = (e, t, r) => t in e ? fe(e, t, { enumerable: true, configurable: true, writable: true, value: r }) : e[t] = r;
17
+ var a = (e, t, r) => pe(e, typeof t != "symbol" ? t + "" : t, r), Y = (e, t, r) => t.has(e) || G("Cannot " + r);
18
+ var u = (e, t, r) => (Y(e, t, "read from private field"), r ? r.call(e) : t.get(e)), O = (e, t, r) => t.has(e) ? G("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, r), _ = (e, t, r, n) => (Y(e, t, "write to private field"), t.set(e, r), r);
19
+ class k {
20
+ }
21
+ a(k, "active", "active"), /** Deactivated account. User cannot log in */
22
+ a(k, "disabled", "disabled"), /** Two factor authentication has been actived for this user
23
+ * but has not yet been configured. Once a user logs in,
24
+ * they will be directed to a page to configure 2FA and will
25
+ * not be able to do anything else (that requires login) until
26
+ * they have done so.
27
+ */
28
+ a(k, "awaitingTwoFactorSetup", "awaitingtwofactorsetup"), /** Email verification has been turned on but user has not
29
+ * verified his or her email address. Cannot log on until it has
30
+ * been verified.
31
+ */
32
+ a(k, "awaitingEmailVerification", "awaitingemailverification"), /**
33
+ * If the state is set to this, the user may not access any
34
+ * login-required functions unless he or she has changed their password.
35
+ *
36
+ * Upon login, the user is redirected to the change password page.
37
+ */
38
+ a(k, "passwordChangeNeeded", "passwordchangeneeded"), /**
39
+ * If the state is set to this, the user may not access any
40
+ * login-required functions unless he or she has reset their password.
41
+ *
42
+ * Upon login, the user is redirected to the reset password page.
43
+ */
44
+ a(k, "passwordResetNeeded", "passwordresetneeded"), /**
45
+ * If the state is set to this, the user may not access any
46
+ * login-required functions unless he or she has reset their second
47
+ * factor configuration.
48
+ *
49
+ * Upon login, the user is redirected to the 2FA configuration page.
50
+ *
51
+ * If you create a user and 2FA is mandatory, you can set state to
52
+ * this value and the user will then be prompted to configure 2FA
53
+ * upon login.
54
+ */
55
+ a(k, "factor2ResetNeeded", "factor2resetneeded"), /**
56
+ * If the state is set to this, the user may not access any
57
+ * login-required functions unless he or she has reset their password
58
+ * and then resets factor2.
59
+ *
60
+ * Upon login, the user is redirected to the reset password page.
61
+ */
62
+ a(k, "passwordAndFactor2ResetNeeded", "passwordandfactor2resetneeded");
63
+ class C {
64
+ }
65
+ a(C, "session", "s:"), /** Password Reset Token */
66
+ a(C, "passwordResetToken", "p:"), /** Email verification token */
67
+ a(C, "emailVerificationToken", "e:"), /** API key */
68
+ a(C, "apiKey", "api:"), /** OAuth authorization code */
69
+ a(C, "authorizationCode", "authz:"), /** OAuth access token */
70
+ a(C, "accessToken", "access:"), /** OAuth refresh token */
71
+ a(C, "refreshToken", "refresh:"), /** OAuth MFA key (used by the password MFA flow) */
72
+ a(C, "mfaToken", "omfa:"), /** Device code device code */
73
+ a(C, "deviceCode", "dc:"), /** Device code flow user code */
74
+ a(C, "userCode", "uc:");
75
+ var y = /* @__PURE__ */ ((e) => (e[e.UserNotExist = 0] = "UserNotExist", e[e.PasswordInvalid = 1] = "PasswordInvalid", e[e.EmailNotExist = 2] = "EmailNotExist", e[e.UsernameOrPasswordInvalid = 3] = "UsernameOrPasswordInvalid", e[e.InvalidClientId = 4] = "InvalidClientId", e[e.ClientExists = 5] = "ClientExists", e[e.InvalidClientSecret = 6] = "InvalidClientSecret", e[e.InvalidClientIdOrSecret = 7] = "InvalidClientIdOrSecret", e[e.InvalidRedirectUri = 8] = "InvalidRedirectUri", e[e.InvalidOAuthFlow = 9] = "InvalidOAuthFlow", e[e.UserNotActive = 10] = "UserNotActive", e[e.EmailNotVerified = 11] = "EmailNotVerified", e[e.TwoFactorIncomplete = 12] = "TwoFactorIncomplete", e[e.Unauthorized = 13] = "Unauthorized", e[e.UnauthorizedClient = 14] = "UnauthorizedClient", e[e.InvalidScope = 15] = "InvalidScope", e[e.InsufficientScope = 16] = "InsufficientScope", e[e.InsufficientPriviledges = 17] = "InsufficientPriviledges", e[e.Forbidden = 18] = "Forbidden", e[e.InvalidKey = 19] = "InvalidKey", e[e.InvalidCsrf = 20] = "InvalidCsrf", e[e.InvalidSession = 21] = "InvalidSession", e[e.Expired = 22] = "Expired", e[e.Connection = 23] = "Connection", e[e.InvalidHash = 24] = "InvalidHash", e[e.UnsupportedAlgorithm = 25] = "UnsupportedAlgorithm", e[e.KeyExists = 26] = "KeyExists", e[e.PasswordChangeNeeded = 27] = "PasswordChangeNeeded", e[e.PasswordResetNeeded = 28] = "PasswordResetNeeded", e[e.Factor2ResetNeeded = 29] = "Factor2ResetNeeded", e[e.Configuration = 30] = "Configuration", e[e.InvalidEmail = 31] = "InvalidEmail", e[e.InvalidPhoneNumber = 32] = "InvalidPhoneNumber", e[e.InvalidUsername = 33] = "InvalidUsername", e[e.PasswordMatch = 34] = "PasswordMatch", e[e.InvalidToken = 35] = "InvalidToken", e[e.MfaRequired = 36] = "MfaRequired", e[e.PasswordFormat = 37] = "PasswordFormat", e[e.DataFormat = 38] = "DataFormat", e[e.FetchError = 39] = "FetchError", e[e.UserExists = 40] = "UserExists", e[e.FormEntry = 41] = "FormEntry", e[e.BadRequest = 42] = "BadRequest", e[e.AuthorizationPending = 43] = "AuthorizationPending", e[e.SlowDown = 44] = "SlowDown", e[e.ExpiredToken = 45] = "ExpiredToken", e[e.ConstraintViolation = 46] = "ConstraintViolation", e[e.NotImplemented = 47] = "NotImplemented", e[e.UnknownError = 48] = "UnknownError", e))(y || {});
76
+ class g extends Error {
77
+ /**
78
+ * Creates a new error to throw,
79
+ *
80
+ * @param code describes the type of error
81
+ * @param message if provided, this error will display. Otherwise a default one for the error code will be used.
82
+ */
83
+ constructor(r, n = void 0) {
84
+ let i, s = 500;
85
+ r == 0 ? (i = "User does not exist", s = 401) : r == 1 ? (i = "Password doesn't match", s = 401) : r == 3 ? (i = "Username or password incorrect", s = 401) : r == 4 ? (i = "Client id is invalid", s = 401) : r == 5 ? (i = "Client ID or name already exists", s = 500) : r == 6 ? (i = "Client secret is invalid", s = 401) : r == 7 ? (i = "Client id or secret is invalid", s = 401) : r == 8 ? (i = "Redirect Uri is not registered", s = 401) : r == 9 ? (i = "Invalid OAuth flow type", s = 500) : r == 2 ? (i = "No user exists with that email address", s = 401) : r == 10 ? (i = "Account is not active", s = 403) : r == 33 ? (i = "Username is not in an allowed format", s = 400) : r == 31 ? (i = "Email is not in an allowed format", s = 400) : r == 32 ? (i = "Phone number is not in an allowed format", s = 400) : r == 11 ? (i = "Email address has not been verified", s = 403) : r == 12 ? (i = "Two-factor setup is not complete", s = 403) : r == 13 ? (i = "Not authorized", s = 401) : r == 14 ? (i = "Client not authorized", s = 401) : r == 15 ? (i = "Invalid scope", s = 403) : r == 16 ? (i = "Insufficient scope", s = 403) : r == 23 ? i = "Connection failure" : r == 22 ? (i = "Token has expired", s = 401) : r == 24 ? i = "Hash is not in a valid format" : r == 19 ? (i = "Key is invalid", s = 401) : r == 18 ? (i = "You do not have permission to access this resource", s = 403) : r == 17 ? (i = "You do not have the right privileges to access this resource", s = 401) : r == 20 ? (i = "CSRF token is invalid", s = 401) : r == 21 ? (i = "Session cookie is invalid", s = 401) : r == 25 ? i = "Algorithm not supported" : r == 26 ? i = "Attempt to create a key that already exists" : r == 27 ? (i = "User must change password", s = 403) : r == 28 ? (i = "User must reset password", s = 403) : r == 29 ? (i = "User must reset 2FA", s = 403) : r == 30 ? i = "There was an error in the configuration" : r == 34 ? (i = "Passwords do not match", s = 401) : r == 35 ? (i = "Token is not valid", s = 401) : r == 36 ? (i = "MFA is required", s = 401) : r == 37 ? (i = "Password format was incorrect", s = 401) : r == 40 ? (i = "User already exists", s = 400) : r == 42 ? (i = "The request is invalid", s = 400) : r == 38 ? (i = "Session data has unexpected format", s = 500) : r == 39 ? (i = "Couldn't execute a fetch", s = 500) : r == 43 ? (i = "Waiting for authorization", s = 200) : r == 44 ? (i = "Slow polling down by 5 seconds", s = 200) : r == 45 ? (i = "Token has expired", s = 401) : r == 46 ? (i = "Database update/insert caused a constraint violation", s = 500) : r == 47 ? (i = "This method has not been implemented", s = 500) : (i = "Unknown error", s = 500), n != null && !Array.isArray(n) ? i = n : Array.isArray(n) && (i = n.join(". "));
86
+ super(i);
87
+ a(this, "isCrossauthError", true);
88
+ a(this, "httpStatus");
89
+ a(this, "code");
90
+ a(this, "codeName");
91
+ a(this, "messages");
92
+ this.code = r, this.codeName = y[r], this.httpStatus = s, this.name = "CrossauthError", Array.isArray(n) ? this.messages = n : this.messages = [i], Object.setPrototypeOf(this, g.prototype);
93
+ }
94
+ /**
95
+ * OAuth defines certain error types. To convert the error in an OAuth
96
+ * response into a CrossauthError object, call this function.
97
+ *
98
+ * @param error as returned by an OAuth call (converted to an {@link @crossauth/common!ErrorCode}).
99
+ * @param error_description as returned by an OAuth call (put in the `message`)
100
+ * @returns a `CrossauthError` instance.
101
+ */
102
+ static fromOAuthError(r, n) {
103
+ let i;
104
+ switch (r) {
105
+ case "invalid_request":
106
+ i = 42;
107
+ break;
108
+ case "unauthorized_client":
109
+ i = 14;
110
+ break;
111
+ case "access_denied":
112
+ i = 13;
113
+ break;
114
+ case "unsupported_response_type":
115
+ i = 42;
116
+ break;
117
+ case "invalid_scope":
118
+ i = 15;
119
+ break;
120
+ case "server_error":
121
+ i = 48;
122
+ break;
123
+ case "temporarily_unavailable":
124
+ i = 23;
125
+ break;
126
+ case "invalid_token":
127
+ i = 35;
128
+ break;
129
+ case "expired_token":
130
+ i = 45;
131
+ break;
132
+ case "insufficient_scope":
133
+ i = 35;
134
+ break;
135
+ case "mfa_required":
136
+ i = 36;
137
+ break;
138
+ case "authorization_pending":
139
+ i = 43;
140
+ break;
141
+ case "slow_down":
142
+ i = 44;
143
+ break;
144
+ default:
145
+ i = 48;
146
+ }
147
+ return new g(i, n);
148
+ }
149
+ get oauthErrorCode() {
150
+ switch (this.code) {
151
+ case 42:
152
+ return "invalid_request";
153
+ case 14:
154
+ return "unauthorized_client";
155
+ case 13:
156
+ return "access_denied";
157
+ case 15:
158
+ return "invalid_scope";
159
+ case 23:
160
+ return "temporarily_unavailable";
161
+ case 35:
162
+ return "invalid_token";
163
+ case 36:
164
+ return "mfa_required";
165
+ case 43:
166
+ return "authorization_pending";
167
+ case 44:
168
+ return "slow_down";
169
+ case 45:
170
+ return "expired_token";
171
+ case 22:
172
+ return "expired_token";
173
+ default:
174
+ return "server_error";
175
+ }
176
+ }
177
+ /**
178
+ * If the passed object is a `CrossauthError` instance, simply returns
179
+ * it.
180
+ * If not and it is an object with `errorCode` in it, creates a
181
+ * CrossauthError from that and `errorMessage`, if present.
182
+ * Otherwise creates a `CrossauthError` object with {@link @crossauth/common!ErrorCode}
183
+ * of `Unknown` from it, setting the `message` if possible.
184
+ *
185
+ * @param e the error to convert.
186
+ * @returns a `CrossauthError` instance.
187
+ */
188
+ static asCrossauthError(r, n) {
189
+ if (r instanceof Error)
190
+ return "isCrossauthError" in r ? r : new g(48, r.message);
191
+ if ("errorCode" in r) {
192
+ let s = 48;
193
+ try {
194
+ s = Number(r.errorCode) ?? 48;
195
+ } catch {
196
+ }
197
+ let o = n ?? y[s];
198
+ return "errorMessage" in r ? o = r.errorMessage : "message" in r && (o = r.message), new g(s, o);
199
+ }
200
+ let i = n ?? y[
201
+ 48
202
+ /* UnknownError */
203
+ ];
204
+ return "message" in r && (i = r.message), new g(48, i);
205
+ }
206
+ }
207
+ const m = class m2 {
208
+ /**
209
+ * Create a logger with the given level
210
+ * @param level the level to report to
211
+ */
212
+ constructor(t) {
213
+ a(this, "level");
214
+ if (t) this.level = t;
215
+ else if (typeof process < "u" && "CROSSAUTH_LOG_LEVEL" in process.env) {
216
+ const r = (process.env.CROSSAUTH_LOG_LEVEL ?? "ERROR").toUpperCase();
217
+ m2.levelName.includes(r) ? this.level = m2.levelName.indexOf(r) : this.level = m2.Error;
218
+ } else
219
+ this.level = m2.Error;
220
+ }
221
+ /**
222
+ * Return the singleton instance of the logger.
223
+ * @returns the logger
224
+ */
225
+ static get logger() {
226
+ return globalThis.crossauthLogger;
227
+ }
228
+ setLevel(t) {
229
+ this.level = t;
230
+ }
231
+ log(t, r) {
232
+ t <= this.level && (typeof r == "string" ? console.log("Crossauth " + m2.levelName[t] + " " + (/* @__PURE__ */ new Date()).toISOString(), r) : console.log(JSON.stringify({ level: m2.levelName[t], time: (/* @__PURE__ */ new Date()).toISOString(), ...r })));
233
+ }
234
+ /**
235
+ * Report an error
236
+ * @param output object to output
237
+ */
238
+ error(t) {
239
+ this.log(m2.Error, t);
240
+ }
241
+ /**
242
+ * Report an warning
243
+ * @param output object to output
244
+ */
245
+ warn(t) {
246
+ this.log(m2.Warn, t);
247
+ }
248
+ /**
249
+ * Report information
250
+ * @param output object to output
251
+ */
252
+ info(t) {
253
+ this.log(m2.Info, t);
254
+ }
255
+ /**
256
+ * Print a debugging message
257
+ * @param output object to output
258
+ */
259
+ debug(t) {
260
+ this.log(m2.Debug, t);
261
+ }
262
+ /**
263
+ * Override the default logger.
264
+ *
265
+ * The only requirement is that the logger has the functions `error()`, `warn()`, `info()` and `debug()`.
266
+ * These functions must accept either an object or a string. If they can only accept a string,
267
+ * set `acceptsJson` to false.
268
+ *
269
+ * @param logger a new logger instance of any supported class
270
+ * @param acceptsJson set this to false if the logger can only take strings.
271
+ */
272
+ static setLogger(t, r) {
273
+ globalThis.crossauthLogger = t, globalThis.crossauthLoggerAcceptsJson = r;
274
+ }
275
+ };
276
+ a(m, "None", 0), /** Only log errors */
277
+ a(m, "Error", 1), /** Log errors and warning */
278
+ a(m, "Warn", 2), /** Log errors, warnings and info messages */
279
+ a(m, "Info", 3), /** Log everything */
280
+ a(m, "Debug", 4), a(m, "levelName", ["NONE", "ERROR", "WARN", "INFO", "DEBUG"]);
281
+ let d = m;
282
+ function h(e) {
283
+ let t;
284
+ typeof e == "object" && "err" in e && typeof e.err == "object" && (t = e.err.stack);
285
+ try {
286
+ typeof e == "object" && "err" in e && typeof e.err == "object" && e.err && "message" in e.err && !("msg" in e) && (e.msg = e.err.message);
287
+ } catch {
288
+ }
289
+ try {
290
+ typeof e == "object" && "err" in e && typeof e.err == "object" && (e.err = { ...e.err, stack: t });
291
+ } catch {
292
+ }
293
+ try {
294
+ typeof e == "object" && "err" in e && !("msg" in e) && (e.msg = e.msg = "An unknown error occurred");
295
+ } catch {
296
+ }
297
+ try {
298
+ typeof e == "object" && "cerr" in e && "isCrossauthError" in e.cerr && e.cerr && (e.errorCode = e.cerr.code, e.errorCodeName = e.cerr.codeName, e.httpStatus = e.cerr.httpStatus, "msg" in e || (e.msg = e.cerr.message), delete e.cerr);
299
+ } catch {
300
+ }
301
+ return typeof e == "string" || globalThis.crossauthLoggerAcceptsJson ? e : JSON.stringify(e);
302
+ }
303
+ globalThis.crossauthLogger = new d(d.None);
304
+ globalThis.crossauthLoggerAcceptsJson = true;
305
+ const te = {
306
+ issuer: "",
307
+ authorization_endpoint: "",
308
+ token_endpoint: "",
309
+ jwks_uri: "",
310
+ response_types_supported: [],
311
+ subject_types_supported: [],
312
+ response_modes_supported: ["query", "fragment"],
313
+ grant_types_supported: ["authorization_code", "implicit"],
314
+ id_token_signing_alg_values_supported: [],
315
+ claim_types_supported: ["normal"],
316
+ claims_parameter_supported: false,
317
+ request_parameter_supported: false,
318
+ request_uri_parameter_supported: true,
319
+ require_request_uri_registration: false
320
+ }, F = crypto, re = (e) => e instanceof CryptoKey, H = new TextEncoder(), z = new TextDecoder();
321
+ function ge(...e) {
322
+ const t = e.reduce((i, { length: s }) => i + s, 0), r = new Uint8Array(t);
323
+ let n = 0;
324
+ for (const i of e)
325
+ r.set(i, n), n += i.length;
326
+ return r;
327
+ }
328
+ const ye = (e) => {
329
+ const t = atob(e), r = new Uint8Array(t.length);
330
+ for (let n = 0; n < t.length; n++)
331
+ r[n] = t.charCodeAt(n);
332
+ return r;
333
+ }, K = (e) => {
334
+ let t = e;
335
+ t instanceof Uint8Array && (t = z.decode(t)), t = t.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "");
336
+ try {
337
+ return ye(t);
338
+ } catch {
339
+ throw new TypeError("The input to be decoded is not correctly encoded.");
340
+ }
341
+ };
342
+ class $ extends Error {
343
+ static get code() {
344
+ return "ERR_JOSE_GENERIC";
345
+ }
346
+ constructor(t) {
347
+ var r;
348
+ super(t), this.code = "ERR_JOSE_GENERIC", this.name = this.constructor.name, (r = Error.captureStackTrace) == null || r.call(Error, this, this.constructor);
349
+ }
350
+ }
351
+ class b extends $ {
352
+ constructor() {
353
+ super(...arguments), this.code = "ERR_JOSE_NOT_SUPPORTED";
354
+ }
355
+ static get code() {
356
+ return "ERR_JOSE_NOT_SUPPORTED";
357
+ }
358
+ }
359
+ class v extends $ {
360
+ constructor() {
361
+ super(...arguments), this.code = "ERR_JWS_INVALID";
362
+ }
363
+ static get code() {
364
+ return "ERR_JWS_INVALID";
365
+ }
366
+ }
367
+ class E extends $ {
368
+ constructor() {
369
+ super(...arguments), this.code = "ERR_JWT_INVALID";
370
+ }
371
+ static get code() {
372
+ return "ERR_JWT_INVALID";
373
+ }
374
+ }
375
+ class me extends $ {
376
+ constructor() {
377
+ super(...arguments), this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED", this.message = "signature verification failed";
378
+ }
379
+ static get code() {
380
+ return "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
381
+ }
382
+ }
383
+ function A(e, t = "algorithm.name") {
384
+ return new TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`);
385
+ }
386
+ function J(e, t) {
387
+ return e.name === t;
388
+ }
389
+ function L(e) {
390
+ return parseInt(e.name.slice(4), 10);
391
+ }
392
+ function we(e) {
393
+ switch (e) {
394
+ case "ES256":
395
+ return "P-256";
396
+ case "ES384":
397
+ return "P-384";
398
+ case "ES512":
399
+ return "P-521";
400
+ default:
401
+ throw new Error("unreachable");
402
+ }
403
+ }
404
+ function ve(e, t) {
405
+ if (t.length && !t.some((r) => e.usages.includes(r))) {
406
+ let r = "CryptoKey does not support this operation, its usages must include ";
407
+ if (t.length > 2) {
408
+ const n = t.pop();
409
+ r += `one of ${t.join(", ")}, or ${n}.`;
410
+ } else t.length === 2 ? r += `one of ${t[0]} or ${t[1]}.` : r += `${t[0]}.`;
411
+ throw new TypeError(r);
412
+ }
413
+ }
414
+ function Se(e, t, ...r) {
415
+ switch (t) {
416
+ case "HS256":
417
+ case "HS384":
418
+ case "HS512": {
419
+ if (!J(e.algorithm, "HMAC"))
420
+ throw A("HMAC");
421
+ const n = parseInt(t.slice(2), 10);
422
+ if (L(e.algorithm.hash) !== n)
423
+ throw A(`SHA-${n}`, "algorithm.hash");
424
+ break;
425
+ }
426
+ case "RS256":
427
+ case "RS384":
428
+ case "RS512": {
429
+ if (!J(e.algorithm, "RSASSA-PKCS1-v1_5"))
430
+ throw A("RSASSA-PKCS1-v1_5");
431
+ const n = parseInt(t.slice(2), 10);
432
+ if (L(e.algorithm.hash) !== n)
433
+ throw A(`SHA-${n}`, "algorithm.hash");
434
+ break;
435
+ }
436
+ case "PS256":
437
+ case "PS384":
438
+ case "PS512": {
439
+ if (!J(e.algorithm, "RSA-PSS"))
440
+ throw A("RSA-PSS");
441
+ const n = parseInt(t.slice(2), 10);
442
+ if (L(e.algorithm.hash) !== n)
443
+ throw A(`SHA-${n}`, "algorithm.hash");
444
+ break;
445
+ }
446
+ case "EdDSA": {
447
+ if (e.algorithm.name !== "Ed25519" && e.algorithm.name !== "Ed448")
448
+ throw A("Ed25519 or Ed448");
449
+ break;
450
+ }
451
+ case "ES256":
452
+ case "ES384":
453
+ case "ES512": {
454
+ if (!J(e.algorithm, "ECDSA"))
455
+ throw A("ECDSA");
456
+ const n = we(t);
457
+ if (e.algorithm.namedCurve !== n)
458
+ throw A(n, "algorithm.namedCurve");
459
+ break;
460
+ }
461
+ default:
462
+ throw new TypeError("CryptoKey does not support this operation");
463
+ }
464
+ ve(e, r);
465
+ }
466
+ function ie(e, t, ...r) {
467
+ var n;
468
+ if (r.length > 2) {
469
+ const i = r.pop();
470
+ e += `one of type ${r.join(", ")}, or ${i}.`;
471
+ } else r.length === 2 ? e += `one of type ${r[0]} or ${r[1]}.` : e += `of type ${r[0]}.`;
472
+ return t == null ? e += ` Received ${t}` : typeof t == "function" && t.name ? e += ` Received function ${t.name}` : typeof t == "object" && t != null && (n = t.constructor) != null && n.name && (e += ` Received an instance of ${t.constructor.name}`), e;
473
+ }
474
+ const X = (e, ...t) => ie("Key must be ", e, ...t);
475
+ function ne(e, t, ...r) {
476
+ return ie(`Key for the ${e} algorithm must be `, t, ...r);
477
+ }
478
+ const se = (e) => re(e) ? true : (e == null ? void 0 : e[Symbol.toStringTag]) === "KeyObject", M = ["CryptoKey"], _e = (...e) => {
479
+ const t = e.filter(Boolean);
480
+ if (t.length === 0 || t.length === 1)
481
+ return true;
482
+ let r;
483
+ for (const n of t) {
484
+ const i = Object.keys(n);
485
+ if (!r || r.size === 0) {
486
+ r = new Set(i);
487
+ continue;
488
+ }
489
+ for (const s of i) {
490
+ if (r.has(s))
491
+ return false;
492
+ r.add(s);
493
+ }
494
+ }
495
+ return true;
496
+ };
497
+ function Ce(e) {
498
+ return typeof e == "object" && e !== null;
499
+ }
500
+ function x(e) {
501
+ if (!Ce(e) || Object.prototype.toString.call(e) !== "[object Object]")
502
+ return false;
503
+ if (Object.getPrototypeOf(e) === null)
504
+ return true;
505
+ let t = e;
506
+ for (; Object.getPrototypeOf(t) !== null; )
507
+ t = Object.getPrototypeOf(t);
508
+ return Object.getPrototypeOf(e) === t;
509
+ }
510
+ const be = (e, t) => {
511
+ if (e.startsWith("RS") || e.startsWith("PS")) {
512
+ const { modulusLength: r } = t.algorithm;
513
+ if (typeof r != "number" || r < 2048)
514
+ throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`);
515
+ }
516
+ };
517
+ function Ae(e) {
518
+ let t, r;
519
+ switch (e.kty) {
520
+ case "RSA": {
521
+ switch (e.alg) {
522
+ case "PS256":
523
+ case "PS384":
524
+ case "PS512":
525
+ t = { name: "RSA-PSS", hash: `SHA-${e.alg.slice(-3)}` }, r = e.d ? ["sign"] : ["verify"];
526
+ break;
527
+ case "RS256":
528
+ case "RS384":
529
+ case "RS512":
530
+ t = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${e.alg.slice(-3)}` }, r = e.d ? ["sign"] : ["verify"];
531
+ break;
532
+ case "RSA-OAEP":
533
+ case "RSA-OAEP-256":
534
+ case "RSA-OAEP-384":
535
+ case "RSA-OAEP-512":
536
+ t = {
537
+ name: "RSA-OAEP",
538
+ hash: `SHA-${parseInt(e.alg.slice(-3), 10) || 1}`
539
+ }, r = e.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
540
+ break;
541
+ default:
542
+ throw new b('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
543
+ }
544
+ break;
545
+ }
546
+ case "EC": {
547
+ switch (e.alg) {
548
+ case "ES256":
549
+ t = { name: "ECDSA", namedCurve: "P-256" }, r = e.d ? ["sign"] : ["verify"];
550
+ break;
551
+ case "ES384":
552
+ t = { name: "ECDSA", namedCurve: "P-384" }, r = e.d ? ["sign"] : ["verify"];
553
+ break;
554
+ case "ES512":
555
+ t = { name: "ECDSA", namedCurve: "P-521" }, r = e.d ? ["sign"] : ["verify"];
556
+ break;
557
+ case "ECDH-ES":
558
+ case "ECDH-ES+A128KW":
559
+ case "ECDH-ES+A192KW":
560
+ case "ECDH-ES+A256KW":
561
+ t = { name: "ECDH", namedCurve: e.crv }, r = e.d ? ["deriveBits"] : [];
562
+ break;
563
+ default:
564
+ throw new b('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
565
+ }
566
+ break;
567
+ }
568
+ case "OKP": {
569
+ switch (e.alg) {
570
+ case "EdDSA":
571
+ t = { name: e.crv }, r = e.d ? ["sign"] : ["verify"];
572
+ break;
573
+ case "ECDH-ES":
574
+ case "ECDH-ES+A128KW":
575
+ case "ECDH-ES+A192KW":
576
+ case "ECDH-ES+A256KW":
577
+ t = { name: e.crv }, r = e.d ? ["deriveBits"] : [];
578
+ break;
579
+ default:
580
+ throw new b('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
581
+ }
582
+ break;
583
+ }
584
+ default:
585
+ throw new b('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
586
+ }
587
+ return { algorithm: t, keyUsages: r };
588
+ }
589
+ const oe = async (e) => {
590
+ if (!e.alg)
591
+ throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
592
+ const { algorithm: t, keyUsages: r } = Ae(e), n = [
593
+ t,
594
+ e.ext ?? false,
595
+ e.key_ops ?? r
596
+ ], i = { ...e };
597
+ return delete i.alg, delete i.use, F.subtle.importKey("jwk", i, ...n);
598
+ }, ae = (e) => K(e);
599
+ let V, j;
600
+ const ce = (e) => (e == null ? void 0 : e[Symbol.toStringTag]) === "KeyObject", de = async (e, t, r, n) => {
601
+ let i = e.get(t);
602
+ if (i != null && i[n])
603
+ return i[n];
604
+ const s = await oe({ ...r, alg: n });
605
+ return i ? i[n] = s : e.set(t, { [n]: s }), s;
606
+ }, Pe = (e, t) => {
607
+ if (ce(e)) {
608
+ let r = e.export({ format: "jwk" });
609
+ return delete r.d, delete r.dp, delete r.dq, delete r.p, delete r.q, delete r.qi, r.k ? ae(r.k) : (j || (j = /* @__PURE__ */ new WeakMap()), de(j, e, r, t));
610
+ }
611
+ return e;
612
+ }, ke = (e, t) => {
613
+ if (ce(e)) {
614
+ let r = e.export({ format: "jwk" });
615
+ return r.k ? ae(r.k) : (V || (V = /* @__PURE__ */ new WeakMap()), de(V, e, r, t));
616
+ }
617
+ return e;
618
+ }, Ie = { normalizePublicKey: Pe, normalizePrivateKey: ke }, I = (e, t, r = 0) => {
619
+ r === 0 && (t.unshift(t.length), t.unshift(6));
620
+ const n = e.indexOf(t[0], r);
621
+ if (n === -1)
622
+ return false;
623
+ const i = e.subarray(n, n + t.length);
624
+ return i.length !== t.length ? false : i.every((s, o) => s === t[o]) || I(e, t, n + 1);
625
+ }, Q = (e) => {
626
+ switch (true) {
627
+ case I(e, [42, 134, 72, 206, 61, 3, 1, 7]):
628
+ return "P-256";
629
+ case I(e, [43, 129, 4, 0, 34]):
630
+ return "P-384";
631
+ case I(e, [43, 129, 4, 0, 35]):
632
+ return "P-521";
633
+ case I(e, [43, 101, 110]):
634
+ return "X25519";
635
+ case I(e, [43, 101, 111]):
636
+ return "X448";
637
+ case I(e, [43, 101, 112]):
638
+ return "Ed25519";
639
+ case I(e, [43, 101, 113]):
640
+ return "Ed448";
641
+ default:
642
+ throw new b("Invalid or unsupported EC Key Curve or OKP Key Sub Type");
643
+ }
644
+ }, le = async (e, t, r, n, i) => {
645
+ let s, o;
646
+ const l = new Uint8Array(atob(r.replace(e, "")).split("").map((p) => p.charCodeAt(0))), f = t === "spki";
647
+ switch (n) {
648
+ case "PS256":
649
+ case "PS384":
650
+ case "PS512":
651
+ s = { name: "RSA-PSS", hash: `SHA-${n.slice(-3)}` }, o = f ? ["verify"] : ["sign"];
652
+ break;
653
+ case "RS256":
654
+ case "RS384":
655
+ case "RS512":
656
+ s = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${n.slice(-3)}` }, o = f ? ["verify"] : ["sign"];
657
+ break;
658
+ case "RSA-OAEP":
659
+ case "RSA-OAEP-256":
660
+ case "RSA-OAEP-384":
661
+ case "RSA-OAEP-512":
662
+ s = {
663
+ name: "RSA-OAEP",
664
+ hash: `SHA-${parseInt(n.slice(-3), 10) || 1}`
665
+ }, o = f ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
666
+ break;
667
+ case "ES256":
668
+ s = { name: "ECDSA", namedCurve: "P-256" }, o = f ? ["verify"] : ["sign"];
669
+ break;
670
+ case "ES384":
671
+ s = { name: "ECDSA", namedCurve: "P-384" }, o = f ? ["verify"] : ["sign"];
672
+ break;
673
+ case "ES512":
674
+ s = { name: "ECDSA", namedCurve: "P-521" }, o = f ? ["verify"] : ["sign"];
675
+ break;
676
+ case "ECDH-ES":
677
+ case "ECDH-ES+A128KW":
678
+ case "ECDH-ES+A192KW":
679
+ case "ECDH-ES+A256KW": {
680
+ const p = Q(l);
681
+ s = p.startsWith("P-") ? { name: "ECDH", namedCurve: p } : { name: p }, o = f ? [] : ["deriveBits"];
682
+ break;
683
+ }
684
+ case "EdDSA":
685
+ s = { name: Q(l) }, o = f ? ["verify"] : ["sign"];
686
+ break;
687
+ default:
688
+ throw new b('Invalid or unsupported "alg" (Algorithm) value');
689
+ }
690
+ return F.subtle.importKey(t, l, s, false, o);
691
+ }, Te = (e, t, r) => le(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g, "pkcs8", e, t), Re = (e, t, r) => le(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", e, t);
692
+ async function Ee(e, t, r) {
693
+ if (typeof e != "string" || e.indexOf("-----BEGIN PUBLIC KEY-----") !== 0)
694
+ throw new TypeError('"spki" must be SPKI formatted string');
695
+ return Re(e, t);
696
+ }
697
+ async function Oe(e, t, r) {
698
+ if (typeof e != "string" || e.indexOf("-----BEGIN PRIVATE KEY-----") !== 0)
699
+ throw new TypeError('"pkcs8" must be PKCS#8 formatted string');
700
+ return Te(e, t);
701
+ }
702
+ async function Z(e, t) {
703
+ if (!x(e))
704
+ throw new TypeError("JWK must be an object");
705
+ switch (t || (t = e.alg), e.kty) {
706
+ case "oct":
707
+ if (typeof e.k != "string" || !e.k)
708
+ throw new TypeError('missing "k" (Key Value) Parameter value');
709
+ return K(e.k);
710
+ case "RSA":
711
+ if (e.oth !== void 0)
712
+ throw new b('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
713
+ case "EC":
714
+ case "OKP":
715
+ return oe({ ...e, alg: t });
716
+ default:
717
+ throw new b('Unsupported "kty" (Key Type) Parameter value');
718
+ }
719
+ }
720
+ const q = (e) => e == null ? void 0 : e[Symbol.toStringTag], Ke = (e, t) => {
721
+ if (!(t instanceof Uint8Array)) {
722
+ if (!se(t))
723
+ throw new TypeError(ne(e, t, ...M, "Uint8Array"));
724
+ if (t.type !== "secret")
725
+ throw new TypeError(`${q(t)} instances for symmetric algorithms must be of type "secret"`);
726
+ }
727
+ }, Ne = (e, t, r) => {
728
+ if (!se(t))
729
+ throw new TypeError(ne(e, t, ...M));
730
+ if (t.type === "secret")
731
+ throw new TypeError(`${q(t)} instances for asymmetric algorithms must not be of type "secret"`);
732
+ if (t.algorithm && r === "verify" && t.type === "private")
733
+ throw new TypeError(`${q(t)} instances for asymmetric algorithm verifying must be of type "public"`);
734
+ if (t.algorithm && r === "encrypt" && t.type === "private")
735
+ throw new TypeError(`${q(t)} instances for asymmetric algorithm encryption must be of type "public"`);
736
+ }, Ue = (e, t, r) => {
737
+ e.startsWith("HS") || e === "dir" || e.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(e) ? Ke(e, t) : Ne(e, t, r);
738
+ };
739
+ function xe(e, t, r, n, i) {
740
+ if (i.crit !== void 0 && (n == null ? void 0 : n.crit) === void 0)
741
+ throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');
742
+ if (!n || n.crit === void 0)
743
+ return /* @__PURE__ */ new Set();
744
+ if (!Array.isArray(n.crit) || n.crit.length === 0 || n.crit.some((o) => typeof o != "string" || o.length === 0))
745
+ throw new e('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
746
+ let s;
747
+ s = t;
748
+ for (const o of n.crit) {
749
+ if (!s.has(o))
750
+ throw new b(`Extension Header Parameter "${o}" is not recognized`);
751
+ if (i[o] === void 0)
752
+ throw new e(`Extension Header Parameter "${o}" is missing`);
753
+ if (s.get(o) && n[o] === void 0)
754
+ throw new e(`Extension Header Parameter "${o}" MUST be integrity protected`);
755
+ }
756
+ return new Set(n.crit);
757
+ }
758
+ function ze(e, t) {
759
+ const r = `SHA-${e.slice(-3)}`;
760
+ switch (e) {
761
+ case "HS256":
762
+ case "HS384":
763
+ case "HS512":
764
+ return { hash: r, name: "HMAC" };
765
+ case "PS256":
766
+ case "PS384":
767
+ case "PS512":
768
+ return { hash: r, name: "RSA-PSS", saltLength: e.slice(-3) >> 3 };
769
+ case "RS256":
770
+ case "RS384":
771
+ case "RS512":
772
+ return { hash: r, name: "RSASSA-PKCS1-v1_5" };
773
+ case "ES256":
774
+ case "ES384":
775
+ case "ES512":
776
+ return { hash: r, name: "ECDSA", namedCurve: t.namedCurve };
777
+ case "EdDSA":
778
+ return { name: t.name };
779
+ default:
780
+ throw new b(`alg ${e} is not supported either by JOSE or your javascript runtime`);
781
+ }
782
+ }
783
+ async function We(e, t, r) {
784
+ if (t = await Ie.normalizePublicKey(t, e), re(t))
785
+ return Se(t, e, r), t;
786
+ if (t instanceof Uint8Array) {
787
+ if (!e.startsWith("HS"))
788
+ throw new TypeError(X(t, ...M));
789
+ return F.subtle.importKey("raw", t, { hash: `SHA-${e.slice(-3)}`, name: "HMAC" }, false, [r]);
790
+ }
791
+ throw new TypeError(X(t, ...M, "Uint8Array"));
792
+ }
793
+ const De = async (e, t, r, n) => {
794
+ const i = await We(e, t, "verify");
795
+ be(e, i);
796
+ const s = ze(e, i.algorithm);
797
+ try {
798
+ return await F.subtle.verify(s, i, r, n);
799
+ } catch {
800
+ return false;
801
+ }
802
+ };
803
+ async function He(e, t, r) {
804
+ if (!x(e))
805
+ throw new v("Flattened JWS must be an object");
806
+ if (e.protected === void 0 && e.header === void 0)
807
+ throw new v('Flattened JWS must have either of the "protected" or "header" members');
808
+ if (e.protected !== void 0 && typeof e.protected != "string")
809
+ throw new v("JWS Protected Header incorrect type");
810
+ if (e.payload === void 0)
811
+ throw new v("JWS Payload missing");
812
+ if (typeof e.signature != "string")
813
+ throw new v("JWS Signature missing or incorrect type");
814
+ if (e.header !== void 0 && !x(e.header))
815
+ throw new v("JWS Unprotected Header incorrect type");
816
+ let n = {};
817
+ if (e.protected)
818
+ try {
819
+ const ue = K(e.protected);
820
+ n = JSON.parse(z.decode(ue));
821
+ } catch {
822
+ throw new v("JWS Protected Header is invalid");
823
+ }
824
+ if (!_e(n, e.header))
825
+ throw new v("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
826
+ const i = {
827
+ ...n,
828
+ ...e.header
829
+ }, s = xe(v, /* @__PURE__ */ new Map([["b64", true]]), void 0, n, i);
830
+ let o = true;
831
+ if (s.has("b64") && (o = n.b64, typeof o != "boolean"))
832
+ throw new v('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
833
+ const { alg: l } = i;
834
+ if (typeof l != "string" || !l)
835
+ throw new v('JWS "alg" (Algorithm) Header Parameter missing or invalid');
836
+ if (o) {
837
+ if (typeof e.payload != "string")
838
+ throw new v("JWS Payload must be a string");
839
+ } else if (typeof e.payload != "string" && !(e.payload instanceof Uint8Array))
840
+ throw new v("JWS Payload must be a string or an Uint8Array instance");
841
+ let f = false;
842
+ typeof t == "function" && (t = await t(n, e), f = true), Ue(l, t, "verify");
843
+ const p = ge(H.encode(e.protected ?? ""), H.encode("."), typeof e.payload == "string" ? H.encode(e.payload) : e.payload);
844
+ let P;
845
+ try {
846
+ P = K(e.signature);
847
+ } catch {
848
+ throw new v("Failed to base64url decode the signature");
849
+ }
850
+ if (!await De(l, t, P, p))
851
+ throw new me();
852
+ let W;
853
+ if (o)
854
+ try {
855
+ W = K(e.payload);
856
+ } catch {
857
+ throw new v("Failed to base64url decode the payload");
858
+ }
859
+ else typeof e.payload == "string" ? W = H.encode(e.payload) : W = e.payload;
860
+ const D = { payload: W };
861
+ return e.protected !== void 0 && (D.protectedHeader = n), e.header !== void 0 && (D.unprotectedHeader = e.header), f ? { ...D, key: t } : D;
862
+ }
863
+ async function Je(e, t, r) {
864
+ if (e instanceof Uint8Array && (e = z.decode(e)), typeof e != "string")
865
+ throw new v("Compact JWS must be a string or Uint8Array");
866
+ const { 0: n, 1: i, 2: s, length: o } = e.split(".");
867
+ if (o !== 3)
868
+ throw new v("Invalid Compact JWS");
869
+ const l = await He({ payload: i, protected: n, signature: s }, t), f = { payload: l.payload, protectedHeader: l.protectedHeader };
870
+ return typeof t == "function" ? { ...f, key: l.key } : f;
871
+ }
872
+ const he = K;
873
+ function qe(e) {
874
+ let t;
875
+ if (typeof e == "string") {
876
+ const r = e.split(".");
877
+ (r.length === 3 || r.length === 5) && ([t] = r);
878
+ } else if (typeof e == "object" && e)
879
+ if ("protected" in e)
880
+ t = e.protected;
881
+ else
882
+ throw new TypeError("Token does not contain a Protected Header");
883
+ try {
884
+ if (typeof t != "string" || !t)
885
+ throw new Error();
886
+ const r = JSON.parse(z.decode(he(t)));
887
+ if (!x(r))
888
+ throw new Error();
889
+ return r;
890
+ } catch {
891
+ throw new TypeError("Invalid Token or Protected Header formatting");
892
+ }
893
+ }
894
+ function Me(e) {
895
+ if (typeof e != "string")
896
+ throw new E("JWTs must use Compact JWS serialization, JWT must be a string");
897
+ const { 1: t, length: r } = e.split(".");
898
+ if (r === 5)
899
+ throw new E("Only JWTs using Compact JWS serialization can be decoded");
900
+ if (r !== 3)
901
+ throw new E("Invalid JWT");
902
+ if (!t)
903
+ throw new E("JWTs must contain a payload");
904
+ let n;
905
+ try {
906
+ n = he(t);
907
+ } catch {
908
+ throw new E("Failed to base64url decode the payload");
909
+ }
910
+ let i;
911
+ try {
912
+ i = JSON.parse(z.decode(n));
913
+ } catch {
914
+ throw new E("Failed to parse the decoded payload as JSON");
915
+ }
916
+ if (!x(i))
917
+ throw new E("Invalid JWT Claims Set");
918
+ return i;
919
+ }
920
+ const c = class c2 {
921
+ /**
922
+ * Returns a user-friendly name for the given flow strings.
923
+ *
924
+ * The value returned is the one in `flowName`.
925
+ * @param flows the flows to return the names of
926
+ * @returns an array of strings
927
+ */
928
+ static flowNames(t) {
929
+ let r = {};
930
+ return t.forEach((n) => {
931
+ n in c2.flowName && (r[n] = c2.flowName[n]);
932
+ }), r;
933
+ }
934
+ /**
935
+ * Returns true if the given string is a valid flow name.
936
+ * @param flow the flow to check
937
+ * @returns true or false.
938
+ */
939
+ static isValidFlow(t) {
940
+ return c2.allFlows().includes(t);
941
+ }
942
+ /**
943
+ * Returns true only if all given strings are valid flows
944
+ * @param flows the flows to check
945
+ * @returns true or false.
946
+ */
947
+ static areAllValidFlows(t) {
948
+ let r = true;
949
+ return t.forEach((n) => {
950
+ c2.isValidFlow(n) || (r = false);
951
+ }), r;
952
+ }
953
+ static allFlows() {
954
+ return [
955
+ c2.AuthorizationCode,
956
+ c2.AuthorizationCodeWithPKCE,
957
+ c2.ClientCredentials,
958
+ c2.RefreshToken,
959
+ c2.DeviceCode,
960
+ c2.Password,
961
+ c2.PasswordMfa,
962
+ c2.OidcAuthorizationCode
963
+ ];
964
+ }
965
+ /**
966
+ * Returns the OAuth grant types that are valid for a given flow, or
967
+ * `undefined` if it is not a valid flow.
968
+ * @param oauthFlow the flow to get the grant type for.
969
+ * @returns a {@link GrantType} value
970
+ */
971
+ static grantType(t) {
972
+ switch (t) {
973
+ case c2.AuthorizationCode:
974
+ case c2.AuthorizationCodeWithPKCE:
975
+ case c2.OidcAuthorizationCode:
976
+ return ["authorization_code"];
977
+ case c2.ClientCredentials:
978
+ return ["client_credentials"];
979
+ case c2.RefreshToken:
980
+ return ["refresh_token"];
981
+ case c2.Password:
982
+ return ["password"];
983
+ case c2.PasswordMfa:
984
+ return ["http://auth0.com/oauth/grant-type/mfa-otp", "http://auth0.com/oauth/grant-type/mfa-oob"];
985
+ case c2.DeviceCode:
986
+ return ["urn:ietf:params:oauth:grant-type:device_code"];
987
+ }
988
+ }
989
+ };
990
+ a(c, "All", "all"), /** OAuth authorization code flow (without PKCE) */
991
+ a(c, "AuthorizationCode", "authorizationCode"), /** OAuth authorization code flow with PKCE */
992
+ a(c, "AuthorizationCodeWithPKCE", "authorizationCodeWithPKCE"), /** Auth client credentials flow */
993
+ a(c, "ClientCredentials", "clientCredentials"), /** OAuth refresh token flow */
994
+ a(c, "RefreshToken", "refreshToken"), /** OAuth device code flow */
995
+ a(c, "DeviceCode", "deviceCode"), /** OAuth password flow */
996
+ a(c, "Password", "password"), /** The Auth0 password MFA extension to the password flow */
997
+ a(c, "PasswordMfa", "passwordMfa"), /** The OpenID Connect authorization code flow, with or without
998
+ * PKCE.
999
+ */
1000
+ a(c, "OidcAuthorizationCode", "oidcAuthorizationCode"), /** A user friendly name for the given flow ID
1001
+ *
1002
+ * For example, if you pass "authorizationCode"
1003
+ * (`OAuthFlows.AuthorizationCode`) you will get `"Authorization Code"`.
1004
+ */
1005
+ a(c, "flowName", {
1006
+ [c.AuthorizationCode]: "Authorization Code",
1007
+ [c.AuthorizationCodeWithPKCE]: "Authorization Code with PKCE",
1008
+ [c.ClientCredentials]: "Client Credentials",
1009
+ [c.RefreshToken]: "Refresh Token",
1010
+ [c.DeviceCode]: "Device Code",
1011
+ [c.Password]: "Password",
1012
+ [c.PasswordMfa]: "Password MFA",
1013
+ [c.OidcAuthorizationCode]: "OIDC Authorization Code"
1014
+ });
1015
+ var w, S, N, T, R;
1016
+ class Be {
1017
+ /**
1018
+ * Constructor.
1019
+ *
1020
+ * @param options options:
1021
+ * - `authServerBaseUrl` the base URI for OAuth calls. This is
1022
+ * the value in the isser field of a JWT. The client will
1023
+ * reject any JWTs that are not from this issuer.
1024
+ * - `client_id` the client ID for this client.
1025
+ * - `redriectUri` when making OAuth calls, this value is put
1026
+ * in the redirect_uri field.
1027
+ * - `number` of characters (before base64-url-encoding) for generating
1028
+ * state values in OAuth calls.
1029
+ * - `verifierLength` of characters (before base64-url-encoding) for
1030
+ * generating PKCE values in OAuth calls.
1031
+ * - `tokenConsumer` to keep this class independent of frontend
1032
+ * and backend specific funtionality (eg classes not available
1033
+ * in browsers), the token consumer, which determines if a token
1034
+ * is valid or not, is abstracted out.
1035
+ * - authServerCredentials credentials flag for fetch calls to the
1036
+ * authorization server
1037
+ * - authServerMode mode flag for fetch calls to the
1038
+ * authorization server
1039
+ * - authServerHeaders headers flag for calls to the
1040
+ * authorization server
1041
+ * - `receiveTokensFn` if defined, this will be called when tokens
1042
+ * are received
1043
+ */
1044
+ constructor({
1045
+ authServerBaseUrl: t,
1046
+ client_id: r,
1047
+ client_secret: n,
1048
+ redirect_uri: i,
1049
+ codeChallengeMethod: s,
1050
+ stateLength: o,
1051
+ verifierLength: l,
1052
+ tokenConsumer: f,
1053
+ authServerCredentials: p,
1054
+ authServerMode: P,
1055
+ authServerHeaders: U
1056
+ }) {
1057
+ a(this, "authServerBaseUrl", "");
1058
+ O(this, w);
1059
+ O(this, S);
1060
+ O(this, N);
1061
+ a(this, "codeChallengeMethod", "S256");
1062
+ O(this, T);
1063
+ a(this, "verifierLength", 32);
1064
+ a(this, "redirect_uri");
1065
+ O(this, R, "");
1066
+ a(this, "stateLength", 32);
1067
+ a(this, "authzCode", "");
1068
+ a(this, "oidcConfig");
1069
+ a(this, "tokenConsumer");
1070
+ a(this, "authServerHeaders", {});
1071
+ a(this, "authServerMode");
1072
+ a(this, "authServerCredentials");
1073
+ this.tokenConsumer = f, this.authServerBaseUrl = t, l && (this.verifierLength = l), o && (this.stateLength = o), r && _(this, w, r), n && _(this, S, n), i && (this.redirect_uri = i), s && (this.codeChallengeMethod = s), this.authServerBaseUrl = t, p && (this.authServerCredentials = p), P && (this.authServerMode = P), U && (this.authServerHeaders = U);
1074
+ }
1075
+ set client_id(t) {
1076
+ _(this, w, t);
1077
+ }
1078
+ set client_secret(t) {
1079
+ _(this, S, t);
1080
+ }
1081
+ set codeVerifier(t) {
1082
+ _(this, T, t);
1083
+ }
1084
+ set codeChallenge(t) {
1085
+ _(this, N, t);
1086
+ }
1087
+ set state(t) {
1088
+ _(this, R, t);
1089
+ }
1090
+ /**
1091
+ * Loads OpenID Connect configuration so that the client can determine
1092
+ * the URLs it can call and the features the authorization server provides.
1093
+ *
1094
+ * @param oidcConfig if defined, loadsa the config from this object.
1095
+ * Otherwise, performs a fetch by appending
1096
+ * `/.well-known/openid-configuration` to the
1097
+ * `authServerBaseUrl`.
1098
+ * @throws {@link @crossauth/common!CrossauthError} with the following {@link @crossauth/common!ErrorCode}s
1099
+ * - `Connection` if data from the URL could not be fetched or parsed.
1100
+ */
1101
+ async loadConfig(t) {
1102
+ if (t) {
1103
+ d.logger.debug(h({ msg: "Reading OIDC config locally" })), this.oidcConfig = t;
1104
+ return;
1105
+ }
1106
+ let r;
1107
+ try {
1108
+ const n = new URL(
1109
+ this.authServerBaseUrl + "/.well-known/openid-configuration"
1110
+ );
1111
+ d.logger.debug(h({ msg: `Fetching OIDC config from ${n}` }));
1112
+ let i = { headers: this.authServerHeaders };
1113
+ this.authServerMode && (i.mode = this.authServerMode), this.authServerCredentials && (i.credentials = this.authServerCredentials), r = await fetch(n, i);
1114
+ } catch (n) {
1115
+ d.logger.error(h({ err: n }));
1116
+ }
1117
+ if (!r || !r.ok)
1118
+ throw new g(
1119
+ y.Connection,
1120
+ "Couldn't get OIDC configuration from URL" + this.authServerBaseUrl + "/.well-known/openid-configuration"
1121
+ );
1122
+ this.oidcConfig = { ...te };
1123
+ try {
1124
+ const n = await r.json();
1125
+ for (const [i, s] of Object.entries(n))
1126
+ this.oidcConfig[i] = s;
1127
+ } catch {
1128
+ throw new g(
1129
+ y.Connection,
1130
+ "Unrecognized response from OIDC configuration endpoint"
1131
+ );
1132
+ }
1133
+ }
1134
+ getOidcConfig() {
1135
+ return this.oidcConfig;
1136
+ }
1137
+ //////////////////////////////////////////////////////////////////////
1138
+ // Authorization Code Flow
1139
+ /**
1140
+ * Starts the authorizatuin code flow, optionally with PKCE.
1141
+ *
1142
+ * Doesn't actually call the endpoint but rather returns its URL
1143
+ *
1144
+ * @param scope optionally specify the scopes to ask the user to
1145
+ * authorize (space separated, non URL-encoded)
1146
+ * @param pkce if true, initiate the Authorization Code Flow with PKCE,
1147
+ * otherwiswe without PKCE.
1148
+ * @returns an object with
1149
+ * - `url` - the full `authorize` URL to fetch, if there was no
1150
+ * error, undefined otherwise
1151
+ * - `error` OAuth error if there was an error, undefined
1152
+ * otherwise. See OAuth specification for authorize endpoint
1153
+ * - `error_description` friendly error message or undefined
1154
+ * if no error
1155
+ */
1156
+ async startAuthorizationCodeFlow(t, r = false) {
1157
+ var s, o, l;
1158
+ if (d.logger.debug(h({ msg: "Starting authorization code flow" })), this.oidcConfig || await this.loadConfig(), !((s = this.oidcConfig) != null && s.response_types_supported.includes("code")) || !((o = this.oidcConfig) != null && o.response_modes_supported.includes("query")))
1159
+ return {
1160
+ error: "invalid_request",
1161
+ error_description: "Server does not support authorization code flow"
1162
+ };
1163
+ if (!((l = this.oidcConfig) != null && l.authorization_endpoint))
1164
+ return {
1165
+ error: "server_error",
1166
+ error_description: "Cannot get authorize endpoint"
1167
+ };
1168
+ if (_(this, R, this.randomValue(this.stateLength)), !u(this, w)) return {
1169
+ error: "invalid_request",
1170
+ error_description: "Cannot make authorization code flow without client id"
1171
+ };
1172
+ if (!this.redirect_uri) return {
1173
+ error: "invalid_request",
1174
+ error_description: "Cannot make authorization code flow without Redirect Uri"
1175
+ };
1176
+ let i = this.oidcConfig.authorization_endpoint + "?response_type=code&client_id=" + encodeURIComponent(u(this, w)) + "&state=" + encodeURIComponent(u(this, R)) + "&redirect_uri=" + encodeURIComponent(this.redirect_uri);
1177
+ return t && (i += "&scope=" + encodeURIComponent(t)), r && (_(this, T, this.randomValue(this.verifierLength)), _(this, N, this.codeChallengeMethod == "plain" ? u(this, T) : await this.sha256(u(this, T))), i += "&code_challenge=" + u(this, N)), { url: i };
1178
+ }
1179
+ /**
1180
+ * This implements the functionality behind the redirect URI
1181
+ *
1182
+ * Does not throw exceptions.
1183
+ *
1184
+ * If an error wasn't reported, a POST request to the `token` endpoint with
1185
+ * the authorization code to get an access token, etc. If there was
1186
+ * an error, this is just passed through without calling and further
1187
+ * endpoints.
1188
+ *
1189
+ * @param code the authorization code
1190
+ * @param state the random state variable
1191
+ * @param error if defined, it will be returned as an error. This is
1192
+ * for cascading errors from previous requests.
1193
+ * @param errorDescription if error is defined, this text is returned
1194
+ * as the `error_description` It is set to `Unknown error`
1195
+ * otherwise
1196
+ * @returns The {@link OAuthTokenResponse} from the `token` endpoint
1197
+ * request, or `error` and `error_description`.
1198
+ */
1199
+ async redirectEndpoint(t, r, n, i) {
1200
+ var p, P;
1201
+ if (this.oidcConfig || await this.loadConfig(), n || !t)
1202
+ return n || (n = "server_error"), i || (i = "Unknown error"), { error: n, error_description: i };
1203
+ if (u(this, R) && r != u(this, R))
1204
+ return { error: "access_denied", error_description: "State is not valid" };
1205
+ if (this.authzCode = t, !((p = this.oidcConfig) != null && p.grant_types_supported.includes("authorization_code")))
1206
+ return {
1207
+ error: "invalid_request",
1208
+ error_description: "Server does not support authorization code grant"
1209
+ };
1210
+ if (!((P = this.oidcConfig) != null && P.token_endpoint))
1211
+ return {
1212
+ error: "server_error",
1213
+ error_description: "Cannot get token endpoint"
1214
+ };
1215
+ const s = this.oidcConfig.token_endpoint;
1216
+ let o, l;
1217
+ o = "authorization_code", l = u(this, S);
1218
+ let f = {
1219
+ grant_type: o,
1220
+ client_id: u(this, w),
1221
+ code: this.authzCode
1222
+ };
1223
+ l && (f.client_secret = l), f.code_verifier = u(this, T);
1224
+ try {
1225
+ return this.post(s, f, this.authServerHeaders);
1226
+ } catch (U) {
1227
+ return d.logger.error(h({ err: U })), {
1228
+ error: "server_error",
1229
+ error_description: "Unable to get access token from server"
1230
+ };
1231
+ }
1232
+ }
1233
+ //////////////////////////////////////////////////////////////////////
1234
+ // Client Credentials Flow
1235
+ /**
1236
+ * Performs the client credentials flow.
1237
+ *
1238
+ * Does not throw exceptions.
1239
+ *
1240
+ * Makes a POST request to the `token` endpoint with the
1241
+ * authorization code to get an access token, etc.
1242
+ *
1243
+ * @param scope the scopes to authorize for the client (optional)
1244
+ * @returns The {@link OAuthTokenResponse} from the `token` endpoint
1245
+ * request, or `error` and `error_description`.
1246
+ */
1247
+ async clientCredentialsFlow(t) {
1248
+ var i, s;
1249
+ if (d.logger.debug(h({ msg: "Starting client credentials flow" })), this.oidcConfig || await this.loadConfig(), !((i = this.oidcConfig) != null && i.grant_types_supported.includes("client_credentials")))
1250
+ return {
1251
+ error: "invalid_request",
1252
+ error_description: "Server does not support client credentials grant"
1253
+ };
1254
+ if (!((s = this.oidcConfig) != null && s.token_endpoint))
1255
+ return { error: "server_error", error_description: "Cannot get token endpoint" };
1256
+ if (!u(this, w)) return {
1257
+ error: "invalid_request",
1258
+ error_description: "Cannot make client credentials flow without client id"
1259
+ };
1260
+ const r = this.oidcConfig.token_endpoint;
1261
+ let n = {
1262
+ grant_type: "client_credentials",
1263
+ client_id: u(this, w),
1264
+ client_secret: u(this, S)
1265
+ };
1266
+ t && (n.scope = t);
1267
+ try {
1268
+ return await this.post(r, n, this.authServerHeaders);
1269
+ } catch (o) {
1270
+ return d.logger.error(h({ err: o })), {
1271
+ error: "server_error",
1272
+ error_description: "Error connecting to authorization server"
1273
+ };
1274
+ }
1275
+ }
1276
+ //////////////////////////////////////////////////////////////////////
1277
+ // Password and Password MFA Flows
1278
+ /** Initiates the Password Flow.
1279
+ *
1280
+ * Does not throw exceptions.
1281
+ *
1282
+ * @param username the username
1283
+ * @param password the user's password
1284
+ * @param scope the scopes to authorize (optional)
1285
+ * @returns An {@link OAuthTokenResponse} which may contain data or
1286
+ * the OAuth error fields. If 2FA is enabled for this user on the
1287
+ * authorization server, the Password MFA flow is followed. See
1288
+ * {@link https://auth0.com/docs/secure/multi-factor-authentication/multi-factor-authentication-factors}.
1289
+ *
1290
+ */
1291
+ async passwordFlow(t, r, n) {
1292
+ var o, l;
1293
+ if (d.logger.debug(h({ msg: "Starting password flow" })), this.oidcConfig || await this.loadConfig(), !((o = this.oidcConfig) != null && o.grant_types_supported.includes("password")))
1294
+ return {
1295
+ error: "invalid_request",
1296
+ error_description: "Server does not support password grant"
1297
+ };
1298
+ if (!((l = this.oidcConfig) != null && l.token_endpoint))
1299
+ return {
1300
+ error: "server_error",
1301
+ error_description: "Cannot get token endpoint"
1302
+ };
1303
+ const i = this.oidcConfig.token_endpoint;
1304
+ let s = {
1305
+ grant_type: "password",
1306
+ client_id: u(this, w),
1307
+ client_secret: u(this, S),
1308
+ username: t,
1309
+ password: r
1310
+ };
1311
+ n && (s.scope = n);
1312
+ try {
1313
+ return await this.post(i, s, this.authServerHeaders);
1314
+ } catch (f) {
1315
+ return d.logger.error(h({ err: f })), {
1316
+ error: "server_error",
1317
+ error_description: "Error connecting to authorization server"
1318
+ };
1319
+ }
1320
+ }
1321
+ /** Request valid authenticators using the Password MFA flow,
1322
+ * after the Password flow has been initiated.
1323
+ *
1324
+ * Does not throw exceptions.
1325
+ *
1326
+ * @param mfaToken the MFA token that was returned by the authorization
1327
+ * server in the response from the Password Flow.
1328
+ * @returns Either
1329
+ * - authenticators an array of {@link MfaAuthenticatorResponse} objects,
1330
+ * as per Auth0's Password MFA documentation
1331
+ * - an `error` and `error_description`, also as per Auth0's Password MFA
1332
+ * documentation
1333
+ */
1334
+ async mfaAuthenticators(t) {
1335
+ var s, o, l;
1336
+ if (d.logger.debug(h({ msg: "Getting valid MFA authenticators" })), this.oidcConfig || await this.loadConfig(), !((s = this.oidcConfig) != null && s.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")) && ((o = this.oidcConfig) != null && o.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-oob")))
1337
+ return {
1338
+ error: "invalid_request",
1339
+ error_description: "Server does not support password_mfa grant"
1340
+ };
1341
+ if (!((l = this.oidcConfig) != null && l.issuer))
1342
+ return { error: "server_error", error_description: "Cannot get issuer" };
1343
+ const r = this.oidcConfig.issuer + (this.oidcConfig.issuer.endsWith("/") ? "" : "/") + "mfa/authenticators", n = await this.get(r, { authorization: "Bearer " + t, ...this.authServerHeaders });
1344
+ if (!Array.isArray(n))
1345
+ return {
1346
+ error: "server_error",
1347
+ error_description: "Expected array of authenticators in mfa/authenticators response"
1348
+ };
1349
+ let i = [];
1350
+ for (let f = 0; f < n.length; ++f) {
1351
+ const p = n[f];
1352
+ if (!p.id || !p.authenticator_type || !p.active)
1353
+ return {
1354
+ error: "server_error",
1355
+ error_description: "Invalid mfa/authenticators response"
1356
+ };
1357
+ i.push({
1358
+ id: p.id,
1359
+ authenticator_type: p.authenticator_type,
1360
+ active: p.active,
1361
+ name: p.name,
1362
+ oob_channel: p.oob_channel
1363
+ });
1364
+ }
1365
+ return { authenticators: i };
1366
+ }
1367
+ /**
1368
+ * This is part of the Auth0 Password MFA flow. Once the client has
1369
+ * received a list of valid authenticators, if it wishes to initiate
1370
+ * OTP, call this function
1371
+ *
1372
+ * Does not throw exceptions.
1373
+ *
1374
+ * @param mfaToken the MFA token that was returned by the authorization
1375
+ * server in the response from the Password Flow.
1376
+ * @param authenticatorId the authenticator ID, as returned in the response
1377
+ * from the `mfaAuthenticators` request.
1378
+ */
1379
+ async mfaOtpRequest(t, r) {
1380
+ var s, o;
1381
+ if (d.logger.debug(h({ msg: "Making MFA OTB request" })), this.oidcConfig || await this.loadConfig(), !((s = this.oidcConfig) != null && s.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))
1382
+ return {
1383
+ error: "invalid_request",
1384
+ error_description: "Server does not support password_mfa grant"
1385
+ };
1386
+ if (!((o = this.oidcConfig) != null && o.issuer))
1387
+ return { error: "server_error", error_description: "Cannot get issuer" };
1388
+ const n = this.oidcConfig.issuer + (this.oidcConfig.issuer.endsWith("/") ? "" : "/") + "mfa/challenge", i = await this.post(n, {
1389
+ client_id: u(this, w),
1390
+ client_secret: u(this, S),
1391
+ challenge_type: "otp",
1392
+ mfa_token: t,
1393
+ authenticator_id: r
1394
+ }, this.authServerHeaders);
1395
+ return i.challenge_type != "otp" ? {
1396
+ error: i.error ?? "server_error",
1397
+ error_description: i.error_description ?? "Invalid OTP challenge response"
1398
+ } : i;
1399
+ }
1400
+ /**
1401
+ * Completes the Password MFA OTP flow.
1402
+ * @param mfaToken the MFA token that was returned by the authorization
1403
+ * server in the response from the Password Flow.
1404
+ * @param otp the OTP entered by the user
1405
+ * @returns an object with some of the following fields, depending on
1406
+ * authorization server configuration and whether there were
1407
+ * errors:
1408
+ * - `access_token` an OAuth access token
1409
+ * - `refresh_token` an OAuth access token
1410
+ * - `id_token` an OpenID Connect ID token
1411
+ * - `expires_in` number of seconds when the access token expires
1412
+ * - `scope` the scopes the user authorized
1413
+ * - `token_type` the OAuth token type
1414
+ * - `error` as per Auth0 Password MFA documentation
1415
+ * - `error_description` friendly error message
1416
+ */
1417
+ async mfaOtpComplete(t, r, n) {
1418
+ var o, l;
1419
+ if (d.logger.debug(h({ msg: "Completing MFA OTP request" })), this.oidcConfig || await this.loadConfig(), !((o = this.oidcConfig) != null && o.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))
1420
+ return {
1421
+ error: "invalid_request",
1422
+ error_description: "Server does not support password_mfa grant"
1423
+ };
1424
+ if (!((l = this.oidcConfig) != null && l.issuer))
1425
+ return { error: "server_error", error_description: "Cannot get issuer" };
1426
+ const i = this.oidcConfig.token_endpoint, s = await this.post(i, {
1427
+ grant_type: "http://auth0.com/oauth/grant-type/mfa-otp",
1428
+ client_id: u(this, w),
1429
+ client_secret: u(this, S),
1430
+ challenge_type: "otp",
1431
+ mfa_token: t,
1432
+ otp: r,
1433
+ scope: n
1434
+ }, this.authServerHeaders);
1435
+ return {
1436
+ id_token: s.id_token,
1437
+ access_token: s.access_token,
1438
+ refresh_token: s.refresh_token,
1439
+ expires_in: Number(s.expires_in),
1440
+ scope: s.scope,
1441
+ token_type: s.token_type,
1442
+ error: s.error,
1443
+ error_description: s.error_description
1444
+ };
1445
+ }
1446
+ /**
1447
+ * This is part of the Auth0 Password MFA flow. Once the client has
1448
+ * received a list of valid authenticators, if it wishes to initiate
1449
+ * OOB (out of band) login, call this function
1450
+ *
1451
+ * Does not throw exceptions.
1452
+ *
1453
+ * @param mfaToken the MFA token that was returned by the authorization
1454
+ * server in the response from the Password Flow.
1455
+ * @param authenticatorId the authenticator ID, as returned in the response
1456
+ * from the `mfaAuthenticators` request.
1457
+ * @returns an object with one or more of the following defined:
1458
+ * - `challenge_type` as per the Auth0 MFA documentation
1459
+ * - `oob_code` as per the Auth0 MFA documentation
1460
+ * - `binding_method` as per the Auth0 MFA documentation
1461
+ * - `error` as per Auth0 Password MFA documentation
1462
+ * - `error_description` friendly error message
1463
+ */
1464
+ async mfaOobRequest(t, r) {
1465
+ var s, o;
1466
+ if (d.logger.debug(h({ msg: "Making MFA OOB request" })), this.oidcConfig || await this.loadConfig(), !((s = this.oidcConfig) != null && s.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))
1467
+ return {
1468
+ error: "invalid_request",
1469
+ error_description: "Server does not support password_mfa grant"
1470
+ };
1471
+ if (!((o = this.oidcConfig) != null && o.issuer))
1472
+ return { error: "server_error", error_description: "Cannot get issuer" };
1473
+ const n = this.oidcConfig.issuer + (this.oidcConfig.issuer.endsWith("/") ? "" : "/") + "mfa/challenge", i = await this.post(n, {
1474
+ client_id: u(this, w),
1475
+ client_secret: u(this, S),
1476
+ challenge_type: "oob",
1477
+ mfa_token: t,
1478
+ authenticator_id: r
1479
+ }, this.authServerHeaders);
1480
+ return i.challenge_type != "oob" || !i.oob_code || !i.binding_method ? { error: i.error ?? "server_error", error_description: i.error_description ?? "Invalid OOB challenge response" } : {
1481
+ challenge_type: i.challenge_type,
1482
+ oob_code: i.oob_code,
1483
+ binding_method: i.binding_method,
1484
+ error: i.error,
1485
+ error_description: i.error_description
1486
+ };
1487
+ }
1488
+ /**
1489
+ * Completes the Password MFA OTP flow.
1490
+ *
1491
+ * Does not throw exceptions.
1492
+ *
1493
+ * @param mfaToken the MFA token that was returned by the authorization
1494
+ * server in the response from the Password Flow.
1495
+ * @param oobCode the code entered by the user
1496
+ * @returns an {@link OAuthTokenResponse} object, which may contain
1497
+ * an error instead of the response fields.
1498
+ */
1499
+ async mfaOobComplete(t, r, n, i) {
1500
+ var l, f;
1501
+ if (d.logger.debug(h({ msg: "Completing MFA OOB request" })), this.oidcConfig || await this.loadConfig(), !((l = this.oidcConfig) != null && l.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-oob")))
1502
+ return {
1503
+ error: "invalid_request",
1504
+ error_description: "Server does not support password_mfa grant"
1505
+ };
1506
+ if (!((f = this.oidcConfig) != null && f.issuer))
1507
+ return { error: "server_error", error_description: "Cannot get issuer" };
1508
+ const s = this.oidcConfig.token_endpoint, o = await this.post(s, {
1509
+ grant_type: "http://auth0.com/oauth/grant-type/mfa-oob",
1510
+ client_id: u(this, w),
1511
+ client_secret: u(this, S),
1512
+ challenge_type: "otp",
1513
+ mfa_token: t,
1514
+ oob_code: r,
1515
+ binding_code: n,
1516
+ scope: i
1517
+ }, this.authServerHeaders);
1518
+ return o.error ? {
1519
+ error: o.error,
1520
+ error_description: o.error_description
1521
+ } : {
1522
+ id_token: o.id_token,
1523
+ access_token: o.access_token,
1524
+ refresh_token: o.refresh_token,
1525
+ expires_in: "expires_in" in o ? Number(o.expires_in) : void 0,
1526
+ scope: o.scope,
1527
+ token_type: o.token_type
1528
+ };
1529
+ }
1530
+ //////////////////////////////////////////////////////////////////////
1531
+ // Refresh Token Flow
1532
+ async refreshTokenFlow(t) {
1533
+ var s, o;
1534
+ if (d.logger.debug(h({ msg: "Starting refresh token flow" })), this.oidcConfig || await this.loadConfig(), !((s = this.oidcConfig) != null && s.grant_types_supported.includes("refresh_token")))
1535
+ return {
1536
+ error: "invalid_request",
1537
+ error_description: "Server does not support refresh_token grant"
1538
+ };
1539
+ if (!((o = this.oidcConfig) != null && o.token_endpoint))
1540
+ return {
1541
+ error: "server_error",
1542
+ error_description: "Cannot get token endpoint"
1543
+ };
1544
+ const r = this.oidcConfig.token_endpoint;
1545
+ let n;
1546
+ n = u(this, S);
1547
+ let i = {
1548
+ grant_type: "refresh_token",
1549
+ refresh_token: t,
1550
+ client_id: u(this, w)
1551
+ };
1552
+ n && (i.client_secret = n);
1553
+ try {
1554
+ return await this.post(r, i, this.authServerHeaders);
1555
+ } catch (l) {
1556
+ return d.logger.error(h({ err: l })), {
1557
+ error: "server_error",
1558
+ error_description: "Error connecting to authorization server"
1559
+ };
1560
+ }
1561
+ }
1562
+ //////////////////////////////////////////////////////////////////////
1563
+ // Device Code Flow
1564
+ /**
1565
+ * Starts the Device Code Flow on the primary device (the one wanting an access token)
1566
+ * @param url The URl for the device_authorization endpoint, as it is not defined in the OIDC configuration
1567
+ * @param scope optional scope to request authorization for
1568
+ * @returns See {@link OAuthDeviceAuthorizationResponse}
1569
+ */
1570
+ async startDeviceCodeFlow(t, r) {
1571
+ var i;
1572
+ if (d.logger.debug(h({ msg: "Starting device code flow" })), this.oidcConfig || await this.loadConfig(), !((i = this.oidcConfig) != null && i.grant_types_supported.includes("urn:ietf:params:oauth:grant-type:device_code")))
1573
+ return {
1574
+ error: "invalid_request",
1575
+ error_description: "Server does not support device code grant"
1576
+ };
1577
+ let n = {
1578
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
1579
+ client_id: u(this, w),
1580
+ client_secret: u(this, S)
1581
+ };
1582
+ r && (n.scope = r);
1583
+ try {
1584
+ return await this.post(t, n, this.authServerHeaders);
1585
+ } catch (s) {
1586
+ return d.logger.error(h({ err: s })), {
1587
+ error: "server_error",
1588
+ error_description: "Error connecting to authorization server"
1589
+ };
1590
+ }
1591
+ }
1592
+ /**
1593
+ * Polls the device endpoint to check if the device code flow has been
1594
+ * authorized by the user.
1595
+ *
1596
+ * @param deviceCode the device code to poll
1597
+ * @returns See {@link OAuthDeviceResponse}
1598
+ */
1599
+ async pollDeviceCodeFlow(t) {
1600
+ var n, i, s;
1601
+ if (d.logger.debug(h({ msg: "Starting device code flow" })), this.oidcConfig || await this.loadConfig(), !((n = this.oidcConfig) != null && n.grant_types_supported.includes("urn:ietf:params:oauth:grant-type:device_code")))
1602
+ return {
1603
+ error: "invalid_request",
1604
+ error_description: "Server does not support device code grant"
1605
+ };
1606
+ if (!((i = this.oidcConfig) != null && i.token_endpoint))
1607
+ return {
1608
+ error: "server_error",
1609
+ error_description: "Cannot get token endpoint"
1610
+ };
1611
+ let r = {
1612
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
1613
+ client_id: u(this, w),
1614
+ client_secret: u(this, S),
1615
+ device_code: t
1616
+ };
1617
+ try {
1618
+ const o = await this.post((s = this.oidcConfig) == null ? void 0 : s.token_endpoint, r, this.authServerHeaders);
1619
+ return o.error, o;
1620
+ } catch (o) {
1621
+ return d.logger.error(h({ err: o })), {
1622
+ error: "server_error",
1623
+ error_description: "Error connecting to authorization server"
1624
+ };
1625
+ }
1626
+ }
1627
+ /**
1628
+ * Makes a POST request to the given URL using `fetch()`.
1629
+ *
1630
+ * @param url the URL to fetch
1631
+ * @param params the body parameters, which are passed as JSON.
1632
+ * @returns the parsed JSON response as an object.
1633
+ * @throws any exception raised by `fetch()`
1634
+ */
1635
+ async post(t, r, n = {}) {
1636
+ d.logger.debug(h({
1637
+ msg: "Fetch POST",
1638
+ url: t,
1639
+ params: Object.keys(r)
1640
+ }));
1641
+ let i = {};
1642
+ return this.authServerCredentials && (i.credentials = this.authServerCredentials), this.authServerMode && (i.mode = this.authServerMode), await (await fetch(t, {
1643
+ method: "POST",
1644
+ ...i,
1645
+ headers: {
1646
+ Accept: "application/json",
1647
+ "Content-Type": "application/json",
1648
+ ...n
1649
+ },
1650
+ body: JSON.stringify(r)
1651
+ })).json();
1652
+ }
1653
+ /**
1654
+ * Makes a GET request to the given URL using `fetch()`.
1655
+ *
1656
+ * @param url the URL to fetch
1657
+ * @param headers any headers to add to the request
1658
+ * @returns the parsed JSON response as an object.
1659
+ * @throws any exception raised by `fetch()`
1660
+ */
1661
+ async get(t, r = {}) {
1662
+ d.logger.debug(h({ msg: "Fetch GET", url: t }));
1663
+ let n = {};
1664
+ return this.authServerCredentials && (n.credentials = this.authServerCredentials), this.authServerMode && (n.mode = this.authServerMode), await (await fetch(t, {
1665
+ method: "GET",
1666
+ ...n,
1667
+ headers: {
1668
+ Accept: "application/json",
1669
+ "Content-Type": "application/json",
1670
+ ...r
1671
+ }
1672
+ })).json();
1673
+ }
1674
+ /**
1675
+ * Validates an OpenID ID token, returning undefined if it is invalid.
1676
+ *
1677
+ * Does not raise exceptions.
1678
+ *
1679
+ * @param token the token to validate. To be valid, the signature must
1680
+ * be valid and the `type` claim in the payload must be set to `id`.
1681
+ * @returns the parsed payload or undefined if the token is invalid.
1682
+ */
1683
+ async validateIdToken(t) {
1684
+ try {
1685
+ return await this.tokenConsumer.tokenAuthorized(t, "id");
1686
+ } catch {
1687
+ return;
1688
+ }
1689
+ }
1690
+ /**
1691
+ * Validatesd a token using the token consumer.
1692
+ *
1693
+ * @param idToken the token to validate
1694
+ * @returns the parsed JSON of the payload, or undefinedf if it is not
1695
+ * valid.
1696
+ */
1697
+ async idTokenAuthorized(t) {
1698
+ try {
1699
+ return await this.tokenConsumer.tokenAuthorized(t, "id");
1700
+ } catch (r) {
1701
+ d.logger.warn(h({ err: r }));
1702
+ return;
1703
+ }
1704
+ }
1705
+ getTokenPayload(t) {
1706
+ return Me(t);
1707
+ }
1708
+ }
1709
+ w = /* @__PURE__ */ new WeakMap(), S = /* @__PURE__ */ new WeakMap(), N = /* @__PURE__ */ new WeakMap(), T = /* @__PURE__ */ new WeakMap(), R = /* @__PURE__ */ new WeakMap();
1710
+ class Le {
1711
+ /**
1712
+ * Constrctor
1713
+ *
1714
+ * @param audience : this is the value expected in the `aud` field
1715
+ * of the JWT. The token is rejected if it doesn't match.
1716
+ * @param options See {@link OAuthTokenConsumerBaseOptions}.
1717
+ */
1718
+ constructor(t, r = {}) {
1719
+ a(this, "audience");
1720
+ a(this, "jwtKeyType");
1721
+ a(this, "jwtSecretKey");
1722
+ a(this, "jwtPublicKey");
1723
+ a(this, "clockTolerance", 10);
1724
+ a(this, "authServerBaseUrl", "");
1725
+ a(this, "oidcConfig");
1726
+ a(this, "keys", {});
1727
+ if (this.audience = t, r.authServerBaseUrl && (this.authServerBaseUrl = r.authServerBaseUrl), r.jwtKeyType && (this.jwtKeyType = r.jwtKeyType), r.jwtSecretKey && (this.jwtSecretKey = r.jwtSecretKey), r.jwtPublicKey && (this.jwtPublicKey = r.jwtPublicKey), r.clockTolerance && (this.clockTolerance = r.clockTolerance), r.oidcConfig && (this.oidcConfig = r.oidcConfig), this.jwtPublicKey && !this.jwtKeyType)
1728
+ throw new g(
1729
+ y.Configuration,
1730
+ "If specifying jwtPublic key, must also specify jwtKeyType"
1731
+ );
1732
+ }
1733
+ /**
1734
+ * This loads keys either from the ones passed in the constructor
1735
+ * or by fetching from the authorization server.
1736
+ *
1737
+ * Note that even if you pass the keys to the constructor, you must
1738
+ * still call this function. This is because key loading is
1739
+ * asynchronous, and constructors may not be async.
1740
+ */
1741
+ async loadKeys() {
1742
+ try {
1743
+ if (this.jwtSecretKey) {
1744
+ if (!this.jwtKeyType)
1745
+ throw new g(
1746
+ y.Configuration,
1747
+ "Must specify jwtKeyType if setting jwtSecretKey"
1748
+ );
1749
+ this.keys._default = await Oe(this.jwtSecretKey, this.jwtKeyType);
1750
+ } else if (this.jwtPublicKey) {
1751
+ if (!this.jwtKeyType)
1752
+ throw new g(
1753
+ y.Configuration,
1754
+ "Must specify jwtKeyType if setting jwtPublicKey"
1755
+ );
1756
+ const t = await Ee(this.jwtPublicKey, this.jwtKeyType);
1757
+ this.keys._default = t;
1758
+ } else {
1759
+ if (this.oidcConfig || await this.loadConfig(), !this.oidcConfig)
1760
+ throw new g(
1761
+ y.Connection,
1762
+ "Load OIDC config before Jwks"
1763
+ );
1764
+ await this.loadJwks();
1765
+ }
1766
+ } catch (t) {
1767
+ throw d.logger.debug(h({ err: t })), new g(y.Connection, "Couldn't load keys");
1768
+ }
1769
+ }
1770
+ /**
1771
+ * Loads OpenID Connect configuration, or fetches it from the
1772
+ * authorization server (using the well-known enpoint appended
1773
+ * to `authServerBaseUrl` )
1774
+ * @param oidcConfig the configuration, or undefined to load it from
1775
+ * the authorization server
1776
+ * @throws a {@link @crossauth/common!CrossauthError} object with {@link @crossauth/common!ErrorCode} of
1777
+ * - `Connection` if the fetch to the authorization server failed.
1778
+ */
1779
+ async loadConfig(t) {
1780
+ if (t) {
1781
+ this.oidcConfig = t;
1782
+ return;
1783
+ }
1784
+ if (!this.authServerBaseUrl)
1785
+ throw new g(y.Connection, "Couldn't get OIDC configuration. Either set authServerBaseUrl or set config manually");
1786
+ let r;
1787
+ try {
1788
+ r = await fetch(new URL("/.well-known/openid-configuration", this.authServerBaseUrl));
1789
+ } catch (n) {
1790
+ d.logger.error(h({ err: n }));
1791
+ }
1792
+ if (!r || !r.ok)
1793
+ throw new g(y.Connection, "Couldn't get OIDC configuration");
1794
+ this.oidcConfig = { ...te };
1795
+ try {
1796
+ const n = await r.json();
1797
+ for (const [i, s] of Object.entries(n))
1798
+ this.oidcConfig[i] = s;
1799
+ } catch {
1800
+ throw new g(y.Connection, "Unrecognized response from OIDC configuration endpoint");
1801
+ }
1802
+ }
1803
+ /**
1804
+ * Loads the JWT signature validation keys, or fetches them from the
1805
+ * authorization server (using the URL in the OIDC configuration).
1806
+ * @param jwks the keys to load, or undefined to fetch them from
1807
+ * the authorization server.
1808
+ * @throws a {@link @crossauth/common!CrossauthError} object with {@link @crossauth/common!ErrorCode} of
1809
+ * - `Connection` if the fetch to the authorization server failed,
1810
+ * the OIDC configuration wasn't set or the keys could not be parsed.
1811
+ */
1812
+ async loadJwks(t) {
1813
+ if (t) {
1814
+ this.keys = {};
1815
+ for (let r = 0; r < t.keys.length; ++r) {
1816
+ const n = t.keys[r];
1817
+ this.keys[n.kid ?? "_default"] = await Z(t.keys[r]);
1818
+ }
1819
+ } else {
1820
+ if (!this.oidcConfig)
1821
+ throw new g(y.Connection, "Load OIDC config before Jwks");
1822
+ let r;
1823
+ try {
1824
+ r = await fetch(new URL(this.oidcConfig.jwks_uri));
1825
+ } catch (n) {
1826
+ d.logger.error(h({ err: n }));
1827
+ }
1828
+ if (!r || !r.ok)
1829
+ throw new g(y.Connection, "Couldn't get OIDC configuration");
1830
+ this.keys = {};
1831
+ try {
1832
+ const n = await r.json();
1833
+ if (!("keys" in n) || !Array.isArray(n.keys))
1834
+ throw new g(y.Connection, "Couldn't fetch keys");
1835
+ for (let i = 0; i < n.keys.length; ++i)
1836
+ try {
1837
+ let s = "_default";
1838
+ "kid" in n.keys[i] && typeof n.keys[i] == "string" && (s = String(n.keys[i]));
1839
+ const o = await Z(n.keys[i]);
1840
+ this.keys[s] = o;
1841
+ } catch (s) {
1842
+ throw d.logger.error(h({ err: s })), new g(y.Connection, "Couldn't load keys");
1843
+ }
1844
+ } catch (n) {
1845
+ throw d.logger.error(h({ err: n })), new g(y.Connection, "Unrecognized response from OIDC jwks endpoint");
1846
+ }
1847
+ }
1848
+ }
1849
+ /**
1850
+ * Returns JWT payload if the token is valid, undefined otherwise.
1851
+ *
1852
+ * Doesn't throw exceptions.
1853
+ *
1854
+ * @param token the token to validate
1855
+ * @param tokenType either `access`, `refresh` or `id`. If the
1856
+ * `type` field in the JWT payload doesn't match this, validation
1857
+ * fails.
1858
+ * @returns the JWT payload if the token is valid, `undefined` otherwise.
1859
+ */
1860
+ async tokenAuthorized(t, r) {
1861
+ (!this.keys || Object.keys(this.keys).length == 0) && await this.loadKeys();
1862
+ const n = await this.validateToken(t);
1863
+ if (n) {
1864
+ if (n.type != r && d.logger.error(h({ msg: r + " expected but got " + n.type })), n.iss != this.authServerBaseUrl) {
1865
+ d.logger.error(h({ msg: `Invalid issuer ${n.iss} in access token`, hashedAccessToken: await this.hash(n.jti) }));
1866
+ return;
1867
+ }
1868
+ if (n.aud && (Array.isArray(n.aud) && !n.aud.includes(this.audience) || !Array.isArray(n.aud) && n.aud != this.audience)) {
1869
+ d.logger.error(h({ msg: `Invalid audience ${n.aud} in access token`, hashedAccessToken: await this.hash(n.jti) }));
1870
+ return;
1871
+ }
1872
+ return n;
1873
+ }
1874
+ }
1875
+ async validateToken(t) {
1876
+ (!this.keys || Object.keys(this.keys).length == 0) && d.logger.warn("No keys loaded so cannot validate tokens");
1877
+ let r;
1878
+ try {
1879
+ r = qe(t).kid;
1880
+ } catch {
1881
+ d.logger.warn(h({ msg: "Invalid access token format" }));
1882
+ return;
1883
+ }
1884
+ let n;
1885
+ "_default" in this.keys && (n = this.keys._default);
1886
+ for (let i in this.keys)
1887
+ if (r == i) {
1888
+ n = this.keys[i];
1889
+ break;
1890
+ }
1891
+ if (!n) {
1892
+ d.logger.warn(h({ msg: "No matching keys found for access token" }));
1893
+ return;
1894
+ }
1895
+ try {
1896
+ const { payload: i } = await Je(t, n), s = JSON.parse(new TextDecoder().decode(i));
1897
+ if (s.exp * 1e3 < Date.now() + this.clockTolerance) {
1898
+ d.logger.warn(h({ msg: "Access token has expired" }));
1899
+ return;
1900
+ }
1901
+ return s;
1902
+ } catch {
1903
+ d.logger.warn(h({ msg: "Access token did not validate" }));
1904
+ return;
1905
+ }
1906
+ }
1907
+ }
1908
+ const TOLERANCE_SECONDS = 30;
1909
+ const AUTOREFRESH_RETRIES = 2;
1910
+ const AUTOREFRESH_RETRY_INTERVAL_SECS = 30;
1911
+ class OAuthAutoRefresher {
1912
+ /**
1913
+ * Constructor
1914
+ *
1915
+ * @param options
1916
+ * - `autoRefreshUrl` the URL to call to perform the refresh Default is `/autorefresh`
1917
+ * - `csrfHeader` the header to put CSRF tokens into
1918
+ * (default `X-CROSSAUTH-CSRF`))
1919
+ * - `mode` overrides the default `mode` in fetch calls
1920
+ * - `credentials` - overrides the default `credentials` for fetch calls
1921
+ * - `headers` - adds headers to fetfh calls
1922
+ * - `tokenProvider` - class for fetching tokens and adding them to requests
1923
+ */
1924
+ constructor(options) {
1925
+ __publicField(this, "autoRefreshUrl", "/autorefresh");
1926
+ __publicField(this, "csrfHeader", "X-CROSSAUTH-CSRF");
1927
+ __publicField(this, "headers", {});
1928
+ __publicField(this, "autoRefreshActive", false);
1929
+ __publicField(this, "mode", "cors");
1930
+ __publicField(this, "credentials", "same-origin");
1931
+ __publicField(this, "tokenProvider");
1932
+ this.tokenProvider = options.tokenProvider;
1933
+ this.autoRefreshUrl = options.autoRefreshUrl;
1934
+ if (options.csrfHeader) this.csrfHeader = options.csrfHeader;
1935
+ if (options.headers) this.headers = options.headers;
1936
+ if (options.mode) this.mode = options.mode;
1937
+ if (options.credentials) this.credentials = options.credentials;
1938
+ }
1939
+ async startAutoRefresh(tokensToFetch = ["access", "id"], errorFn) {
1940
+ if (!this.autoRefreshActive) {
1941
+ this.autoRefreshActive = true;
1942
+ d.logger.debug(h({ msg: "Starting auto refresh" }));
1943
+ await this.scheduleAutoRefresh(tokensToFetch, errorFn);
1944
+ }
1945
+ }
1946
+ stopAutoRefresh() {
1947
+ this.autoRefreshActive = false;
1948
+ d.logger.debug(h({ msg: "Stopping auto refresh" }));
1949
+ }
1950
+ async scheduleAutoRefresh(tokensToFetch, errorFn) {
1951
+ const csrfTokenPromise = this.tokenProvider.getCsrfToken();
1952
+ const csrfToken = csrfTokenPromise ? await csrfTokenPromise : void 0;
1953
+ const expiries = await this.tokenProvider.getTokenExpiries([...tokensToFetch, "refresh"], csrfToken);
1954
+ if (expiries.refresh == void 0) {
1955
+ d.logger.debug(h({ msg: `No refresh token found` }));
1956
+ return;
1957
+ }
1958
+ const now = Date.now();
1959
+ let tokenExpiry = expiries.id;
1960
+ if (!tokenExpiry || expiries.access && expiries.access < tokenExpiry) tokenExpiry = expiries.access;
1961
+ if (!tokenExpiry) {
1962
+ d.logger.debug(h({ msg: `No tokens expire` }));
1963
+ return;
1964
+ }
1965
+ const renewTime = tokenExpiry * 1e3 - now - TOLERANCE_SECONDS;
1966
+ if (renewTime < 0) {
1967
+ d.logger.debug(h({ msg: `Expiry time has passed` }));
1968
+ return;
1969
+ }
1970
+ if (expiries.refresh && expiries.refresh - TOLERANCE_SECONDS < renewTime) {
1971
+ d.logger.debug(h({ msg: `Refresh token has expired` }));
1972
+ return;
1973
+ }
1974
+ let wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1975
+ d.logger.debug(h({ msg: `Waiting ${renewTime} before refreshing tokens` }));
1976
+ await wait(renewTime);
1977
+ await this.autoRefresh(tokensToFetch, csrfToken, errorFn);
1978
+ }
1979
+ async autoRefresh(tokensToFetch, csrfToken, errorFn) {
1980
+ if (this.autoRefreshActive) {
1981
+ let reply = void 0;
1982
+ let success = false;
1983
+ let tries = 0;
1984
+ while (!success && tries <= AUTOREFRESH_RETRIES) {
1985
+ try {
1986
+ let headers = { ...this.headers };
1987
+ if (csrfToken) {
1988
+ headers[this.csrfHeader] = csrfToken;
1989
+ }
1990
+ d.logger.debug(h({ msg: `Initiating auto refresh` }));
1991
+ const resp = await this.tokenProvider.jsonFetchWithToken(
1992
+ this.autoRefreshUrl,
1993
+ {
1994
+ method: "POST",
1995
+ headers: {
1996
+ "Accept": "application/json",
1997
+ "Content-Type": "application/json",
1998
+ ...headers
1999
+ },
2000
+ mode: this.mode,
2001
+ credentials: this.credentials,
2002
+ body: {
2003
+ csrfToken
2004
+ }
2005
+ },
2006
+ "refresh"
2007
+ );
2008
+ if (!resp.ok) {
2009
+ d.logger.error(h({ msg: "Failed auto refreshing tokens", status: resp.status }));
2010
+ }
2011
+ reply = await resp.json();
2012
+ if (reply == null ? void 0 : reply.ok) {
2013
+ await this.scheduleAutoRefresh(tokensToFetch, errorFn);
2014
+ success = true;
2015
+ try {
2016
+ await this.tokenProvider.receiveTokens(reply);
2017
+ } catch (e) {
2018
+ const cerr = g.asCrossauthError(e);
2019
+ if (errorFn) {
2020
+ errorFn("Couldn't receive tokens", cerr);
2021
+ } else {
2022
+ d.logger.debug(h({ err: e }));
2023
+ d.logger.error(h({ msg: "Error receiving tokens", cerr }));
2024
+ }
2025
+ }
2026
+ } else {
2027
+ if (tries < AUTOREFRESH_RETRIES) {
2028
+ d.logger.error(h({ msg: `Failed auto refreshing tokens. Retrying in ${AUTOREFRESH_RETRY_INTERVAL_SECS} seconds` }));
2029
+ let wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2030
+ await wait(AUTOREFRESH_RETRY_INTERVAL_SECS * 1e3);
2031
+ } else {
2032
+ d.logger.error(h({ msg: `Failed auto refreshing tokens. Number of retries exceeded` }));
2033
+ if (errorFn) {
2034
+ errorFn("Failed auto refreshing tokens");
2035
+ }
2036
+ }
2037
+ tries++;
2038
+ }
2039
+ } catch (e) {
2040
+ const ce2 = g.asCrossauthError(e);
2041
+ d.logger.debug(h({ err: ce2 }));
2042
+ if (tries < AUTOREFRESH_RETRIES) {
2043
+ d.logger.error(h({ msg: `Failed auto refreshing tokens. Retrying in ${AUTOREFRESH_RETRIES} seconds` }));
2044
+ let wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2045
+ await wait(AUTOREFRESH_RETRY_INTERVAL_SECS);
2046
+ } else {
2047
+ d.logger.error(h({ msg: `Failed auto refreshing tokens. Number of retries exceeded` }));
2048
+ if (errorFn) {
2049
+ errorFn(ce2.message, ce2);
2050
+ }
2051
+ }
2052
+ tries++;
2053
+ }
2054
+ }
2055
+ }
2056
+ }
2057
+ }
2058
+ class OAuthDeviceCodePoller {
2059
+ /**
2060
+ * Constructor
2061
+ *
2062
+ * @param options
2063
+ * - `deviceCodePollUrl` the URL to call to poll for authorization. Default `/devicecodepoll`
2064
+ * - `mode` overrides the default `mode` in fetch calls
2065
+ * - `credentials` - overrides the default `credentials` for fetch calls
2066
+ * - `headers` - adds headers to fetfh calls
2067
+ */
2068
+ constructor(options) {
2069
+ __publicField(this, "deviceCodePollUrl", "/devicecodepoll");
2070
+ __publicField(this, "headers", {});
2071
+ __publicField(this, "pollingActive", false);
2072
+ __publicField(this, "mode", "cors");
2073
+ __publicField(this, "credentials", "same-origin");
2074
+ __publicField(this, "respectRedirect", true);
2075
+ __publicField(this, "oauthClient");
2076
+ this.oauthClient = options.oauthClient;
2077
+ if (options.deviceCodePollUrl != void 0) this.deviceCodePollUrl = options.deviceCodePollUrl;
2078
+ if (options.headers) this.headers = options.headers;
2079
+ if (options.mode) this.mode = options.mode;
2080
+ if (options.credentials) this.credentials = options.credentials;
2081
+ }
2082
+ async startPolling(deviceCode, pollResultFn, interval = 5) {
2083
+ if (!this.pollingActive) {
2084
+ this.pollingActive = true;
2085
+ d.logger.debug(h({ msg: "Starting auto refresh" }));
2086
+ await this.poll(deviceCode, interval, pollResultFn);
2087
+ }
2088
+ }
2089
+ stopPolling() {
2090
+ this.pollingActive = false;
2091
+ d.logger.debug(h({ msg: "Stopping auto refresh" }));
2092
+ }
2093
+ async poll(deviceCode, interval, pollResultFn) {
2094
+ var _a;
2095
+ if (!deviceCode) {
2096
+ d.logger.debug(h({ msg: "device code poll: no device code provided" }));
2097
+ pollResultFn("error", "Error waiting for authorization");
2098
+ } else {
2099
+ try {
2100
+ d.logger.debug(h({ msg: "device code poll: poll" }));
2101
+ if (!this.deviceCodePollUrl && this.oauthClient) {
2102
+ if (!this.oauthClient.getOidcConfig()) await this.oauthClient.loadConfig();
2103
+ if (!((_a = this.oauthClient.getOidcConfig()) == null ? void 0 : _a.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-oob"))) {
2104
+ return {
2105
+ error: "invalid_request",
2106
+ error_description: "Server does not support password_mfa grant"
2107
+ };
2108
+ }
2109
+ let config = this.oauthClient.getOidcConfig();
2110
+ if (!(config == null ? void 0 : config.token_endpoint)) return {
2111
+ error: "server_error",
2112
+ error_description: "Couldn't get OIDC configuration"
2113
+ };
2114
+ this.deviceCodePollUrl = config.token_endpoint;
2115
+ }
2116
+ if (!this.deviceCodePollUrl) {
2117
+ return {
2118
+ error: "server_error",
2119
+ error_description: "Must either provide deviceCodePollUrl or an oauthClient to fetch it from"
2120
+ };
2121
+ }
2122
+ const resp = await fetch(this.deviceCodePollUrl, {
2123
+ method: "POST",
2124
+ body: JSON.stringify({ device_code: deviceCode }),
2125
+ headers: { "content-type": "application/json" }
2126
+ });
2127
+ if (resp.redirected) {
2128
+ this.pollingActive = false;
2129
+ if (resp.redirected) {
2130
+ pollResultFn("completeAndRedirect", void 0, resp.url);
2131
+ }
2132
+ } else if (!resp.ok) {
2133
+ this.pollingActive = false;
2134
+ pollResultFn("error", "Received an error from the authorization server");
2135
+ } else {
2136
+ const body = await resp.json();
2137
+ d.logger.debug(h({ msg: "device code poll: received" + JSON.stringify(body) }));
2138
+ if (body.error == "expired_token") {
2139
+ this.pollingActive = false;
2140
+ pollResultFn("expired_token", "Timeout waiting for authorization");
2141
+ } else if (body.error == "authorization_pending" || body.error == "slow_down") {
2142
+ if (body.error == "slow_down") interval += 5;
2143
+ let waitseconds = body.interval ?? interval;
2144
+ let wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2145
+ d.logger.debug(h({ msg: "device code poll: waiting " + String(waitseconds) + " seconds" }));
2146
+ await wait(waitseconds * 1e3);
2147
+ if (this.pollingActive) this.poll(deviceCode, interval, pollResultFn);
2148
+ } else if (body.error) {
2149
+ this.pollingActive = false;
2150
+ pollResultFn("error", body.error_description ?? body.error);
2151
+ } else {
2152
+ this.pollingActive = false;
2153
+ pollResultFn("complete");
2154
+ }
2155
+ }
2156
+ } catch (e) {
2157
+ this.pollingActive = false;
2158
+ const ce2 = g.asCrossauthError(e);
2159
+ d.logger.debug(h({ err: ce2 }));
2160
+ d.logger.error(h({ msg: "Polling failed", cerr: ce2 }));
2161
+ pollResultFn("error", ce2.message);
2162
+ }
2163
+ }
2164
+ }
2165
+ }
2166
+ class OAuthBffClient {
2167
+ /**
2168
+ * Constructor
2169
+ *
2170
+ * @param options
2171
+ * - `bffPrefix` the base url for BFF calls to the OAuth client
2172
+ * (eg `bff`, which is the default)
2173
+ * - `csrfHeader` the header to put CSRF tokens into
2174
+ * (default `X-CROSSAUTH-CSRF`))
2175
+ * - `getCsrfTokenUrl` URL to use to fetch CSRF tokens. Default is
2176
+ * `/api/getcsrftoken`
2177
+ * - `autoRefreshUrl` URL to use to refresh tokens. Default is
2178
+ * `/api/refreshtokens`
2179
+ * - `tokensUrl` URL to use to fetch token payloads. Default is
2180
+ * `/tokens`
2181
+ * - `deviceCodePollUrl` URL for polling for device code authorization.
2182
+ * Default is `/devicecodepoll`
2183
+ * - `mode` overrides the default `mode` in fetch calls
2184
+ * - `credentials` - overrides the default `credentials` for fetch calls
2185
+ * - `headers` - adds headers to fetfh calls
2186
+ */
2187
+ constructor(options = {}) {
2188
+ __publicField(this, "bffPrefix", "/bff");
2189
+ __publicField(this, "csrfHeader", "X-CROSSAUTH-CSRF");
2190
+ __publicField(this, "enableCsrfProtection", true);
2191
+ __publicField(this, "headers", {});
2192
+ __publicField(this, "mode", "cors");
2193
+ __publicField(this, "credentials", "same-origin");
2194
+ __publicField(this, "autoRefresher");
2195
+ __publicField(this, "deviceCodePoller");
2196
+ __publicField(this, "getCsrfTokenUrl", "/api/getcsrftoken");
2197
+ __publicField(this, "autoRefreshUrl", "/api/refreshtokens");
2198
+ __publicField(this, "tokensUrl", "/tokens");
2199
+ if (options.bffPrefix) this.bffPrefix = options.bffPrefix;
2200
+ if (options.csrfHeader) this.csrfHeader = options.csrfHeader;
2201
+ if (options.enableCsrfProtection != void 0) this.enableCsrfProtection = options.enableCsrfProtection;
2202
+ if (options.getCsrfTokenUrl) this.getCsrfTokenUrl = options.getCsrfTokenUrl;
2203
+ if (options.tokensUrl) this.tokensUrl = options.tokensUrl;
2204
+ if (options.autoRefreshUrl) this.autoRefreshUrl = options.autoRefreshUrl;
2205
+ if (!this.bffPrefix.endsWith("/")) this.bffPrefix += "/";
2206
+ if (options.headers) this.headers = options.headers;
2207
+ if (options.mode) this.mode = options.mode;
2208
+ if (options.credentials) this.credentials = options.credentials;
2209
+ this.autoRefresher = new OAuthAutoRefresher({
2210
+ ...options,
2211
+ autoRefreshUrl: this.autoRefreshUrl,
2212
+ tokenProvider: this
2213
+ });
2214
+ this.deviceCodePoller = new OAuthDeviceCodePoller({ ...options, oauthClient: void 0 });
2215
+ }
2216
+ /**
2217
+ * Gets a CSRF token from the server
2218
+ * @returns the CSRF token that can be included in
2219
+ * the `X-CROSSAUTH-CSRF` header
2220
+ */
2221
+ async getCsrfToken() {
2222
+ if (!this.enableCsrfProtection) return void 0;
2223
+ try {
2224
+ const resp = await fetch(this.getCsrfTokenUrl, {
2225
+ headers: this.headers,
2226
+ credentials: this.credentials,
2227
+ mode: this.mode
2228
+ });
2229
+ const json = await resp.json();
2230
+ if (!json.ok) throw g.asCrossauthError(json);
2231
+ return json.csrfToken;
2232
+ } catch (e) {
2233
+ throw g.asCrossauthError(e);
2234
+ }
2235
+ }
2236
+ /**
2237
+ * Fetches the ID token from the client.
2238
+ *
2239
+ * This only returns something if the ID token was returned to the BFF
2240
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
2241
+ *
2242
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2243
+ * making the request
2244
+ * @returns the ID token payload or an empty object if there isn't one
2245
+ */
2246
+ async getIdToken(csrfToken) {
2247
+ const tokens = await this.getTokens(csrfToken);
2248
+ return (tokens == null ? void 0 : tokens.id_token) ?? null;
2249
+ }
2250
+ /**
2251
+ * Returns whether or not there is an ID token stored in the BFF server
2252
+ * for this client.
2253
+ *
2254
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2255
+ * making the request
2256
+ * @returns true or false
2257
+ */
2258
+ async haveIdToken(csrfToken) {
2259
+ const tokens = await this.getTokens(csrfToken);
2260
+ if (tokens == null) return false;
2261
+ if (tokens.have_id_token != void 0) return tokens.have_id_token;
2262
+ return "id_token" in tokens;
2263
+ }
2264
+ /**
2265
+ * Fetches the access token from the client.
2266
+ *
2267
+ * This only returns something if the access token was returned to the BFF
2268
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
2269
+ *
2270
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2271
+ * making the request
2272
+ * @param headers any additional headers to add (will be added to
2273
+ * the ones given with {@link OAuthBffClient.addHeader} )
2274
+ * @returns the access token payload or an empty object if there isn't one
2275
+ */
2276
+ async getAccessToken(csrfToken) {
2277
+ const tokens = await this.getTokens(csrfToken);
2278
+ return (tokens == null ? void 0 : tokens.access_token) ?? null;
2279
+ }
2280
+ /**
2281
+ * Returns whether or not there is an access token stored in the BFF server
2282
+ * for this client.
2283
+ *
2284
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2285
+ * making the request
2286
+ * @returns true or false
2287
+ */
2288
+ async haveAccessToken(csrfToken) {
2289
+ const tokens = await this.getTokens(csrfToken);
2290
+ if (tokens == null) return false;
2291
+ if (tokens.have_access_token != void 0) return tokens.have_access_token;
2292
+ return "access_token" in tokens;
2293
+ }
2294
+ /**
2295
+ * Fetches the refresh token from the client.
2296
+ *
2297
+ * This only returns something if the refresh token was returned to the BFF
2298
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
2299
+ *
2300
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2301
+ * making the request
2302
+ * @returns the refresh token payload or an empty object if there isn't one
2303
+ */
2304
+ async getRefreshToken(csrfToken) {
2305
+ const tokens = await this.getTokens(csrfToken);
2306
+ return (tokens == null ? void 0 : tokens.refresh_token) ?? null;
2307
+ }
2308
+ /**
2309
+ * Returns whether or not there is a refresh token stored in the BFF server
2310
+ * for this client.
2311
+ *
2312
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
2313
+ * making the request
2314
+ * @returns true or false
2315
+ */
2316
+ async haveRefreshToken(csrfToken) {
2317
+ const tokens = await this.getTokens(csrfToken);
2318
+ if (tokens == null) return false;
2319
+ if (tokens.have_refresh_token != void 0) return tokens.have_refresh_token;
2320
+ return "refresh_token" in tokens;
2321
+ }
2322
+ /**
2323
+ * Calls an API endpoint via the BFF server
2324
+ * @param method the HTTP method
2325
+ * @param endpoint the endpoint to call, relative to `bffPrefix`
2326
+ * @param body : the body to pass to the call
2327
+ * @param csrfToken : the CSRF token
2328
+ * @returns the HTTP status code and the body or null
2329
+ */
2330
+ async api(method, endpoint, body, csrfToken) {
2331
+ let headers = { ...this.headers };
2332
+ if (!csrfToken && !["GET", "HEAD", "OPTIONS"].includes(method)) {
2333
+ csrfToken = await this.getCsrfToken();
2334
+ if (csrfToken) headers[this.csrfHeader] = csrfToken;
2335
+ }
2336
+ if (endpoint.startsWith("/")) endpoint = endpoint.substring(1);
2337
+ let params = {};
2338
+ if (body) params.body = JSON.stringify(body);
2339
+ const resp = await fetch(
2340
+ this.bffPrefix + endpoint,
2341
+ {
2342
+ headers,
2343
+ method,
2344
+ mode: this.mode,
2345
+ credentials: this.credentials,
2346
+ ...params
2347
+ }
2348
+ );
2349
+ let responseBody = null;
2350
+ if (resp.body) responseBody = await resp.json();
2351
+ return { status: resp.status, body: responseBody };
2352
+ }
2353
+ /**
2354
+ * Return all tokens that the client has been enabled to return.
2355
+ *
2356
+ * @param csrfToken the CSRF token if one is needed
2357
+ * @returns an object with the following (whichever are enabled at the client)
2358
+ * - `id_token`
2359
+ * - `access_token`
2360
+ * - `refresh_token`
2361
+ * - `have_id_token`
2362
+ * - `have_access_token`
2363
+ * - `have_refresh_token`
2364
+ */
2365
+ async getTokens(csrfToken) {
2366
+ if (!csrfToken) csrfToken = await this.getCsrfToken();
2367
+ let headers = { ...this.headers };
2368
+ if (csrfToken)
2369
+ headers[this.csrfHeader] = csrfToken;
2370
+ try {
2371
+ const resp = await fetch(this.tokensUrl, {
2372
+ method: "POST",
2373
+ headers,
2374
+ mode: this.mode,
2375
+ credentials: this.credentials
2376
+ });
2377
+ if (resp.status == 204) {
2378
+ return {};
2379
+ }
2380
+ const body = await resp.json();
2381
+ return body;
2382
+ } catch (e) {
2383
+ throw g.asCrossauthError(e);
2384
+ }
2385
+ }
2386
+ /**
2387
+ * Turns auto refresh of tokens on
2388
+ * @param tokensToFetch which tokens to fetch
2389
+ * @param errorFn what to call in case of error
2390
+ */
2391
+ async startAutoRefresh(tokensToFetch = ["access", "id"], errorFn) {
2392
+ return this.autoRefresher.startAutoRefresh(tokensToFetch, errorFn);
2393
+ }
2394
+ /**
2395
+ * Turns auto refresh of tokens off
2396
+ */
2397
+ stopAutoRefresh() {
2398
+ return this.autoRefresher.stopAutoRefresh();
2399
+ }
2400
+ /**
2401
+ * Turns polling for a device code
2402
+ * @param tokensToFetch which tokens to fetch
2403
+ * @param errorFn what to call in case of error
2404
+ */
2405
+ async startDeviceCodePolling(deviceCode, pollResultFn, interval = 5) {
2406
+ return this.deviceCodePoller.startPolling(deviceCode, pollResultFn, interval);
2407
+ }
2408
+ /**
2409
+ * Turns off polling for a device code
2410
+ */
2411
+ stopDeviceCodePolling() {
2412
+ return this.deviceCodePoller.stopPolling();
2413
+ }
2414
+ ///////////////////////////////////////////////////////////
2415
+ // OAuthTokenProvider interface
2416
+ /**
2417
+ * Fetches the expiry times for each token.
2418
+ * @param crfToken the CSRF token. If emtpy
2419
+ * , one will be fetched before
2420
+ * making the request
2421
+ * @returns for each token, either the expiry, `null` if it does not
2422
+ * expire, or `undefined` if the token does not exist
2423
+ */
2424
+ async getTokenExpiries(tokensToFetch, csrfToken) {
2425
+ const tokens = await this.getTokens(csrfToken);
2426
+ const idToken = tokensToFetch.includes("id") ? (tokens == null ? void 0 : tokens.id_token) ?? null : null;
2427
+ const accessToken = tokensToFetch.includes("access") ? (tokens == null ? void 0 : tokens.access_token) ?? null : null;
2428
+ const refreshToken = tokensToFetch.includes("refresh") ? (tokens == null ? void 0 : tokens.refresh_token) ?? null : null;
2429
+ let idTokenExpiry = void 0;
2430
+ let accessTokenExpiry = void 0;
2431
+ let refreshTokenExpiry = void 0;
2432
+ if (idToken) {
2433
+ idTokenExpiry = idToken.exp ? idToken.exp : null;
2434
+ }
2435
+ if (accessToken) {
2436
+ accessTokenExpiry = accessToken.exp ? accessToken.exp : null;
2437
+ }
2438
+ if (refreshToken) {
2439
+ refreshTokenExpiry = refreshToken.exp ? refreshToken.exp : null;
2440
+ }
2441
+ return {
2442
+ id: idTokenExpiry,
2443
+ access: accessTokenExpiry,
2444
+ refresh: refreshTokenExpiry
2445
+ };
2446
+ }
2447
+ /**
2448
+ * Makes a fetch, adding in the requested token
2449
+ * @param url the URL to fetch
2450
+ * @param params parameters to add to the fetch
2451
+ * @param token which token to add
2452
+ * @returns parsed JSON response
2453
+ */
2454
+ async jsonFetchWithToken(url, params, _token) {
2455
+ if (typeof params.body != "string") params.body = JSON.stringify(params.body);
2456
+ return await fetch(url, params);
2457
+ }
2458
+ receiveTokens(_tokens) {
2459
+ return new Promise((_resolve) => {
2460
+ });
2461
+ }
2462
+ }
2463
+ class OAuthTokenConsumer extends Le {
2464
+ /**
2465
+ * SHA256 and Base64-url-encodes the given test
2466
+ * @param plaintext the text to encode
2467
+ * @returns the SHA256 hash, Base64-url-encode
2468
+ */
2469
+ async hash(plaintext) {
2470
+ const encoder = new TextEncoder();
2471
+ const data = encoder.encode(plaintext);
2472
+ const hash = await crypto.subtle.digest("SHA-256", data);
2473
+ const hashArray = Array.from(new Uint8Array(hash));
2474
+ return btoa(hashArray.reduce((acc, current) => acc + String.fromCharCode(current), "")).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
2475
+ }
2476
+ }
2477
+ class OAuthClient extends Be {
2478
+ /**
2479
+ * Constructor
2480
+ *
2481
+ * @param options
2482
+ * - `authServerBaseUrl` the base url the authorization server.
2483
+ * For example, the authorize endpoint would be
2484
+ * `authServerBaseUrl + "authorize"`.
2485
+ * Required: no default
2486
+ * - `resServerBaseUrl` the base url the resource server.
2487
+ * For example, Relative URLs to the resource server are relative
2488
+ * to this. If you always give absolute URLs, this is optional.
2489
+ * If you don't give it and you do make relative URLs, it will be
2490
+ * relative to the page you are on. Default: empty string.
2491
+ * - `redirect_uri` a URL on the site serving this app which the
2492
+ * authorization server will redirect to with an authorization
2493
+ * code. See description in class documentation.
2494
+ * This is not required if you are not using OAuth flows
2495
+ * which require a redirect URI (eg the password flow).
2496
+ * - `accessTokenResponseType` where to store access tokens. See
2497
+ * class documentation. Default `return`.
2498
+ * - `refreshTokenResponseType` where to store refresh tokens. See
2499
+ * class documentation. Default `return`.
2500
+ * - `idTokenResponseType` where to store id tokens. See
2501
+ * class documentation. Default `return`.
2502
+ * - `accessTokenName` name for access token in local or session
2503
+ * storage, depending on `accessTokenResponseType`
2504
+ * - `refreshTokenName` name for refresh token in local or session
2505
+ * storage, depending on `refreshTokenResponseType`
2506
+ * - `idTokenName` name for id token in local or session
2507
+ * storage, depending on `idTokenResponseType`
2508
+ * - `mresServerMode` overrides the default `mode` in fetch calls
2509
+ * - `resServerCredentials` - overrides the default `credentials` for fetch calls
2510
+ * - `resServerHeaders` - adds headers to fetfh calls
2511
+ * - `autoRefresh` - if set and tokens are present in local or session storage,
2512
+ * automatically turn on auto refresh
2513
+ * - `deviceAuthorization` URL, relative to the authorization server base,
2514
+ * for starting the device code flow. Default `device_authorization`
2515
+ * Default is `/devicecodepoll`
2516
+ * For other options see {@link @crossauth/common/OAuthClientBase}.
2517
+ */
2518
+ constructor(options) {
2519
+ if (!options.tokenConsumer) {
2520
+ options.tokenConsumer = new OAuthTokenConsumer(
2521
+ options.client_id,
2522
+ {
2523
+ authServerBaseUrl: options.authServerBaseUrl
2524
+ }
2525
+ );
2526
+ }
2527
+ super(options);
2528
+ __publicField(this, "resServerBaseUrl", "");
2529
+ __publicField(this, "resServerHeaders", {});
2530
+ __publicField(this, "resServerMode", "cors");
2531
+ __publicField(this, "resServerCredentials", "same-origin");
2532
+ __publicField(this, "accessTokenResponseType", "memory");
2533
+ __publicField(this, "refreshTokenResponseType", "memory");
2534
+ __publicField(this, "idTokenResponseType", "memory");
2535
+ __publicField(this, "accessTokenName", "CROSSAUTH_AT");
2536
+ __publicField(this, "refreshTokenName", "CROSSAUTH_RT");
2537
+ __publicField(this, "idTokenName", "CROSSAUTH_IT");
2538
+ __privateAdd(this, _accessToken);
2539
+ __privateAdd(this, _refreshToken);
2540
+ __privateAdd(this, _idTokenPayload);
2541
+ __privateAdd(this, _accessTokenPayload);
2542
+ __privateAdd(this, _refreshTokenPayload);
2543
+ __privateAdd(this, _client_id);
2544
+ __privateAdd(this, _client_secret);
2545
+ __publicField(this, "autoRefresher");
2546
+ __publicField(this, "deviceCodePoller");
2547
+ __publicField(this, "deviceAuthorizationUrl", "device_authorization");
2548
+ if (this.resServerBaseUrl != void 0) {
2549
+ this.resServerBaseUrl = options.resServerBaseUrl ?? "";
2550
+ if (this.resServerBaseUrl.length > 0 && !this.resServerBaseUrl.endsWith("/")) {
2551
+ this.resServerBaseUrl += "/";
2552
+ }
2553
+ }
2554
+ if (options.accessTokenResponseType) this.accessTokenResponseType = options.accessTokenResponseType;
2555
+ if (options.idTokenResponseType) this.idTokenResponseType = options.idTokenResponseType;
2556
+ if (options.refreshTokenResponseType) this.refreshTokenResponseType = options.refreshTokenResponseType;
2557
+ if (options.accessTokenName) this.accessTokenName = options.accessTokenName;
2558
+ if (options.idTokenName) this.idTokenName = options.idTokenName;
2559
+ if (options.refreshTokenName) this.refreshTokenName = options.refreshTokenName;
2560
+ if (options.resServerHeaders) this.resServerHeaders = options.resServerHeaders;
2561
+ if (options.resServerMode) this.resServerMode = options.resServerMode;
2562
+ if (options.resServerCredentials) this.resServerCredentials = options.resServerCredentials;
2563
+ if (options.client_id) __privateSet(this, _client_id, options.client_id);
2564
+ if (options.client_secret) __privateSet(this, _client_secret, options.client_secret);
2565
+ if (options.deviceAuthorizationUrl) this.deviceAuthorizationUrl = options.deviceAuthorizationUrl;
2566
+ this.autoRefresher = new OAuthAutoRefresher({
2567
+ ...options,
2568
+ autoRefreshUrl: this.authServerBaseUrl + "/token",
2569
+ tokenProvider: this
2570
+ });
2571
+ this.deviceCodePoller = new OAuthDeviceCodePoller({ ...options, oauthClient: this, deviceCodePollUrl: null });
2572
+ let idToken;
2573
+ let accessToken;
2574
+ let refreshToken;
2575
+ if (this.idTokenResponseType == "sessionStorage") {
2576
+ idToken = sessionStorage.getItem(this.idTokenName);
2577
+ } else if (this.idTokenResponseType == "localStorage") {
2578
+ idToken = localStorage.getItem(this.idTokenName);
2579
+ }
2580
+ if (this.accessTokenResponseType == "sessionStorage") {
2581
+ accessToken = sessionStorage.getItem(this.accessTokenName);
2582
+ } else if (this.accessTokenResponseType == "localStorage") {
2583
+ accessToken = localStorage.getItem(this.accessTokenName);
2584
+ }
2585
+ if (this.refreshTokenResponseType == "sessionStorage") {
2586
+ refreshToken = sessionStorage.getItem(this.refreshTokenName);
2587
+ } else if (this.refreshTokenResponseType == "localStorage") {
2588
+ refreshToken = localStorage.getItem(this.refreshTokenName);
2589
+ }
2590
+ this.receiveTokens({
2591
+ access_token: accessToken,
2592
+ id_token: idToken,
2593
+ refresh_token: refreshToken
2594
+ });
2595
+ if (accessToken) {
2596
+ const payload = this.getTokenPayload(accessToken);
2597
+ if (payload) {
2598
+ __privateSet(this, _accessToken, accessToken);
2599
+ __privateSet(this, _accessTokenPayload, payload);
2600
+ }
2601
+ }
2602
+ if (refreshToken) {
2603
+ const payload = this.getTokenPayload(refreshToken);
2604
+ if (payload) {
2605
+ __privateSet(this, _refreshToken, refreshToken);
2606
+ __privateSet(this, _refreshTokenPayload, payload);
2607
+ }
2608
+ }
2609
+ if (idToken) {
2610
+ this.validateIdToken(idToken).then((payload) => {
2611
+ __privateSet(this, _idTokenPayload, payload);
2612
+ if (options.autoRefresh) {
2613
+ this.startAutoRefresh(options.autoRefresh).then().catch((err) => {
2614
+ d.logger.debug(h({ err, msg: "Couldn't start auto refresh" }));
2615
+ });
2616
+ }
2617
+ }).catch((err) => {
2618
+ d.logger.debug(h({ err, msg: "Couldn't validate ID token" }));
2619
+ });
2620
+ } else if (__privateGet(this, _accessToken) && options.autoRefresh && refreshToken) {
2621
+ this.startAutoRefresh(options.autoRefresh).then().catch((err) => {
2622
+ d.logger.debug(h({ err, msg: "Couldn't start auto refresh" }));
2623
+ });
2624
+ } else if (refreshToken && !accessToken) {
2625
+ this.refreshTokenFlow(refreshToken).then((_resp) => {
2626
+ d.logger.debug(h({ msg: "Refreshed tokens" }));
2627
+ if (options.autoRefresh) {
2628
+ this.startAutoRefresh(options.autoRefresh).then().catch((err) => {
2629
+ d.logger.debug(h({ err, msg: "Couldn't start auto refresh" }));
2630
+ });
2631
+ }
2632
+ }).catch((err) => {
2633
+ const ce2 = g.asCrossauthError(err);
2634
+ d.logger.debug(h({ err: ce2 }));
2635
+ d.logger.error(h({ msg: "failed refreshing tokens", cerr: ce2 }));
2636
+ });
2637
+ }
2638
+ }
2639
+ get idTokenPayload() {
2640
+ return __privateGet(this, _idTokenPayload);
2641
+ }
2642
+ /**
2643
+ * Processes the query parameters for a Redirect URI request if they
2644
+ * exist in the URL.
2645
+ *
2646
+ * Call this on page load to see if it was called as redirect URI.
2647
+ *
2648
+ * If this URL doesn't match the redirect URI passed in the constructor,
2649
+ * or this URL was not called with OAuth Redirect URI query parameters,
2650
+ * undefined is returned.
2651
+ *
2652
+ * If this URL contains the error query parameter, `errorFn` is called.
2653
+ * It is also called if the state does not match.
2654
+ *
2655
+ * If an authorization code was in the query parameters, the token
2656
+ * endpoint is called. Depending on whether that returned an error,
2657
+ * either `receiveTokenFn` or `errorFn` will be called.
2658
+ *
2659
+ * @param receiveTokenFn if defined, called if a token is returned.
2660
+ *
2661
+ * @param errorFn if defined, called if any OAuth endpoint returned `error`,
2662
+ * or if the `state` was not correct.
2663
+ *
2664
+ * @returns the result of `receiveTokenFn`, `errorFn` or `undefined`. If
2665
+ * `receiveTokenFn`/`errorFn` is not defined, rather than calling
2666
+ * it, this function just returns the OAuth response.
2667
+ *
2668
+ */
2669
+ async handleRedirectUri() {
2670
+ const url = new URL(window.location.href);
2671
+ if (url.origin + url.pathname != this.redirect_uri) return void 0;
2672
+ const params = new URLSearchParams(window.location.search);
2673
+ let code = void 0;
2674
+ let state = void 0;
2675
+ let error = void 0;
2676
+ let error_description = void 0;
2677
+ for (const [key, value] of params) {
2678
+ if (key == "code") code = value;
2679
+ if (key == "state") state = value;
2680
+ if (key == "error") error = value;
2681
+ if (key == "error_description") error_description = value;
2682
+ }
2683
+ if (!error && !code) return void 0;
2684
+ if (error) {
2685
+ const cerr = g.fromOAuthError(error, error_description);
2686
+ d.logger.debug(h({ err: cerr }));
2687
+ d.logger.error(h({ cerr, msg: "Error from authorize endpoint: " + error }));
2688
+ throw cerr;
2689
+ }
2690
+ const resp = await this.redirectEndpoint(code, state, error, error_description);
2691
+ if (resp.error) {
2692
+ const cerr = g.fromOAuthError(resp.error, error_description);
2693
+ d.logger.debug(h({ err: cerr }));
2694
+ d.logger.error(h({ cerr, msg: "Error from redirect endpoint: " + resp.error }));
2695
+ throw cerr;
2696
+ }
2697
+ await this.receiveTokens(resp);
2698
+ return resp;
2699
+ }
2700
+ /**
2701
+ * Turns auto refresh of tokens on
2702
+ * @param tokensToFetch which tokens to fetch
2703
+ * @param errorFn what to call in case of error
2704
+ */
2705
+ async startAutoRefresh(tokensToFetch = ["access", "id"], errorFn) {
2706
+ return this.autoRefresher.startAutoRefresh(tokensToFetch, errorFn);
2707
+ }
2708
+ /**
2709
+ * Turns auto refresh of tokens off
2710
+ */
2711
+ stopAutoRefresh() {
2712
+ return this.autoRefresher.stopAutoRefresh();
2713
+ }
2714
+ /**
2715
+ * Turns polling for a device code
2716
+ * @param tokensToFetch which tokens to fetch
2717
+ * @param errorFn what to call in case of error
2718
+ */
2719
+ async startDeviceCodePolling(deviceCode, pollResultFn, interval = 5) {
2720
+ return this.deviceCodePoller.startPolling(deviceCode, pollResultFn, interval);
2721
+ }
2722
+ /**
2723
+ * Turns off polling for a device code
2724
+ */
2725
+ stopDeviceCodePolling() {
2726
+ return this.deviceCodePoller.stopPolling();
2727
+ }
2728
+ /**
2729
+ * Return the ID token payload
2730
+ *
2731
+ * This does the same thign as {@link idTokenPayload}. We have it here
2732
+ * as well for consistency with {@link OAuthBffClient}.
2733
+ *
2734
+ * @returns the payload as an object
2735
+ */
2736
+ getIdToken() {
2737
+ return __privateGet(this, _idTokenPayload);
2738
+ }
2739
+ ///////
2740
+ // Implementation of abstract methods
2741
+ /**
2742
+ * Produce a random Base64-url-encoded string, whose length before
2743
+ * base64-url-encoding is the given length,
2744
+ * @param length the length of the random array before base64-url-encoding.
2745
+ * @returns the random value as a Base64-url-encoded srting
2746
+ */
2747
+ randomValue(length) {
2748
+ const array = new Uint8Array(length);
2749
+ self.crypto.getRandomValues(array);
2750
+ return btoa(array.reduce((acc, current) => acc + String.fromCharCode(current), "")).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
2751
+ }
2752
+ /**
2753
+ * SHA256 and Base64-url-encodes the given test
2754
+ * @param plaintext the text to encode
2755
+ * @returns the SHA256 hash, Base64-url-encode
2756
+ */
2757
+ async sha256(plaintext) {
2758
+ const encoder = new TextEncoder();
2759
+ const data = encoder.encode(plaintext);
2760
+ const hash = await crypto.subtle.digest("SHA-256", data);
2761
+ const hashArray = Array.from(new Uint8Array(hash));
2762
+ return btoa(hashArray.reduce((acc, current) => acc + String.fromCharCode(current), "")).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
2763
+ }
2764
+ /**
2765
+ * Calls an API endpoint on the resource server
2766
+ * @param method the HTTP method
2767
+ * @param endpoint the endpoint to call, relative to `resServerBaseUrl`
2768
+ * @param body : the body to pass to the call
2769
+ * @returns the HTTP status code and the body or null
2770
+ */
2771
+ async api(method, endpoint, body) {
2772
+ let headers = { ...this.resServerHeaders };
2773
+ if (endpoint.startsWith("/")) endpoint = endpoint.substring(1);
2774
+ let params = {};
2775
+ if (body) params.body = JSON.stringify(body);
2776
+ let accessToken;
2777
+ if (this.accessTokenResponseType == "sessionStorage") {
2778
+ accessToken = sessionStorage.getItem(this.accessTokenName);
2779
+ } else if (this.accessTokenResponseType == "localStorage") {
2780
+ accessToken = localStorage.getItem(this.accessTokenName);
2781
+ }
2782
+ headers.authorization = "Bearer " + accessToken;
2783
+ const resp = await fetch(
2784
+ this.resServerBaseUrl + endpoint,
2785
+ {
2786
+ headers,
2787
+ method,
2788
+ mode: this.resServerMode,
2789
+ credentials: this.resServerCredentials,
2790
+ ...params
2791
+ }
2792
+ );
2793
+ let responseBody = null;
2794
+ if (resp.body) responseBody = await resp.json();
2795
+ return { status: resp.status, body: responseBody };
2796
+ }
2797
+ ///////////////////////////////////////////////////////////
2798
+ // OAuthTokenProvider interface
2799
+ /**
2800
+ * Fetches the expiry times for each token.
2801
+ * @param crfToken the CSRF token. If emtpy
2802
+ * , one will be fetched before
2803
+ * making the request
2804
+ * @returns for each token, either the expiry, `null` if it does not
2805
+ * expire, or `undefined` if the token does not exist
2806
+ */
2807
+ async getTokenExpiries(_tokensToFetch, _csrfToken) {
2808
+ let idTokenExpiry = void 0;
2809
+ let accessTokenExpiry = void 0;
2810
+ let refreshTokenExpiry = void 0;
2811
+ if (__privateGet(this, _idTokenPayload)) {
2812
+ idTokenExpiry = __privateGet(this, _idTokenPayload).exp ? __privateGet(this, _idTokenPayload).exp : null;
2813
+ }
2814
+ if (__privateGet(this, _accessTokenPayload)) {
2815
+ accessTokenExpiry = __privateGet(this, _accessTokenPayload).exp ? __privateGet(this, _accessTokenPayload).exp : null;
2816
+ }
2817
+ if (__privateGet(this, _refreshTokenPayload)) {
2818
+ refreshTokenExpiry = __privateGet(this, _refreshTokenPayload).exp ? __privateGet(this, _refreshTokenPayload).exp : null;
2819
+ }
2820
+ return {
2821
+ id: idTokenExpiry,
2822
+ access: accessTokenExpiry,
2823
+ refresh: refreshTokenExpiry
2824
+ };
2825
+ }
2826
+ /**
2827
+ * Makes a fetch, adding in the requested token.
2828
+ *
2829
+ * Also adds client ID and secret if they are defined.
2830
+ *
2831
+ * @param url the URL to fetch
2832
+ * @param params parameters to add to the fetch
2833
+ * @param token which token to add
2834
+ * @returns parsed JSON response
2835
+ */
2836
+ async jsonFetchWithToken(url, params, token) {
2837
+ if (token == "access") {
2838
+ if (!__privateGet(this, _accessToken)) {
2839
+ throw new g(y.InvalidToken, "Cannot make fetch with access token - no access token defined");
2840
+ }
2841
+ if (!params.headers) params.headers = {};
2842
+ params.headers.authorization = "Bearer " + __privateGet(this, _accessToken);
2843
+ } else {
2844
+ if (!params.body) params.body = {};
2845
+ if (!__privateGet(this, _refreshToken)) {
2846
+ throw new g(y.InvalidToken, "Cannot make fetch with refresh token - no refresh token defined");
2847
+ }
2848
+ params.body.refresh_token = __privateGet(this, _refreshToken);
2849
+ params.body.grant_type = "refresh_token";
2850
+ }
2851
+ if (__privateGet(this, _client_id)) {
2852
+ if (!params.body) params.body = {};
2853
+ params.body.client_id = __privateGet(this, _client_id);
2854
+ if (__privateGet(this, _client_secret)) {
2855
+ params.body.client_secret = __privateGet(this, _client_secret);
2856
+ }
2857
+ }
2858
+ if (typeof params.body != "string") params.body = JSON.stringify(params.body);
2859
+ return await fetch(url, params);
2860
+ }
2861
+ /**
2862
+ * Does nothing as CSRF tokens are not needed for this class
2863
+ * @returns `undefined`
2864
+ */
2865
+ async getCsrfToken() {
2866
+ return void 0;
2867
+ }
2868
+ async receiveTokens(tokens) {
2869
+ if (tokens.access_token) {
2870
+ const payload = this.getTokenPayload(tokens.access_token);
2871
+ if (payload) {
2872
+ __privateSet(this, _accessToken, tokens.access_token);
2873
+ __privateSet(this, _accessTokenPayload, payload);
2874
+ }
2875
+ if (this.accessTokenResponseType == "localStorage") {
2876
+ localStorage.setItem(this.accessTokenName, tokens.access_token);
2877
+ } else if (this.accessTokenResponseType == "sessionStorage") {
2878
+ sessionStorage.setItem(this.accessTokenName, tokens.access_token);
2879
+ }
2880
+ }
2881
+ if (tokens.refresh_token) {
2882
+ const payload = this.getTokenPayload(tokens.refresh_token);
2883
+ if (payload) {
2884
+ __privateSet(this, _refreshToken, tokens.refresh_token);
2885
+ __privateSet(this, _refreshTokenPayload, payload);
2886
+ }
2887
+ if (this.refreshTokenResponseType == "localStorage") {
2888
+ localStorage.setItem(this.refreshTokenName, tokens.refresh_token);
2889
+ } else if (this.accessTokenResponseType == "sessionStorage") {
2890
+ sessionStorage.setItem(this.refreshTokenName, tokens.refresh_token);
2891
+ }
2892
+ }
2893
+ if (tokens.id_token) {
2894
+ const payload = await this.validateIdToken(tokens.id_token);
2895
+ __privateSet(this, _idTokenPayload, payload);
2896
+ if (this.idTokenResponseType == "localStorage") {
2897
+ localStorage.setItem(this.idTokenName, tokens.id_token);
2898
+ } else if (this.idTokenResponseType == "sessionStorage") {
2899
+ sessionStorage.setItem(this.idTokenName, tokens.id_token);
2900
+ }
2901
+ }
2902
+ }
2903
+ /////////
2904
+ // Wrap flow functions
2905
+ /**
2906
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2907
+ * then saves the tokens, as per the requested method
2908
+ * @param scope
2909
+ */
2910
+ async clientCredentialsFlow(scope) {
2911
+ const resp = await super.clientCredentialsFlow(scope);
2912
+ await this.receiveTokens(resp);
2913
+ return resp;
2914
+ }
2915
+ /**
2916
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2917
+ * then saves the tokens, as per the requested method
2918
+ * @param scope
2919
+ */
2920
+ async passwordFlow(username, password, scope) {
2921
+ const resp = await super.passwordFlow(username, password, scope);
2922
+ await this.receiveTokens(resp);
2923
+ return resp;
2924
+ }
2925
+ /**
2926
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2927
+ * then saves the tokens, as per the requested method
2928
+ * @param scope
2929
+ */
2930
+ async deviceCodeFlow(scope) {
2931
+ let url = this.authServerBaseUrl;
2932
+ if (!url.endsWith("/")) url += "/";
2933
+ url += this.deviceAuthorizationUrl;
2934
+ const resp = await super.startDeviceCodeFlow(url, scope);
2935
+ return resp;
2936
+ }
2937
+ /**
2938
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2939
+ * then saves the tokens, as per the requested method
2940
+ * @param scope
2941
+ */
2942
+ async mfaOtpComplete(mfaToken, otp) {
2943
+ const resp = await super.mfaOtpComplete(mfaToken, otp);
2944
+ await this.receiveTokens(resp);
2945
+ return resp;
2946
+ }
2947
+ /**
2948
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2949
+ * then saves the tokens, as per the requested method
2950
+ * @param scope
2951
+ */
2952
+ async mfaOobComplete(mfaToken, oobCode, bindingCode) {
2953
+ const resp = await super.mfaOobComplete(mfaToken, oobCode, bindingCode);
2954
+ await this.receiveTokens(resp);
2955
+ return resp;
2956
+ }
2957
+ /**
2958
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
2959
+ * then saves the tokens, as per the requested method
2960
+ * @param scope
2961
+ */
2962
+ async refreshTokenFlow(refreshToken) {
2963
+ if (!refreshToken) {
2964
+ if (__privateGet(this, _refreshToken)) {
2965
+ refreshToken = __privateGet(this, _refreshToken);
2966
+ } else {
2967
+ throw new g(y.InvalidToken, "Cannot refresh tokens: no refresh token present");
2968
+ }
2969
+ }
2970
+ const resp = await super.refreshTokenFlow(refreshToken);
2971
+ await this.receiveTokens(resp);
2972
+ return resp;
2973
+ }
2974
+ /**
2975
+ * Executes the authorization code flow
2976
+ * @param scope the scope to request
2977
+ * @param pkce whether or not to use PKCE.
2978
+ */
2979
+ async authorizationCodeFlow(scope, pkce = false) {
2980
+ const resp = await super.startAuthorizationCodeFlow(scope, pkce);
2981
+ if (resp.error || !resp.url) {
2982
+ const cerr = g.fromOAuthError(
2983
+ resp.error ?? "Couldn't create URL for authorization code flow",
2984
+ resp.error_description
2985
+ );
2986
+ d.logger.debug(h({ err: cerr }));
2987
+ throw cerr;
2988
+ }
2989
+ location.href = resp.url;
2990
+ }
2991
+ }
2992
+ _accessToken = new WeakMap();
2993
+ _refreshToken = new WeakMap();
2994
+ _idTokenPayload = new WeakMap();
2995
+ _accessTokenPayload = new WeakMap();
2996
+ _refreshTokenPayload = new WeakMap();
2997
+ _client_id = new WeakMap();
2998
+ _client_secret = new WeakMap();
2999
+ export {
3000
+ g as CrossauthError,
3001
+ d as CrossauthLogger,
3002
+ OAuthBffClient,
3003
+ OAuthClient,
3004
+ h as j
3005
+ };