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