@crossauth/frontend 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -3005
- package/dist/index.iife.js +1 -3008
- package/dist/index.js +1145 -1460
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,3005 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
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
|
-
var _accessToken, _refreshToken, _idTokenPayload, _accessTokenPayload, _refreshTokenPayload, _client_id, _client_secret;
|
|
13
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
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;
|
|
1
|
+
"use strict";var Ie=Object.defineProperty;var ce=r=>{throw TypeError(r)};var Oe=(r,e,t)=>e in r?Ie(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var f=(r,e,t)=>Oe(r,typeof e!="symbol"?e+"":e,t),de=(r,e,t)=>e.has(r)||ce("Cannot "+t);var w=(r,e,t)=>(de(r,e,"read from private field"),t?t.call(r):e.get(r)),N=(r,e,t)=>e.has(r)?ce("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),b=(r,e,t,o)=>(de(r,e,"write to private field"),o?o.call(r,t):e.set(r,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var Ue=Object.defineProperty,ge=r=>{throw TypeError(r)},Ne=(r,e,t)=>e in r?Ue(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,l=(r,e,t)=>Ne(r,typeof e!="symbol"?e+"":e,t),pe=(r,e,t)=>e.has(r)||ge("Cannot "+t),p=(r,e,t)=>(pe(r,e,"read from private field"),t?t.call(r):e.get(r)),$=(r,e,t)=>e.has(r)?ge("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),E=(r,e,t,o)=>(pe(r,e,"write to private field"),e.set(r,t),t);class H{}l(H,"active","active"),l(H,"disabled","disabled"),l(H,"awaitingTwoFactorSetup","awaitingtwofactorsetup"),l(H,"awaitingEmailVerification","awaitingemailverification"),l(H,"passwordChangeNeeded","passwordchangeneeded"),l(H,"passwordResetNeeded","passwordresetneeded"),l(H,"factor2ResetNeeded","factor2resetneeded"),l(H,"passwordAndFactor2ResetNeeded","passwordandfactor2resetneeded");class P{}l(P,"session","s:"),l(P,"passwordResetToken","p:"),l(P,"emailVerificationToken","e:"),l(P,"apiKey","api:"),l(P,"authorizationCode","authz:"),l(P,"accessToken","access:"),l(P,"refreshToken","refresh:"),l(P,"mfaToken","omfa:"),l(P,"deviceCode","dc:"),l(P,"userCode","uc:");var m=(r=>(r[r.UserNotExist=0]="UserNotExist",r[r.PasswordInvalid=1]="PasswordInvalid",r[r.EmailNotExist=2]="EmailNotExist",r[r.UsernameOrPasswordInvalid=3]="UsernameOrPasswordInvalid",r[r.InvalidClientId=4]="InvalidClientId",r[r.ClientExists=5]="ClientExists",r[r.InvalidClientSecret=6]="InvalidClientSecret",r[r.InvalidClientIdOrSecret=7]="InvalidClientIdOrSecret",r[r.InvalidRedirectUri=8]="InvalidRedirectUri",r[r.InvalidOAuthFlow=9]="InvalidOAuthFlow",r[r.UserNotActive=10]="UserNotActive",r[r.EmailNotVerified=11]="EmailNotVerified",r[r.TwoFactorIncomplete=12]="TwoFactorIncomplete",r[r.Unauthorized=13]="Unauthorized",r[r.UnauthorizedClient=14]="UnauthorizedClient",r[r.InvalidScope=15]="InvalidScope",r[r.InsufficientScope=16]="InsufficientScope",r[r.InsufficientPriviledges=17]="InsufficientPriviledges",r[r.Forbidden=18]="Forbidden",r[r.InvalidKey=19]="InvalidKey",r[r.InvalidCsrf=20]="InvalidCsrf",r[r.InvalidSession=21]="InvalidSession",r[r.Expired=22]="Expired",r[r.Connection=23]="Connection",r[r.InvalidHash=24]="InvalidHash",r[r.UnsupportedAlgorithm=25]="UnsupportedAlgorithm",r[r.KeyExists=26]="KeyExists",r[r.PasswordChangeNeeded=27]="PasswordChangeNeeded",r[r.PasswordResetNeeded=28]="PasswordResetNeeded",r[r.Factor2ResetNeeded=29]="Factor2ResetNeeded",r[r.Configuration=30]="Configuration",r[r.InvalidEmail=31]="InvalidEmail",r[r.InvalidPhoneNumber=32]="InvalidPhoneNumber",r[r.InvalidUsername=33]="InvalidUsername",r[r.PasswordMatch=34]="PasswordMatch",r[r.InvalidToken=35]="InvalidToken",r[r.MfaRequired=36]="MfaRequired",r[r.PasswordFormat=37]="PasswordFormat",r[r.DataFormat=38]="DataFormat",r[r.FetchError=39]="FetchError",r[r.UserExists=40]="UserExists",r[r.FormEntry=41]="FormEntry",r[r.BadRequest=42]="BadRequest",r[r.AuthorizationPending=43]="AuthorizationPending",r[r.SlowDown=44]="SlowDown",r[r.ExpiredToken=45]="ExpiredToken",r[r.ConstraintViolation=46]="ConstraintViolation",r[r.NotImplemented=47]="NotImplemented",r[r.UnknownError=48]="UnknownError",r))(m||{});class g extends Error{constructor(e,t=void 0){let o,s=500;e==0?(o="User does not exist",s=401):e==1?(o="Password doesn't match",s=401):e==3?(o="Username or password incorrect",s=401):e==4?(o="Client id is invalid",s=401):e==5?(o="Client ID or name already exists",s=500):e==6?(o="Client secret is invalid",s=401):e==7?(o="Client id or secret is invalid",s=401):e==8?(o="Redirect Uri is not registered",s=401):e==9?(o="Invalid OAuth flow type",s=500):e==2?(o="No user exists with that email address",s=401):e==10?(o="Account is not active",s=403):e==33?(o="Username is not in an allowed format",s=400):e==31?(o="Email is not in an allowed format",s=400):e==32?(o="Phone number is not in an allowed format",s=400):e==11?(o="Email address has not been verified",s=403):e==12?(o="Two-factor setup is not complete",s=403):e==13?(o="Not authorized",s=401):e==14?(o="Client not authorized",s=401):e==15?(o="Invalid scope",s=403):e==16?(o="Insufficient scope",s=403):e==23?o="Connection failure":e==22?(o="Token has expired",s=401):e==24?o="Hash is not in a valid format":e==19?(o="Key is invalid",s=401):e==18?(o="You do not have permission to access this resource",s=403):e==17?(o="You do not have the right privileges to access this resource",s=401):e==20?(o="CSRF token is invalid",s=401):e==21?(o="Session cookie is invalid",s=401):e==25?o="Algorithm not supported":e==26?o="Attempt to create a key that already exists":e==27?(o="User must change password",s=403):e==28?(o="User must reset password",s=403):e==29?(o="User must reset 2FA",s=403):e==30?o="There was an error in the configuration":e==34?(o="Passwords do not match",s=401):e==35?(o="Token is not valid",s=401):e==36?(o="MFA is required",s=401):e==37?(o="Password format was incorrect",s=401):e==40?(o="User already exists",s=400):e==42?(o="The request is invalid",s=400):e==38?(o="Session data has unexpected format",s=500):e==39?(o="Couldn't execute a fetch",s=500):e==43?(o="Waiting for authorization",s=200):e==44?(o="Slow polling down by 5 seconds",s=200):e==45?(o="Token has expired",s=401):e==46?(o="Database update/insert caused a constraint violation",s=500):e==47?(o="This method has not been implemented",s=500):(o="Unknown error",s=500),t!=null&&!Array.isArray(t)?o=t:Array.isArray(t)&&(o=t.join(". ")),super(o),l(this,"isCrossauthError",!0),l(this,"httpStatus"),l(this,"code"),l(this,"codeName"),l(this,"messages"),this.code=e,this.codeName=m[e],this.httpStatus=s,this.name="CrossauthError",Array.isArray(t)?this.messages=t:this.messages=[o],Object.setPrototypeOf(this,g.prototype)}static fromOAuthError(e,t){let o;switch(e){case"invalid_request":o=42;break;case"unauthorized_client":o=14;break;case"access_denied":o=13;break;case"unsupported_response_type":o=42;break;case"invalid_scope":o=15;break;case"server_error":o=48;break;case"temporarily_unavailable":o=23;break;case"invalid_token":o=35;break;case"expired_token":o=45;break;case"insufficient_scope":o=35;break;case"mfa_required":o=36;break;case"authorization_pending":o=43;break;case"slow_down":o=44;break;default:o=48}return new g(o,t)}get oauthErrorCode(){switch(this.code){case 42:return"invalid_request";case 14:return"unauthorized_client";case 13:return"access_denied";case 15:return"invalid_scope";case 23:return"temporarily_unavailable";case 35:return"invalid_token";case 36:return"mfa_required";case 43:return"authorization_pending";case 44:return"slow_down";case 45:return"expired_token";case 22:return"expired_token";default:return"server_error"}}static asCrossauthError(e,t){if(e instanceof Error)return"isCrossauthError"in e?e:new g(48,e.message);if("errorCode"in e){let s=48;try{s=Number(e.errorCode)??48}catch{}let n=t??m[s];return"errorMessage"in e?n=e.errorMessage:"message"in e&&(n=e.message),new g(s,n)}let o=t??m[48];return"message"in e&&(o=e.message),new g(48,o)}}const W=class A{constructor(e){if(l(this,"level"),e)this.level=e;else if(typeof process<"u"&&"CROSSAUTH_LOG_LEVEL"in process.env){const t=(process.env.CROSSAUTH_LOG_LEVEL??"ERROR").toUpperCase();A.levelName.includes(t)?this.level=A.levelName.indexOf(t):this.level=A.Error}else this.level=A.Error}static get logger(){return globalThis.crossauthLogger}setLevel(e){this.level=e}log(e,t){e<=this.level&&(typeof t=="string"?console.log("Crossauth "+A.levelName[e]+" "+new Date().toISOString(),t):console.log(JSON.stringify({level:A.levelName[e],time:new Date().toISOString(),...t})))}error(e){this.log(A.Error,e)}warn(e){this.log(A.Warn,e)}info(e){this.log(A.Info,e)}debug(e){this.log(A.Debug,e)}static setLogger(e,t){globalThis.crossauthLogger=e,globalThis.crossauthLoggerAcceptsJson=t}};l(W,"None",0),l(W,"Error",1),l(W,"Warn",2),l(W,"Info",3),l(W,"Debug",4),l(W,"levelName",["NONE","ERROR","WARN","INFO","DEBUG"]);let c=W;function d(r){let e;typeof r=="object"&&"err"in r&&typeof r.err=="object"&&(e=r.err.stack);try{typeof r=="object"&&"err"in r&&typeof r.err=="object"&&r.err&&"message"in r.err&&!("msg"in r)&&(r.msg=r.err.message)}catch{}try{typeof r=="object"&&"err"in r&&typeof r.err=="object"&&(r.err={...r.err,stack:e})}catch{}try{typeof r=="object"&&"err"in r&&!("msg"in r)&&(r.msg=r.msg="An unknown error occurred")}catch{}try{typeof r=="object"&&"cerr"in r&&"isCrossauthError"in r.cerr&&r.cerr&&(r.errorCode=r.cerr.code,r.errorCodeName=r.cerr.codeName,r.httpStatus=r.cerr.httpStatus,"msg"in r||(r.msg=r.cerr.message),delete r.cerr)}catch{}return typeof r=="string"||globalThis.crossauthLoggerAcceptsJson?r:JSON.stringify(r)}globalThis.crossauthLogger=new c(c.None);globalThis.crossauthLoggerAcceptsJson=!0;const ye={issuer:"",authorization_endpoint:"",token_endpoint:"",jwks_uri:"",response_types_supported:[],subject_types_supported:[],response_modes_supported:["query","fragment"],grant_types_supported:["authorization_code","implicit"],id_token_signing_alg_values_supported:[],claim_types_supported:["normal"],claims_parameter_supported:!1,request_parameter_supported:!1,request_uri_parameter_supported:!0,require_request_uri_registration:!1},te=crypto,we=r=>r instanceof CryptoKey,X=new TextEncoder,G=new TextDecoder;function He(...r){const e=r.reduce((s,{length:n})=>s+n,0),t=new Uint8Array(e);let o=0;for(const s of r)t.set(s,o),o+=s.length;return t}const je=r=>{const e=atob(r),t=new Uint8Array(e.length);for(let o=0;o<e.length;o++)t[o]=e.charCodeAt(o);return t},M=r=>{let e=r;e instanceof Uint8Array&&(e=G.decode(e)),e=e.replace(/-/g,"+").replace(/_/g,"/").replace(/\s/g,"");try{return je(e)}catch{throw new TypeError("The input to be decoded is not correctly encoded.")}};class oe extends Error{static get code(){return"ERR_JOSE_GENERIC"}constructor(e){var t;super(e),this.code="ERR_JOSE_GENERIC",this.name=this.constructor.name,(t=Error.captureStackTrace)==null||t.call(Error,this,this.constructor)}}class I extends oe{constructor(){super(...arguments),this.code="ERR_JOSE_NOT_SUPPORTED"}static get code(){return"ERR_JOSE_NOT_SUPPORTED"}}class S extends oe{constructor(){super(...arguments),this.code="ERR_JWS_INVALID"}static get code(){return"ERR_JWS_INVALID"}}class D extends oe{constructor(){super(...arguments),this.code="ERR_JWT_INVALID"}static get code(){return"ERR_JWT_INVALID"}}class xe extends oe{constructor(){super(...arguments),this.code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED",this.message="signature verification failed"}static get code(){return"ERR_JWS_SIGNATURE_VERIFICATION_FAILED"}}function O(r,e="algorithm.name"){return new TypeError(`CryptoKey does not support this operation, its ${e} must be ${r}`)}function Q(r,e){return r.name===e}function se(r){return parseInt(r.name.slice(4),10)}function Ke(r){switch(r){case"ES256":return"P-256";case"ES384":return"P-384";case"ES512":return"P-521";default:throw new Error("unreachable")}}function ze(r,e){if(e.length&&!e.some(t=>r.usages.includes(t))){let t="CryptoKey does not support this operation, its usages must include ";if(e.length>2){const o=e.pop();t+=`one of ${e.join(", ")}, or ${o}.`}else e.length===2?t+=`one of ${e[0]} or ${e[1]}.`:t+=`${e[0]}.`;throw new TypeError(t)}}function De(r,e,...t){switch(e){case"HS256":case"HS384":case"HS512":{if(!Q(r.algorithm,"HMAC"))throw O("HMAC");const o=parseInt(e.slice(2),10);if(se(r.algorithm.hash)!==o)throw O(`SHA-${o}`,"algorithm.hash");break}case"RS256":case"RS384":case"RS512":{if(!Q(r.algorithm,"RSASSA-PKCS1-v1_5"))throw O("RSASSA-PKCS1-v1_5");const o=parseInt(e.slice(2),10);if(se(r.algorithm.hash)!==o)throw O(`SHA-${o}`,"algorithm.hash");break}case"PS256":case"PS384":case"PS512":{if(!Q(r.algorithm,"RSA-PSS"))throw O("RSA-PSS");const o=parseInt(e.slice(2),10);if(se(r.algorithm.hash)!==o)throw O(`SHA-${o}`,"algorithm.hash");break}case"EdDSA":{if(r.algorithm.name!=="Ed25519"&&r.algorithm.name!=="Ed448")throw O("Ed25519 or Ed448");break}case"ES256":case"ES384":case"ES512":{if(!Q(r.algorithm,"ECDSA"))throw O("ECDSA");const o=Ke(e);if(r.algorithm.namedCurve!==o)throw O(o,"algorithm.namedCurve");break}default:throw new TypeError("CryptoKey does not support this operation")}ze(r,t)}function me(r,e,...t){var o;if(t.length>2){const s=t.pop();r+=`one of type ${t.join(", ")}, or ${s}.`}else t.length===2?r+=`one of type ${t[0]} or ${t[1]}.`:r+=`of type ${t[0]}.`;return e==null?r+=` Received ${e}`:typeof e=="function"&&e.name?r+=` Received function ${e.name}`:typeof e=="object"&&e!=null&&(o=e.constructor)!=null&&o.name&&(r+=` Received an instance of ${e.constructor.name}`),r}const he=(r,...e)=>me("Key must be ",r,...e);function ve(r,e,...t){return me(`Key for the ${r} algorithm must be `,e,...t)}const Ce=r=>we(r)?!0:(r==null?void 0:r[Symbol.toStringTag])==="KeyObject",re=["CryptoKey"],We=(...r)=>{const e=r.filter(Boolean);if(e.length===0||e.length===1)return!0;let t;for(const o of e){const s=Object.keys(o);if(!t||t.size===0){t=new Set(s);continue}for(const n of s){if(t.has(n))return!1;t.add(n)}}return!0};function Fe(r){return typeof r=="object"&&r!==null}function V(r){if(!Fe(r)||Object.prototype.toString.call(r)!=="[object Object]")return!1;if(Object.getPrototypeOf(r)===null)return!0;let e=r;for(;Object.getPrototypeOf(e)!==null;)e=Object.getPrototypeOf(e);return Object.getPrototypeOf(r)===e}const Je=(r,e)=>{if(r.startsWith("RS")||r.startsWith("PS")){const{modulusLength:t}=e.algorithm;if(typeof t!="number"||t<2048)throw new TypeError(`${r} requires key modulusLength to be 2048 bits or larger`)}};function Me(r){let e,t;switch(r.kty){case"RSA":{switch(r.alg){case"PS256":case"PS384":case"PS512":e={name:"RSA-PSS",hash:`SHA-${r.alg.slice(-3)}`},t=r.d?["sign"]:["verify"];break;case"RS256":case"RS384":case"RS512":e={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${r.alg.slice(-3)}`},t=r.d?["sign"]:["verify"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":e={name:"RSA-OAEP",hash:`SHA-${parseInt(r.alg.slice(-3),10)||1}`},t=r.d?["decrypt","unwrapKey"]:["encrypt","wrapKey"];break;default:throw new I('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"EC":{switch(r.alg){case"ES256":e={name:"ECDSA",namedCurve:"P-256"},t=r.d?["sign"]:["verify"];break;case"ES384":e={name:"ECDSA",namedCurve:"P-384"},t=r.d?["sign"]:["verify"];break;case"ES512":e={name:"ECDSA",namedCurve:"P-521"},t=r.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":e={name:"ECDH",namedCurve:r.crv},t=r.d?["deriveBits"]:[];break;default:throw new I('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}case"OKP":{switch(r.alg){case"EdDSA":e={name:r.crv},t=r.d?["sign"]:["verify"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":e={name:r.crv},t=r.d?["deriveBits"]:[];break;default:throw new I('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}break}default:throw new I('Invalid or unsupported JWK "kty" (Key Type) Parameter value')}return{algorithm:e,keyUsages:t}}const ke=async r=>{if(!r.alg)throw new TypeError('"alg" argument is required when "jwk.alg" is not present');const{algorithm:e,keyUsages:t}=Me(r),o=[e,r.ext??!1,r.key_ops??t],s={...r};return delete s.alg,delete s.use,te.subtle.importKey("jwk",s,...o)},Se=r=>M(r);let ie,ne;const _e=r=>(r==null?void 0:r[Symbol.toStringTag])==="KeyObject",Te=async(r,e,t,o)=>{let s=r.get(e);if(s!=null&&s[o])return s[o];const n=await ke({...t,alg:o});return s?s[o]=n:r.set(e,{[o]:n}),n},Be=(r,e)=>{if(_e(r)){let t=r.export({format:"jwk"});return delete t.d,delete t.dp,delete t.dq,delete t.p,delete t.q,delete t.qi,t.k?Se(t.k):(ne||(ne=new WeakMap),Te(ne,r,t,e))}return r},Le=(r,e)=>{if(_e(r)){let t=r.export({format:"jwk"});return t.k?Se(t.k):(ie||(ie=new WeakMap),Te(ie,r,t,e))}return r},$e={normalizePublicKey:Be,normalizePrivateKey:Le},j=(r,e,t=0)=>{t===0&&(e.unshift(e.length),e.unshift(6));const o=r.indexOf(e[0],t);if(o===-1)return!1;const s=r.subarray(o,o+e.length);return s.length!==e.length?!1:s.every((n,i)=>n===e[i])||j(r,e,o+1)},le=r=>{switch(!0){case j(r,[42,134,72,206,61,3,1,7]):return"P-256";case j(r,[43,129,4,0,34]):return"P-384";case j(r,[43,129,4,0,35]):return"P-521";case j(r,[43,101,110]):return"X25519";case j(r,[43,101,111]):return"X448";case j(r,[43,101,112]):return"Ed25519";case j(r,[43,101,113]):return"Ed448";default:throw new I("Invalid or unsupported EC Key Curve or OKP Key Sub Type")}},be=async(r,e,t,o,s)=>{let n,i;const a=new Uint8Array(atob(t.replace(r,"")).split("").map(u=>u.charCodeAt(0))),h=e==="spki";switch(o){case"PS256":case"PS384":case"PS512":n={name:"RSA-PSS",hash:`SHA-${o.slice(-3)}`},i=h?["verify"]:["sign"];break;case"RS256":case"RS384":case"RS512":n={name:"RSASSA-PKCS1-v1_5",hash:`SHA-${o.slice(-3)}`},i=h?["verify"]:["sign"];break;case"RSA-OAEP":case"RSA-OAEP-256":case"RSA-OAEP-384":case"RSA-OAEP-512":n={name:"RSA-OAEP",hash:`SHA-${parseInt(o.slice(-3),10)||1}`},i=h?["encrypt","wrapKey"]:["decrypt","unwrapKey"];break;case"ES256":n={name:"ECDSA",namedCurve:"P-256"},i=h?["verify"]:["sign"];break;case"ES384":n={name:"ECDSA",namedCurve:"P-384"},i=h?["verify"]:["sign"];break;case"ES512":n={name:"ECDSA",namedCurve:"P-521"},i=h?["verify"]:["sign"];break;case"ECDH-ES":case"ECDH-ES+A128KW":case"ECDH-ES+A192KW":case"ECDH-ES+A256KW":{const u=le(a);n=u.startsWith("P-")?{name:"ECDH",namedCurve:u}:{name:u},i=h?[]:["deriveBits"];break}case"EdDSA":n={name:le(a)},i=h?["verify"]:["sign"];break;default:throw new I('Invalid or unsupported "alg" (Algorithm) value')}return te.subtle.importKey(e,a,n,!1,i)},qe=(r,e,t)=>be(/(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g,"pkcs8",r,e),Ve=(r,e,t)=>be(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g,"spki",r,e);async function Ge(r,e,t){if(typeof r!="string"||r.indexOf("-----BEGIN PUBLIC KEY-----")!==0)throw new TypeError('"spki" must be SPKI formatted string');return Ve(r,e)}async function Ye(r,e,t){if(typeof r!="string"||r.indexOf("-----BEGIN PRIVATE KEY-----")!==0)throw new TypeError('"pkcs8" must be PKCS#8 formatted string');return qe(r,e)}async function ue(r,e){if(!V(r))throw new TypeError("JWK must be an object");switch(e||(e=r.alg),r.kty){case"oct":if(typeof r.k!="string"||!r.k)throw new TypeError('missing "k" (Key Value) Parameter value');return M(r.k);case"RSA":if(r.oth!==void 0)throw new I('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');case"EC":case"OKP":return ke({...r,alg:e});default:throw new I('Unsupported "kty" (Key Type) Parameter value')}}const ee=r=>r==null?void 0:r[Symbol.toStringTag],Xe=(r,e)=>{if(!(e instanceof Uint8Array)){if(!Ce(e))throw new TypeError(ve(r,e,...re,"Uint8Array"));if(e.type!=="secret")throw new TypeError(`${ee(e)} instances for symmetric algorithms must be of type "secret"`)}},Qe=(r,e,t)=>{if(!Ce(e))throw new TypeError(ve(r,e,...re));if(e.type==="secret")throw new TypeError(`${ee(e)} instances for asymmetric algorithms must not be of type "secret"`);if(e.algorithm&&t==="verify"&&e.type==="private")throw new TypeError(`${ee(e)} instances for asymmetric algorithm verifying must be of type "public"`);if(e.algorithm&&t==="encrypt"&&e.type==="private")throw new TypeError(`${ee(e)} instances for asymmetric algorithm encryption must be of type "public"`)},Ze=(r,e,t)=>{r.startsWith("HS")||r==="dir"||r.startsWith("PBES2")||/^A\d{3}(?:GCM)?KW$/.test(r)?Xe(r,e):Qe(r,e,t)};function er(r,e,t,o,s){if(s.crit!==void 0&&(o==null?void 0:o.crit)===void 0)throw new r('"crit" (Critical) Header Parameter MUST be integrity protected');if(!o||o.crit===void 0)return new Set;if(!Array.isArray(o.crit)||o.crit.length===0||o.crit.some(i=>typeof i!="string"||i.length===0))throw new r('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');let n;n=e;for(const i of o.crit){if(!n.has(i))throw new I(`Extension Header Parameter "${i}" is not recognized`);if(s[i]===void 0)throw new r(`Extension Header Parameter "${i}" is missing`);if(n.get(i)&&o[i]===void 0)throw new r(`Extension Header Parameter "${i}" MUST be integrity protected`)}return new Set(o.crit)}function rr(r,e){const t=`SHA-${r.slice(-3)}`;switch(r){case"HS256":case"HS384":case"HS512":return{hash:t,name:"HMAC"};case"PS256":case"PS384":case"PS512":return{hash:t,name:"RSA-PSS",saltLength:r.slice(-3)>>3};case"RS256":case"RS384":case"RS512":return{hash:t,name:"RSASSA-PKCS1-v1_5"};case"ES256":case"ES384":case"ES512":return{hash:t,name:"ECDSA",namedCurve:e.namedCurve};case"EdDSA":return{name:e.name};default:throw new I(`alg ${r} is not supported either by JOSE or your javascript runtime`)}}async function tr(r,e,t){if(e=await $e.normalizePublicKey(e,r),we(e))return De(e,r,t),e;if(e instanceof Uint8Array){if(!r.startsWith("HS"))throw new TypeError(he(e,...re));return te.subtle.importKey("raw",e,{hash:`SHA-${r.slice(-3)}`,name:"HMAC"},!1,[t])}throw new TypeError(he(e,...re,"Uint8Array"))}const or=async(r,e,t,o)=>{const s=await tr(r,e,"verify");Je(r,s);const n=rr(r,s.algorithm);try{return await te.subtle.verify(n,s,t,o)}catch{return!1}};async function sr(r,e,t){if(!V(r))throw new S("Flattened JWS must be an object");if(r.protected===void 0&&r.header===void 0)throw new S('Flattened JWS must have either of the "protected" or "header" members');if(r.protected!==void 0&&typeof r.protected!="string")throw new S("JWS Protected Header incorrect type");if(r.payload===void 0)throw new S("JWS Payload missing");if(typeof r.signature!="string")throw new S("JWS Signature missing or incorrect type");if(r.header!==void 0&&!V(r.header))throw new S("JWS Unprotected Header incorrect type");let o={};if(r.protected)try{const Re=M(r.protected);o=JSON.parse(G.decode(Re))}catch{throw new S("JWS Protected Header is invalid")}if(!We(o,r.header))throw new S("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");const s={...o,...r.header},n=er(S,new Map([["b64",!0]]),void 0,o,s);let i=!0;if(n.has("b64")&&(i=o.b64,typeof i!="boolean"))throw new S('The "b64" (base64url-encode payload) Header Parameter must be a boolean');const{alg:a}=s;if(typeof a!="string"||!a)throw new S('JWS "alg" (Algorithm) Header Parameter missing or invalid');if(i){if(typeof r.payload!="string")throw new S("JWS Payload must be a string")}else if(typeof r.payload!="string"&&!(r.payload instanceof Uint8Array))throw new S("JWS Payload must be a string or an Uint8Array instance");let h=!1;typeof e=="function"&&(e=await e(o,r),h=!0),Ze(a,e,"verify");const u=He(X.encode(r.protected??""),X.encode("."),typeof r.payload=="string"?X.encode(r.payload):r.payload);let y;try{y=M(r.signature)}catch{throw new S("Failed to base64url decode the signature")}if(!await or(a,e,y,u))throw new xe;let _;if(i)try{_=M(r.payload)}catch{throw new S("Failed to base64url decode the payload")}else typeof r.payload=="string"?_=X.encode(r.payload):_=r.payload;const Y={payload:_};return r.protected!==void 0&&(Y.protectedHeader=o),r.header!==void 0&&(Y.unprotectedHeader=r.header),h?{...Y,key:e}:Y}async function ir(r,e,t){if(r instanceof Uint8Array&&(r=G.decode(r)),typeof r!="string")throw new S("Compact JWS must be a string or Uint8Array");const{0:o,1:s,2:n,length:i}=r.split(".");if(i!==3)throw new S("Invalid Compact JWS");const a=await sr({payload:s,protected:o,signature:n},e),h={payload:a.payload,protectedHeader:a.protectedHeader};return typeof e=="function"?{...h,key:a.key}:h}const Ae=M;function nr(r){let e;if(typeof r=="string"){const t=r.split(".");(t.length===3||t.length===5)&&([e]=t)}else if(typeof r=="object"&&r)if("protected"in r)e=r.protected;else throw new TypeError("Token does not contain a Protected Header");try{if(typeof e!="string"||!e)throw new Error;const t=JSON.parse(G.decode(Ae(e)));if(!V(t))throw new Error;return t}catch{throw new TypeError("Invalid Token or Protected Header formatting")}}function ar(r){if(typeof r!="string")throw new D("JWTs must use Compact JWS serialization, JWT must be a string");const{1:e,length:t}=r.split(".");if(t===5)throw new D("Only JWTs using Compact JWS serialization can be decoded");if(t!==3)throw new D("Invalid JWT");if(!e)throw new D("JWTs must contain a payload");let o;try{o=Ae(e)}catch{throw new D("Failed to base64url decode the payload")}let s;try{s=JSON.parse(G.decode(o))}catch{throw new D("Failed to parse the decoded payload as JSON")}if(!V(s))throw new D("Invalid JWT Claims Set");return s}const C=class v{static flowNames(e){let t={};return e.forEach(o=>{o in v.flowName&&(t[o]=v.flowName[o])}),t}static isValidFlow(e){return v.allFlows().includes(e)}static areAllValidFlows(e){let t=!0;return e.forEach(o=>{v.isValidFlow(o)||(t=!1)}),t}static allFlows(){return[v.AuthorizationCode,v.AuthorizationCodeWithPKCE,v.ClientCredentials,v.RefreshToken,v.DeviceCode,v.Password,v.PasswordMfa,v.OidcAuthorizationCode]}static grantType(e){switch(e){case v.AuthorizationCode:case v.AuthorizationCodeWithPKCE:case v.OidcAuthorizationCode:return["authorization_code"];case v.ClientCredentials:return["client_credentials"];case v.RefreshToken:return["refresh_token"];case v.Password:return["password"];case v.PasswordMfa:return["http://auth0.com/oauth/grant-type/mfa-otp","http://auth0.com/oauth/grant-type/mfa-oob"];case v.DeviceCode:return["urn:ietf:params:oauth:grant-type:device_code"]}}};l(C,"All","all"),l(C,"AuthorizationCode","authorizationCode"),l(C,"AuthorizationCodeWithPKCE","authorizationCodeWithPKCE"),l(C,"ClientCredentials","clientCredentials"),l(C,"RefreshToken","refreshToken"),l(C,"DeviceCode","deviceCode"),l(C,"Password","password"),l(C,"PasswordMfa","passwordMfa"),l(C,"OidcAuthorizationCode","oidcAuthorizationCode"),l(C,"flowName",{[C.AuthorizationCode]:"Authorization Code",[C.AuthorizationCodeWithPKCE]:"Authorization Code with PKCE",[C.ClientCredentials]:"Client Credentials",[C.RefreshToken]:"Refresh Token",[C.DeviceCode]:"Device Code",[C.Password]:"Password",[C.PasswordMfa]:"Password MFA",[C.OidcAuthorizationCode]:"OIDC Authorization Code"});var k,T,q,F,J;class cr{constructor({authServerBaseUrl:e,client_id:t,client_secret:o,redirect_uri:s,codeChallengeMethod:n,stateLength:i,verifierLength:a,tokenConsumer:h,authServerCredentials:u,authServerMode:y,authServerHeaders:_}){l(this,"authServerBaseUrl",""),$(this,k),$(this,T),$(this,q),l(this,"codeChallengeMethod","S256"),$(this,F),l(this,"verifierLength",32),l(this,"redirect_uri"),$(this,J,""),l(this,"stateLength",32),l(this,"authzCode",""),l(this,"oidcConfig"),l(this,"tokenConsumer"),l(this,"authServerHeaders",{}),l(this,"authServerMode"),l(this,"authServerCredentials"),this.tokenConsumer=h,this.authServerBaseUrl=e,a&&(this.verifierLength=a),i&&(this.stateLength=i),t&&E(this,k,t),o&&E(this,T,o),s&&(this.redirect_uri=s),n&&(this.codeChallengeMethod=n),this.authServerBaseUrl=e,u&&(this.authServerCredentials=u),y&&(this.authServerMode=y),_&&(this.authServerHeaders=_)}set client_id(e){E(this,k,e)}set client_secret(e){E(this,T,e)}set codeVerifier(e){E(this,F,e)}set codeChallenge(e){E(this,q,e)}set state(e){E(this,J,e)}async loadConfig(e){if(e){c.logger.debug(d({msg:"Reading OIDC config locally"})),this.oidcConfig=e;return}let t;try{const o=new URL(this.authServerBaseUrl+"/.well-known/openid-configuration");c.logger.debug(d({msg:`Fetching OIDC config from ${o}`}));let s={headers:this.authServerHeaders};this.authServerMode&&(s.mode=this.authServerMode),this.authServerCredentials&&(s.credentials=this.authServerCredentials),t=await fetch(o,s)}catch(o){c.logger.error(d({err:o}))}if(!t||!t.ok)throw new g(m.Connection,"Couldn't get OIDC configuration from URL"+this.authServerBaseUrl+"/.well-known/openid-configuration");this.oidcConfig={...ye};try{const o=await t.json();for(const[s,n]of Object.entries(o))this.oidcConfig[s]=n}catch{throw new g(m.Connection,"Unrecognized response from OIDC configuration endpoint")}}getOidcConfig(){return this.oidcConfig}async startAuthorizationCodeFlow(e,t=!1){var o,s,n;if(c.logger.debug(d({msg:"Starting authorization code flow"})),this.oidcConfig||await this.loadConfig(),!((o=this.oidcConfig)!=null&&o.response_types_supported.includes("code"))||!((s=this.oidcConfig)!=null&&s.response_modes_supported.includes("query")))return{error:"invalid_request",error_description:"Server does not support authorization code flow"};if(!((n=this.oidcConfig)!=null&&n.authorization_endpoint))return{error:"server_error",error_description:"Cannot get authorize endpoint"};if(E(this,J,this.randomValue(this.stateLength)),!p(this,k))return{error:"invalid_request",error_description:"Cannot make authorization code flow without client id"};if(!this.redirect_uri)return{error:"invalid_request",error_description:"Cannot make authorization code flow without Redirect Uri"};let i=this.oidcConfig.authorization_endpoint+"?response_type=code&client_id="+encodeURIComponent(p(this,k))+"&state="+encodeURIComponent(p(this,J))+"&redirect_uri="+encodeURIComponent(this.redirect_uri);return e&&(i+="&scope="+encodeURIComponent(e)),t&&(E(this,F,this.randomValue(this.verifierLength)),E(this,q,this.codeChallengeMethod=="plain"?p(this,F):await this.sha256(p(this,F))),i+="&code_challenge="+p(this,q)),{url:i}}async redirectEndpoint(e,t,o,s){var n,i;if(this.oidcConfig||await this.loadConfig(),o||!e)return o||(o="server_error"),s||(s="Unknown error"),{error:o,error_description:s};if(p(this,J)&&t!=p(this,J))return{error:"access_denied",error_description:"State is not valid"};if(this.authzCode=e,!((n=this.oidcConfig)!=null&&n.grant_types_supported.includes("authorization_code")))return{error:"invalid_request",error_description:"Server does not support authorization code grant"};if(!((i=this.oidcConfig)!=null&&i.token_endpoint))return{error:"server_error",error_description:"Cannot get token endpoint"};const a=this.oidcConfig.token_endpoint;let h,u;h="authorization_code",u=p(this,T);let y={grant_type:h,client_id:p(this,k),code:this.authzCode};u&&(y.client_secret=u),y.code_verifier=p(this,F);try{return this.post(a,y,this.authServerHeaders)}catch(_){return c.logger.error(d({err:_})),{error:"server_error",error_description:"Unable to get access token from server"}}}async clientCredentialsFlow(e){var t,o;if(c.logger.debug(d({msg:"Starting client credentials flow"})),this.oidcConfig||await this.loadConfig(),!((t=this.oidcConfig)!=null&&t.grant_types_supported.includes("client_credentials")))return{error:"invalid_request",error_description:"Server does not support client credentials grant"};if(!((o=this.oidcConfig)!=null&&o.token_endpoint))return{error:"server_error",error_description:"Cannot get token endpoint"};if(!p(this,k))return{error:"invalid_request",error_description:"Cannot make client credentials flow without client id"};const s=this.oidcConfig.token_endpoint;let n={grant_type:"client_credentials",client_id:p(this,k),client_secret:p(this,T)};e&&(n.scope=e);try{return await this.post(s,n,this.authServerHeaders)}catch(i){return c.logger.error(d({err:i})),{error:"server_error",error_description:"Error connecting to authorization server"}}}async passwordFlow(e,t,o){var s,n;if(c.logger.debug(d({msg:"Starting password flow"})),this.oidcConfig||await this.loadConfig(),!((s=this.oidcConfig)!=null&&s.grant_types_supported.includes("password")))return{error:"invalid_request",error_description:"Server does not support password grant"};if(!((n=this.oidcConfig)!=null&&n.token_endpoint))return{error:"server_error",error_description:"Cannot get token endpoint"};const i=this.oidcConfig.token_endpoint;let a={grant_type:"password",client_id:p(this,k),client_secret:p(this,T),username:e,password:t};o&&(a.scope=o);try{return await this.post(i,a,this.authServerHeaders)}catch(h){return c.logger.error(d({err:h})),{error:"server_error",error_description:"Error connecting to authorization server"}}}async mfaAuthenticators(e){var t,o,s;if(c.logger.debug(d({msg:"Getting valid MFA authenticators"})),this.oidcConfig||await this.loadConfig(),!((t=this.oidcConfig)!=null&&t.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"))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};if(!((s=this.oidcConfig)!=null&&s.issuer))return{error:"server_error",error_description:"Cannot get issuer"};const n=this.oidcConfig.issuer+(this.oidcConfig.issuer.endsWith("/")?"":"/")+"mfa/authenticators",i=await this.get(n,{authorization:"Bearer "+e,...this.authServerHeaders});if(!Array.isArray(i))return{error:"server_error",error_description:"Expected array of authenticators in mfa/authenticators response"};let a=[];for(let h=0;h<i.length;++h){const u=i[h];if(!u.id||!u.authenticator_type||!u.active)return{error:"server_error",error_description:"Invalid mfa/authenticators response"};a.push({id:u.id,authenticator_type:u.authenticator_type,active:u.active,name:u.name,oob_channel:u.oob_channel})}return{authenticators:a}}async mfaOtpRequest(e,t){var o,s;if(c.logger.debug(d({msg:"Making MFA OTB request"})),this.oidcConfig||await this.loadConfig(),!((o=this.oidcConfig)!=null&&o.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};if(!((s=this.oidcConfig)!=null&&s.issuer))return{error:"server_error",error_description:"Cannot get issuer"};const n=this.oidcConfig.issuer+(this.oidcConfig.issuer.endsWith("/")?"":"/")+"mfa/challenge",i=await this.post(n,{client_id:p(this,k),client_secret:p(this,T),challenge_type:"otp",mfa_token:e,authenticator_id:t},this.authServerHeaders);return i.challenge_type!="otp"?{error:i.error??"server_error",error_description:i.error_description??"Invalid OTP challenge response"}:i}async mfaOtpComplete(e,t,o){var s,n;if(c.logger.debug(d({msg:"Completing MFA OTP request"})),this.oidcConfig||await this.loadConfig(),!((s=this.oidcConfig)!=null&&s.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};if(!((n=this.oidcConfig)!=null&&n.issuer))return{error:"server_error",error_description:"Cannot get issuer"};const i=this.oidcConfig.token_endpoint,a=await this.post(i,{grant_type:"http://auth0.com/oauth/grant-type/mfa-otp",client_id:p(this,k),client_secret:p(this,T),challenge_type:"otp",mfa_token:e,otp:t,scope:o},this.authServerHeaders);return{id_token:a.id_token,access_token:a.access_token,refresh_token:a.refresh_token,expires_in:Number(a.expires_in),scope:a.scope,token_type:a.token_type,error:a.error,error_description:a.error_description}}async mfaOobRequest(e,t){var o,s;if(c.logger.debug(d({msg:"Making MFA OOB request"})),this.oidcConfig||await this.loadConfig(),!((o=this.oidcConfig)!=null&&o.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-otp")))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};if(!((s=this.oidcConfig)!=null&&s.issuer))return{error:"server_error",error_description:"Cannot get issuer"};const n=this.oidcConfig.issuer+(this.oidcConfig.issuer.endsWith("/")?"":"/")+"mfa/challenge",i=await this.post(n,{client_id:p(this,k),client_secret:p(this,T),challenge_type:"oob",mfa_token:e,authenticator_id:t},this.authServerHeaders);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"}:{challenge_type:i.challenge_type,oob_code:i.oob_code,binding_method:i.binding_method,error:i.error,error_description:i.error_description}}async mfaOobComplete(e,t,o,s){var n,i;if(c.logger.debug(d({msg:"Completing MFA OOB request"})),this.oidcConfig||await this.loadConfig(),!((n=this.oidcConfig)!=null&&n.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-oob")))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};if(!((i=this.oidcConfig)!=null&&i.issuer))return{error:"server_error",error_description:"Cannot get issuer"};const a=this.oidcConfig.token_endpoint,h=await this.post(a,{grant_type:"http://auth0.com/oauth/grant-type/mfa-oob",client_id:p(this,k),client_secret:p(this,T),challenge_type:"otp",mfa_token:e,oob_code:t,binding_code:o,scope:s},this.authServerHeaders);return h.error?{error:h.error,error_description:h.error_description}:{id_token:h.id_token,access_token:h.access_token,refresh_token:h.refresh_token,expires_in:"expires_in"in h?Number(h.expires_in):void 0,scope:h.scope,token_type:h.token_type}}async refreshTokenFlow(e){var t,o;if(c.logger.debug(d({msg:"Starting refresh token flow"})),this.oidcConfig||await this.loadConfig(),!((t=this.oidcConfig)!=null&&t.grant_types_supported.includes("refresh_token")))return{error:"invalid_request",error_description:"Server does not support refresh_token grant"};if(!((o=this.oidcConfig)!=null&&o.token_endpoint))return{error:"server_error",error_description:"Cannot get token endpoint"};const s=this.oidcConfig.token_endpoint;let n;n=p(this,T);let i={grant_type:"refresh_token",refresh_token:e,client_id:p(this,k)};n&&(i.client_secret=n);try{return await this.post(s,i,this.authServerHeaders)}catch(a){return c.logger.error(d({err:a})),{error:"server_error",error_description:"Error connecting to authorization server"}}}async startDeviceCodeFlow(e,t){var o;if(c.logger.debug(d({msg:"Starting device code flow"})),this.oidcConfig||await this.loadConfig(),!((o=this.oidcConfig)!=null&&o.grant_types_supported.includes("urn:ietf:params:oauth:grant-type:device_code")))return{error:"invalid_request",error_description:"Server does not support device code grant"};let s={grant_type:"urn:ietf:params:oauth:grant-type:device_code",client_id:p(this,k),client_secret:p(this,T)};t&&(s.scope=t);try{return await this.post(e,s,this.authServerHeaders)}catch(n){return c.logger.error(d({err:n})),{error:"server_error",error_description:"Error connecting to authorization server"}}}async pollDeviceCodeFlow(e){var t,o,s;if(c.logger.debug(d({msg:"Starting device code flow"})),this.oidcConfig||await this.loadConfig(),!((t=this.oidcConfig)!=null&&t.grant_types_supported.includes("urn:ietf:params:oauth:grant-type:device_code")))return{error:"invalid_request",error_description:"Server does not support device code grant"};if(!((o=this.oidcConfig)!=null&&o.token_endpoint))return{error:"server_error",error_description:"Cannot get token endpoint"};let n={grant_type:"urn:ietf:params:oauth:grant-type:device_code",client_id:p(this,k),client_secret:p(this,T),device_code:e};try{const i=await this.post((s=this.oidcConfig)==null?void 0:s.token_endpoint,n,this.authServerHeaders);return i.error,i}catch(i){return c.logger.error(d({err:i})),{error:"server_error",error_description:"Error connecting to authorization server"}}}async post(e,t,o={}){c.logger.debug(d({msg:"Fetch POST",url:e,params:Object.keys(t)}));let s={};return this.authServerCredentials&&(s.credentials=this.authServerCredentials),this.authServerMode&&(s.mode=this.authServerMode),await(await fetch(e,{method:"POST",...s,headers:{Accept:"application/json","Content-Type":"application/json",...o},body:JSON.stringify(t)})).json()}async get(e,t={}){c.logger.debug(d({msg:"Fetch GET",url:e}));let o={};return this.authServerCredentials&&(o.credentials=this.authServerCredentials),this.authServerMode&&(o.mode=this.authServerMode),await(await fetch(e,{method:"GET",...o,headers:{Accept:"application/json","Content-Type":"application/json",...t}})).json()}async validateIdToken(e){try{return await this.tokenConsumer.tokenAuthorized(e,"id")}catch{return}}async idTokenAuthorized(e){try{return await this.tokenConsumer.tokenAuthorized(e,"id")}catch(t){c.logger.warn(d({err:t}));return}}getTokenPayload(e){return ar(e)}}k=new WeakMap,T=new WeakMap,q=new WeakMap,F=new WeakMap,J=new WeakMap;class dr{constructor(e,t={}){if(l(this,"audience"),l(this,"jwtKeyType"),l(this,"jwtSecretKey"),l(this,"jwtPublicKey"),l(this,"clockTolerance",10),l(this,"authServerBaseUrl",""),l(this,"oidcConfig"),l(this,"keys",{}),this.audience=e,t.authServerBaseUrl&&(this.authServerBaseUrl=t.authServerBaseUrl),t.jwtKeyType&&(this.jwtKeyType=t.jwtKeyType),t.jwtSecretKey&&(this.jwtSecretKey=t.jwtSecretKey),t.jwtPublicKey&&(this.jwtPublicKey=t.jwtPublicKey),t.clockTolerance&&(this.clockTolerance=t.clockTolerance),t.oidcConfig&&(this.oidcConfig=t.oidcConfig),this.jwtPublicKey&&!this.jwtKeyType)throw new g(m.Configuration,"If specifying jwtPublic key, must also specify jwtKeyType")}async loadKeys(){try{if(this.jwtSecretKey){if(!this.jwtKeyType)throw new g(m.Configuration,"Must specify jwtKeyType if setting jwtSecretKey");this.keys._default=await Ye(this.jwtSecretKey,this.jwtKeyType)}else if(this.jwtPublicKey){if(!this.jwtKeyType)throw new g(m.Configuration,"Must specify jwtKeyType if setting jwtPublicKey");const e=await Ge(this.jwtPublicKey,this.jwtKeyType);this.keys._default=e}else{if(this.oidcConfig||await this.loadConfig(),!this.oidcConfig)throw new g(m.Connection,"Load OIDC config before Jwks");await this.loadJwks()}}catch(e){throw c.logger.debug(d({err:e})),new g(m.Connection,"Couldn't load keys")}}async loadConfig(e){if(e){this.oidcConfig=e;return}if(!this.authServerBaseUrl)throw new g(m.Connection,"Couldn't get OIDC configuration. Either set authServerBaseUrl or set config manually");let t;try{t=await fetch(new URL("/.well-known/openid-configuration",this.authServerBaseUrl))}catch(o){c.logger.error(d({err:o}))}if(!t||!t.ok)throw new g(m.Connection,"Couldn't get OIDC configuration");this.oidcConfig={...ye};try{const o=await t.json();for(const[s,n]of Object.entries(o))this.oidcConfig[s]=n}catch{throw new g(m.Connection,"Unrecognized response from OIDC configuration endpoint")}}async loadJwks(e){if(e){this.keys={};for(let t=0;t<e.keys.length;++t){const o=e.keys[t];this.keys[o.kid??"_default"]=await ue(e.keys[t])}}else{if(!this.oidcConfig)throw new g(m.Connection,"Load OIDC config before Jwks");let t;try{t=await fetch(new URL(this.oidcConfig.jwks_uri))}catch(o){c.logger.error(d({err:o}))}if(!t||!t.ok)throw new g(m.Connection,"Couldn't get OIDC configuration");this.keys={};try{const o=await t.json();if(!("keys"in o)||!Array.isArray(o.keys))throw new g(m.Connection,"Couldn't fetch keys");for(let s=0;s<o.keys.length;++s)try{let n="_default";"kid"in o.keys[s]&&typeof o.keys[s]=="string"&&(n=String(o.keys[s]));const i=await ue(o.keys[s]);this.keys[n]=i}catch(n){throw c.logger.error(d({err:n})),new g(m.Connection,"Couldn't load keys")}}catch(o){throw c.logger.error(d({err:o})),new g(m.Connection,"Unrecognized response from OIDC jwks endpoint")}}}async tokenAuthorized(e,t){(!this.keys||Object.keys(this.keys).length==0)&&await this.loadKeys();const o=await this.validateToken(e);if(o){if(o.type!=t&&c.logger.error(d({msg:t+" expected but got "+o.type})),o.iss!=this.authServerBaseUrl){c.logger.error(d({msg:`Invalid issuer ${o.iss} in access token`,hashedAccessToken:await this.hash(o.jti)}));return}if(o.aud&&(Array.isArray(o.aud)&&!o.aud.includes(this.audience)||!Array.isArray(o.aud)&&o.aud!=this.audience)){c.logger.error(d({msg:`Invalid audience ${o.aud} in access token`,hashedAccessToken:await this.hash(o.jti)}));return}return o}}async validateToken(e){(!this.keys||Object.keys(this.keys).length==0)&&c.logger.warn("No keys loaded so cannot validate tokens");let t;try{t=nr(e).kid}catch{c.logger.warn(d({msg:"Invalid access token format"}));return}let o;"_default"in this.keys&&(o=this.keys._default);for(let s in this.keys)if(t==s){o=this.keys[s];break}if(!o){c.logger.warn(d({msg:"No matching keys found for access token"}));return}try{const{payload:s}=await ir(e,o),n=JSON.parse(new TextDecoder().decode(s));if(n.exp*1e3<Date.now()+this.clockTolerance){c.logger.warn(d({msg:"Access token has expired"}));return}return n}catch{c.logger.warn(d({msg:"Access token did not validate"}));return}}}const fe=30,Z=2,ae=30;class Ee{constructor(e){f(this,"autoRefreshUrl","/autorefresh");f(this,"csrfHeader","X-CROSSAUTH-CSRF");f(this,"headers",{});f(this,"autoRefreshActive",!1);f(this,"mode","cors");f(this,"credentials","same-origin");f(this,"tokenProvider");this.tokenProvider=e.tokenProvider,this.autoRefreshUrl=e.autoRefreshUrl,e.csrfHeader&&(this.csrfHeader=e.csrfHeader),e.headers&&(this.headers=e.headers),e.mode&&(this.mode=e.mode),e.credentials&&(this.credentials=e.credentials)}async startAutoRefresh(e=["access","id"],t){this.autoRefreshActive||(this.autoRefreshActive=!0,c.logger.debug(d({msg:"Starting auto refresh"})),await this.scheduleAutoRefresh(e,t))}stopAutoRefresh(){this.autoRefreshActive=!1,c.logger.debug(d({msg:"Stopping auto refresh"}))}async scheduleAutoRefresh(e,t){const o=this.tokenProvider.getCsrfToken(),s=o?await o:void 0,n=await this.tokenProvider.getTokenExpiries([...e,"refresh"],s);if(n.refresh==null){c.logger.debug(d({msg:"No refresh token found"}));return}const i=Date.now();let a=n.id;if((!a||n.access&&n.access<a)&&(a=n.access),!a){c.logger.debug(d({msg:"No tokens expire"}));return}const h=a*1e3-i-fe;if(h<0){c.logger.debug(d({msg:"Expiry time has passed"}));return}if(n.refresh&&n.refresh-fe<h){c.logger.debug(d({msg:"Refresh token has expired"}));return}let u=y=>new Promise(_=>setTimeout(_,y));c.logger.debug(d({msg:`Waiting ${h} before refreshing tokens`})),await u(h),await this.autoRefresh(e,s,t)}async autoRefresh(e,t,o){if(this.autoRefreshActive){let s,n=!1,i=0;for(;!n&&i<=Z;)try{let a={...this.headers};t&&(a[this.csrfHeader]=t),c.logger.debug(d({msg:"Initiating auto refresh"}));const h=await this.tokenProvider.jsonFetchWithToken(this.autoRefreshUrl,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",...a},mode:this.mode,credentials:this.credentials,body:{csrfToken:t}},"refresh");if(h.ok||c.logger.error(d({msg:"Failed auto refreshing tokens",status:h.status})),s=await h.json(),s!=null&&s.ok){await this.scheduleAutoRefresh(e,o),n=!0;try{await this.tokenProvider.receiveTokens(s)}catch(u){const y=g.asCrossauthError(u);o?o("Couldn't receive tokens",y):(c.logger.debug(d({err:u})),c.logger.error(d({msg:"Error receiving tokens",cerr:y})))}}else i<Z?(c.logger.error(d({msg:`Failed auto refreshing tokens. Retrying in ${ae} seconds`})),await(y=>new Promise(_=>setTimeout(_,y)))(ae*1e3)):(c.logger.error(d({msg:"Failed auto refreshing tokens. Number of retries exceeded"})),o&&o("Failed auto refreshing tokens")),i++}catch(a){const h=g.asCrossauthError(a);c.logger.debug(d({err:h})),i<Z?(c.logger.error(d({msg:`Failed auto refreshing tokens. Retrying in ${Z} seconds`})),await(y=>new Promise(_=>setTimeout(_,y)))(ae)):(c.logger.error(d({msg:"Failed auto refreshing tokens. Number of retries exceeded"})),o&&o(h.message,h)),i++}}}}class Pe{constructor(e){f(this,"deviceCodePollUrl","/devicecodepoll");f(this,"headers",{});f(this,"pollingActive",!1);f(this,"mode","cors");f(this,"credentials","same-origin");f(this,"respectRedirect",!0);f(this,"oauthClient");this.oauthClient=e.oauthClient,e.deviceCodePollUrl!=null&&(this.deviceCodePollUrl=e.deviceCodePollUrl),e.headers&&(this.headers=e.headers),e.mode&&(this.mode=e.mode),e.credentials&&(this.credentials=e.credentials)}async startPolling(e,t,o=5){this.pollingActive||(this.pollingActive=!0,c.logger.debug(d({msg:"Starting auto refresh"})),await this.poll(e,o,t))}stopPolling(){this.pollingActive=!1,c.logger.debug(d({msg:"Stopping auto refresh"}))}async poll(e,t,o){var s;if(!e)c.logger.debug(d({msg:"device code poll: no device code provided"})),o("error","Error waiting for authorization");else try{if(c.logger.debug(d({msg:"device code poll: poll"})),!this.deviceCodePollUrl&&this.oauthClient){if(this.oauthClient.getOidcConfig()||await this.oauthClient.loadConfig(),!((s=this.oauthClient.getOidcConfig())!=null&&s.grant_types_supported.includes("http://auth0.com/oauth/grant-type/mfa-oob")))return{error:"invalid_request",error_description:"Server does not support password_mfa grant"};let i=this.oauthClient.getOidcConfig();if(!(i!=null&&i.token_endpoint))return{error:"server_error",error_description:"Couldn't get OIDC configuration"};this.deviceCodePollUrl=i.token_endpoint}if(!this.deviceCodePollUrl)return{error:"server_error",error_description:"Must either provide deviceCodePollUrl or an oauthClient to fetch it from"};const n=await fetch(this.deviceCodePollUrl,{method:"POST",body:JSON.stringify({device_code:e}),headers:{"content-type":"application/json"}});if(n.redirected)this.pollingActive=!1,n.redirected&&o("completeAndRedirect",void 0,n.url);else if(!n.ok)this.pollingActive=!1,o("error","Received an error from the authorization server");else{const i=await n.json();if(c.logger.debug(d({msg:"device code poll: received"+JSON.stringify(i)})),i.error=="expired_token")this.pollingActive=!1,o("expired_token","Timeout waiting for authorization");else if(i.error=="authorization_pending"||i.error=="slow_down"){i.error=="slow_down"&&(t+=5);let a=i.interval??t,h=u=>new Promise(y=>setTimeout(y,u));c.logger.debug(d({msg:"device code poll: waiting "+String(a)+" seconds"})),await h(a*1e3),this.pollingActive&&this.poll(e,t,o)}else i.error?(this.pollingActive=!1,o("error",i.error_description??i.error)):(this.pollingActive=!1,o("complete"))}}catch(n){this.pollingActive=!1;const i=g.asCrossauthError(n);c.logger.debug(d({err:i})),c.logger.error(d({msg:"Polling failed",cerr:i})),o("error",i.message)}}}class hr{constructor(e={}){f(this,"bffPrefix","/bff");f(this,"csrfHeader","X-CROSSAUTH-CSRF");f(this,"enableCsrfProtection",!0);f(this,"headers",{});f(this,"mode","cors");f(this,"credentials","same-origin");f(this,"autoRefresher");f(this,"deviceCodePoller");f(this,"getCsrfTokenUrl","/api/getcsrftoken");f(this,"autoRefreshUrl","/api/refreshtokens");f(this,"tokensUrl","/tokens");e.bffPrefix&&(this.bffPrefix=e.bffPrefix),e.csrfHeader&&(this.csrfHeader=e.csrfHeader),e.enableCsrfProtection!=null&&(this.enableCsrfProtection=e.enableCsrfProtection),e.getCsrfTokenUrl&&(this.getCsrfTokenUrl=e.getCsrfTokenUrl),e.tokensUrl&&(this.tokensUrl=e.tokensUrl),e.autoRefreshUrl&&(this.autoRefreshUrl=e.autoRefreshUrl),this.bffPrefix.endsWith("/")||(this.bffPrefix+="/"),e.headers&&(this.headers=e.headers),e.mode&&(this.mode=e.mode),e.credentials&&(this.credentials=e.credentials),this.autoRefresher=new Ee({...e,autoRefreshUrl:this.autoRefreshUrl,tokenProvider:this}),this.deviceCodePoller=new Pe({...e,oauthClient:void 0})}async getCsrfToken(){if(this.enableCsrfProtection)try{const t=await(await fetch(this.getCsrfTokenUrl,{headers:this.headers,credentials:this.credentials,mode:this.mode})).json();if(!t.ok)throw g.asCrossauthError(t);return t.csrfToken}catch(e){throw g.asCrossauthError(e)}}async getIdToken(e){const t=await this.getTokens(e);return(t==null?void 0:t.id_token)??null}async haveIdToken(e){const t=await this.getTokens(e);return t==null?!1:t.have_id_token!=null?t.have_id_token:"id_token"in t}async getAccessToken(e){const t=await this.getTokens(e);return(t==null?void 0:t.access_token)??null}async haveAccessToken(e){const t=await this.getTokens(e);return t==null?!1:t.have_access_token!=null?t.have_access_token:"access_token"in t}async getRefreshToken(e){const t=await this.getTokens(e);return(t==null?void 0:t.refresh_token)??null}async haveRefreshToken(e){const t=await this.getTokens(e);return t==null?!1:t.have_refresh_token!=null?t.have_refresh_token:"refresh_token"in t}async api(e,t,o,s){let n={...this.headers};!s&&!["GET","HEAD","OPTIONS"].includes(e)&&(s=await this.getCsrfToken(),s&&(n[this.csrfHeader]=s)),t.startsWith("/")&&(t=t.substring(1));let i={};o&&(i.body=JSON.stringify(o));const a=await fetch(this.bffPrefix+t,{headers:n,method:e,mode:this.mode,credentials:this.credentials,...i});let h=null;return a.body&&(h=await a.json()),{status:a.status,body:h}}async getTokens(e){e||(e=await this.getCsrfToken());let t={...this.headers};e&&(t[this.csrfHeader]=e);try{const o=await fetch(this.tokensUrl,{method:"POST",headers:t,mode:this.mode,credentials:this.credentials});return o.status==204?{}:await o.json()}catch(o){throw g.asCrossauthError(o)}}async startAutoRefresh(e=["access","id"],t){return this.autoRefresher.startAutoRefresh(e,t)}stopAutoRefresh(){return this.autoRefresher.stopAutoRefresh()}async startDeviceCodePolling(e,t,o=5){return this.deviceCodePoller.startPolling(e,t,o)}stopDeviceCodePolling(){return this.deviceCodePoller.stopPolling()}async getTokenExpiries(e,t){const o=await this.getTokens(t),s=e.includes("id")?(o==null?void 0:o.id_token)??null:null,n=e.includes("access")?(o==null?void 0:o.access_token)??null:null,i=e.includes("refresh")?(o==null?void 0:o.refresh_token)??null:null;let a,h,u;return s&&(a=s.exp?s.exp:null),n&&(h=n.exp?n.exp:null),i&&(u=i.exp?i.exp:null),{id:a,access:h,refresh:u}}async jsonFetchWithToken(e,t,o){return typeof t.body!="string"&&(t.body=JSON.stringify(t.body)),await fetch(e,t)}receiveTokens(e){return new Promise(t=>{})}}class lr extends dr{async hash(e){const o=new TextEncoder().encode(e),s=await crypto.subtle.digest("SHA-256",o),n=Array.from(new Uint8Array(s));return btoa(n.reduce((i,a)=>i+String.fromCharCode(a),"")).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}}var x,U,R,K,z,B,L;class ur extends cr{constructor(t){t.tokenConsumer||(t.tokenConsumer=new lr(t.client_id,{authServerBaseUrl:t.authServerBaseUrl}));super(t);f(this,"resServerBaseUrl","");f(this,"resServerHeaders",{});f(this,"resServerMode","cors");f(this,"resServerCredentials","same-origin");f(this,"accessTokenResponseType","memory");f(this,"refreshTokenResponseType","memory");f(this,"idTokenResponseType","memory");f(this,"accessTokenName","CROSSAUTH_AT");f(this,"refreshTokenName","CROSSAUTH_RT");f(this,"idTokenName","CROSSAUTH_IT");N(this,x);N(this,U);N(this,R);N(this,K);N(this,z);N(this,B);N(this,L);f(this,"autoRefresher");f(this,"deviceCodePoller");f(this,"deviceAuthorizationUrl","device_authorization");this.resServerBaseUrl!=null&&(this.resServerBaseUrl=t.resServerBaseUrl??"",this.resServerBaseUrl.length>0&&!this.resServerBaseUrl.endsWith("/")&&(this.resServerBaseUrl+="/")),t.accessTokenResponseType&&(this.accessTokenResponseType=t.accessTokenResponseType),t.idTokenResponseType&&(this.idTokenResponseType=t.idTokenResponseType),t.refreshTokenResponseType&&(this.refreshTokenResponseType=t.refreshTokenResponseType),t.accessTokenName&&(this.accessTokenName=t.accessTokenName),t.idTokenName&&(this.idTokenName=t.idTokenName),t.refreshTokenName&&(this.refreshTokenName=t.refreshTokenName),t.resServerHeaders&&(this.resServerHeaders=t.resServerHeaders),t.resServerMode&&(this.resServerMode=t.resServerMode),t.resServerCredentials&&(this.resServerCredentials=t.resServerCredentials),t.client_id&&b(this,B,t.client_id),t.client_secret&&b(this,L,t.client_secret),t.deviceAuthorizationUrl&&(this.deviceAuthorizationUrl=t.deviceAuthorizationUrl),this.autoRefresher=new Ee({...t,autoRefreshUrl:this.authServerBaseUrl+"/token",tokenProvider:this}),this.deviceCodePoller=new Pe({...t,oauthClient:this,deviceCodePollUrl:null});let o,s,n;if(this.idTokenResponseType=="sessionStorage"?o=sessionStorage.getItem(this.idTokenName):this.idTokenResponseType=="localStorage"&&(o=localStorage.getItem(this.idTokenName)),this.accessTokenResponseType=="sessionStorage"?s=sessionStorage.getItem(this.accessTokenName):this.accessTokenResponseType=="localStorage"&&(s=localStorage.getItem(this.accessTokenName)),this.refreshTokenResponseType=="sessionStorage"?n=sessionStorage.getItem(this.refreshTokenName):this.refreshTokenResponseType=="localStorage"&&(n=localStorage.getItem(this.refreshTokenName)),this.receiveTokens({access_token:s,id_token:o,refresh_token:n}),s){const i=this.getTokenPayload(s);i&&(b(this,x,s),b(this,K,i))}if(n){const i=this.getTokenPayload(n);i&&(b(this,U,n),b(this,z,i))}o?this.validateIdToken(o).then(i=>{b(this,R,i),t.autoRefresh&&this.startAutoRefresh(t.autoRefresh).then().catch(a=>{c.logger.debug(d({err:a,msg:"Couldn't start auto refresh"}))})}).catch(i=>{c.logger.debug(d({err:i,msg:"Couldn't validate ID token"}))}):w(this,x)&&t.autoRefresh&&n?this.startAutoRefresh(t.autoRefresh).then().catch(i=>{c.logger.debug(d({err:i,msg:"Couldn't start auto refresh"}))}):n&&!s&&this.refreshTokenFlow(n).then(i=>{c.logger.debug(d({msg:"Refreshed tokens"})),t.autoRefresh&&this.startAutoRefresh(t.autoRefresh).then().catch(a=>{c.logger.debug(d({err:a,msg:"Couldn't start auto refresh"}))})}).catch(i=>{const a=g.asCrossauthError(i);c.logger.debug(d({err:a})),c.logger.error(d({msg:"failed refreshing tokens",cerr:a}))})}get idTokenPayload(){return w(this,R)}async handleRedirectUri(){const t=new URL(window.location.href);if(t.origin+t.pathname!=this.redirect_uri)return;const o=new URLSearchParams(window.location.search);let s,n,i,a;for(const[u,y]of o)u=="code"&&(s=y),u=="state"&&(n=y),u=="error"&&(i=y),u=="error_description"&&(a=y);if(!i&&!s)return;if(i){const u=g.fromOAuthError(i,a);throw c.logger.debug(d({err:u})),c.logger.error(d({cerr:u,msg:"Error from authorize endpoint: "+i})),u}const h=await this.redirectEndpoint(s,n,i,a);if(h.error){const u=g.fromOAuthError(h.error,a);throw c.logger.debug(d({err:u})),c.logger.error(d({cerr:u,msg:"Error from redirect endpoint: "+h.error})),u}return await this.receiveTokens(h),h}async startAutoRefresh(t=["access","id"],o){return this.autoRefresher.startAutoRefresh(t,o)}stopAutoRefresh(){return this.autoRefresher.stopAutoRefresh()}async startDeviceCodePolling(t,o,s=5){return this.deviceCodePoller.startPolling(t,o,s)}stopDeviceCodePolling(){return this.deviceCodePoller.stopPolling()}getIdToken(){return w(this,R)}randomValue(t){const o=new Uint8Array(t);return self.crypto.getRandomValues(o),btoa(o.reduce((s,n)=>s+String.fromCharCode(n),"")).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}async sha256(t){const s=new TextEncoder().encode(t),n=await crypto.subtle.digest("SHA-256",s),i=Array.from(new Uint8Array(n));return btoa(i.reduce((a,h)=>a+String.fromCharCode(h),"")).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}async api(t,o,s){let n={...this.resServerHeaders};o.startsWith("/")&&(o=o.substring(1));let i={};s&&(i.body=JSON.stringify(s));let a;this.accessTokenResponseType=="sessionStorage"?a=sessionStorage.getItem(this.accessTokenName):this.accessTokenResponseType=="localStorage"&&(a=localStorage.getItem(this.accessTokenName)),n.authorization="Bearer "+a;const h=await fetch(this.resServerBaseUrl+o,{headers:n,method:t,mode:this.resServerMode,credentials:this.resServerCredentials,...i});let u=null;return h.body&&(u=await h.json()),{status:h.status,body:u}}async getTokenExpiries(t,o){let s,n,i;return w(this,R)&&(s=w(this,R).exp?w(this,R).exp:null),w(this,K)&&(n=w(this,K).exp?w(this,K).exp:null),w(this,z)&&(i=w(this,z).exp?w(this,z).exp:null),{id:s,access:n,refresh:i}}async jsonFetchWithToken(t,o,s){if(s=="access"){if(!w(this,x))throw new g(m.InvalidToken,"Cannot make fetch with access token - no access token defined");o.headers||(o.headers={}),o.headers.authorization="Bearer "+w(this,x)}else{if(o.body||(o.body={}),!w(this,U))throw new g(m.InvalidToken,"Cannot make fetch with refresh token - no refresh token defined");o.body.refresh_token=w(this,U),o.body.grant_type="refresh_token"}return w(this,B)&&(o.body||(o.body={}),o.body.client_id=w(this,B),w(this,L)&&(o.body.client_secret=w(this,L))),typeof o.body!="string"&&(o.body=JSON.stringify(o.body)),await fetch(t,o)}async getCsrfToken(){}async receiveTokens(t){if(t.access_token){const o=this.getTokenPayload(t.access_token);o&&(b(this,x,t.access_token),b(this,K,o)),this.accessTokenResponseType=="localStorage"?localStorage.setItem(this.accessTokenName,t.access_token):this.accessTokenResponseType=="sessionStorage"&&sessionStorage.setItem(this.accessTokenName,t.access_token)}if(t.refresh_token){const o=this.getTokenPayload(t.refresh_token);o&&(b(this,U,t.refresh_token),b(this,z,o)),this.refreshTokenResponseType=="localStorage"?localStorage.setItem(this.refreshTokenName,t.refresh_token):this.accessTokenResponseType=="sessionStorage"&&sessionStorage.setItem(this.refreshTokenName,t.refresh_token)}if(t.id_token){const o=await this.validateIdToken(t.id_token);b(this,R,o),this.idTokenResponseType=="localStorage"?localStorage.setItem(this.idTokenName,t.id_token):this.idTokenResponseType=="sessionStorage"&&sessionStorage.setItem(this.idTokenName,t.id_token)}}async clientCredentialsFlow(t){const o=await super.clientCredentialsFlow(t);return await this.receiveTokens(o),o}async passwordFlow(t,o,s){const n=await super.passwordFlow(t,o,s);return await this.receiveTokens(n),n}async deviceCodeFlow(t){let o=this.authServerBaseUrl;return o.endsWith("/")||(o+="/"),o+=this.deviceAuthorizationUrl,await super.startDeviceCodeFlow(o,t)}async mfaOtpComplete(t,o){const s=await super.mfaOtpComplete(t,o);return await this.receiveTokens(s),s}async mfaOobComplete(t,o,s){const n=await super.mfaOobComplete(t,o,s);return await this.receiveTokens(n),n}async refreshTokenFlow(t){if(!t)if(w(this,U))t=w(this,U);else throw new g(m.InvalidToken,"Cannot refresh tokens: no refresh token present");const o=await super.refreshTokenFlow(t);return await this.receiveTokens(o),o}async authorizationCodeFlow(t,o=!1){const s=await super.startAuthorizationCodeFlow(t,o);if(s.error||!s.url){const n=g.fromOAuthError(s.error??"Couldn't create URL for authorization code flow",s.error_description);throw c.logger.debug(d({err:n})),n}location.href=s.url}}x=new WeakMap,U=new WeakMap,R=new WeakMap,K=new WeakMap,z=new WeakMap,B=new WeakMap,L=new WeakMap;exports.CrossauthError=g;exports.CrossauthLogger=c;exports.OAuthBffClient=hr;exports.OAuthClient=ur;exports.j=d;
|