@cedarjs/auth-dbauth-api 9.0.0-canary.1784 → 9.0.0-canary.3124
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/DbAuthHandler.d.ts +37 -43
- package/dist/DbAuthHandler.d.ts.map +1 -1
- package/dist/DbAuthHandler.js +171 -162
- package/dist/decoder.js +5 -30
- package/dist/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +7 -61
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -36
- package/dist/originValidation.d.ts +131 -0
- package/dist/originValidation.d.ts.map +1 -0
- package/dist/originValidation.js +92 -0
- package/dist/session.d.ts +114 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +103 -0
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +21 -68
- package/package.json +25 -16
- package/LICENSE +0 -21
package/dist/DbAuthHandler.js
CHANGED
|
@@ -1,43 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var import_shared = require("./shared");
|
|
40
|
-
const DEFAULT_ALLOWED_USER_FIELDS = ["id", "email"];
|
|
1
|
+
import md5 from "md5";
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
3
|
+
import {
|
|
4
|
+
createCorsContext,
|
|
5
|
+
isFetchApiRequest,
|
|
6
|
+
normalizeRequest
|
|
7
|
+
} from "@cedarjs/api";
|
|
8
|
+
import * as DbAuthError from "./errors.js";
|
|
9
|
+
import {
|
|
10
|
+
isProxiedRequest,
|
|
11
|
+
isRequestOriginTrusted,
|
|
12
|
+
requiresOriginValidation,
|
|
13
|
+
resolveRequestHost,
|
|
14
|
+
resolveRequestProtocol
|
|
15
|
+
} from "./originValidation.js";
|
|
16
|
+
import {
|
|
17
|
+
buildCookieAttributes,
|
|
18
|
+
createAuthProviderCookieString,
|
|
19
|
+
createCsrfToken,
|
|
20
|
+
createExpiresAtDate,
|
|
21
|
+
createLoginResponse,
|
|
22
|
+
createSessionCookieString,
|
|
23
|
+
DEFAULT_ALLOWED_USER_FIELDS,
|
|
24
|
+
sanitizeUser
|
|
25
|
+
} from "./session.js";
|
|
26
|
+
import {
|
|
27
|
+
decryptSession,
|
|
28
|
+
extractCookie,
|
|
29
|
+
extractHashingOptions,
|
|
30
|
+
generateCookieName,
|
|
31
|
+
getDbAuthResponseBuilder,
|
|
32
|
+
getSession,
|
|
33
|
+
hashPassword,
|
|
34
|
+
hashToken,
|
|
35
|
+
isLegacySession,
|
|
36
|
+
legacyHashPassword,
|
|
37
|
+
webAuthnSession
|
|
38
|
+
} from "./shared.js";
|
|
41
39
|
class DbAuthHandler {
|
|
42
40
|
event;
|
|
43
41
|
_normalizedRequest;
|
|
@@ -102,7 +100,7 @@ class DbAuthHandler {
|
|
|
102
100
|
}
|
|
103
101
|
// generate a new token (standard UUID)
|
|
104
102
|
static get CSRF_TOKEN() {
|
|
105
|
-
return (
|
|
103
|
+
return createCsrfToken();
|
|
106
104
|
}
|
|
107
105
|
static get AVAILABLE_WEBAUTHN_TRANSPORTS() {
|
|
108
106
|
return ["usb", "ble", "nfc", "internal"];
|
|
@@ -121,7 +119,7 @@ class DbAuthHandler {
|
|
|
121
119
|
deleteHeaders.append(
|
|
122
120
|
"set-cookie",
|
|
123
121
|
[
|
|
124
|
-
`${
|
|
122
|
+
`${generateCookieName(this.options.cookie?.name)}=`,
|
|
125
123
|
...this._cookieAttributes({ expires: "now" })
|
|
126
124
|
].join(";")
|
|
127
125
|
);
|
|
@@ -136,31 +134,29 @@ class DbAuthHandler {
|
|
|
136
134
|
constructor(event, _context, options) {
|
|
137
135
|
this.options = options;
|
|
138
136
|
this.event = event;
|
|
139
|
-
this.httpMethod =
|
|
140
|
-
this.cookie =
|
|
141
|
-
this.createResponse =
|
|
137
|
+
this.httpMethod = isFetchApiRequest(event) ? event.method : event.httpMethod;
|
|
138
|
+
this.cookie = extractCookie(event) || "";
|
|
139
|
+
this.createResponse = getDbAuthResponseBuilder(event);
|
|
142
140
|
this._validateOptions();
|
|
143
141
|
this.db = this.options.db;
|
|
144
142
|
this.dbAccessor = this.db[this.options.authModelAccessor];
|
|
145
143
|
this.dbCredentialAccessor = this.options.credentialModelAccessor ? this.db[this.options.credentialModelAccessor] : null;
|
|
146
144
|
this.hasInvalidSession = false;
|
|
147
145
|
this.allowedUserFields = this.options.allowedUserFields || DEFAULT_ALLOWED_USER_FIELDS;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
sessionExpiresAt.getSeconds() + this.options.login.expires
|
|
146
|
+
this.sessionExpiresDate = createExpiresAtDate(
|
|
147
|
+
this.options.login.expires
|
|
151
148
|
);
|
|
152
|
-
this.sessionExpiresDate = sessionExpiresAt.toUTCString();
|
|
153
149
|
const webAuthnExpiresAt = /* @__PURE__ */ new Date();
|
|
154
150
|
webAuthnExpiresAt.setSeconds(
|
|
155
151
|
webAuthnExpiresAt.getSeconds() + (this.options?.webAuthn?.expires || 0)
|
|
156
152
|
);
|
|
157
153
|
this.webAuthnExpiresDate = webAuthnExpiresAt.toUTCString();
|
|
158
154
|
if (options.cors) {
|
|
159
|
-
this.corsContext =
|
|
155
|
+
this.corsContext = createCorsContext(options.cors);
|
|
160
156
|
}
|
|
161
157
|
try {
|
|
162
|
-
this.encryptedSession =
|
|
163
|
-
const [session, csrfToken] =
|
|
158
|
+
this.encryptedSession = getSession(this.cookie, this.options.cookie?.name);
|
|
159
|
+
const [session, csrfToken] = decryptSession(this.encryptedSession);
|
|
164
160
|
this.session = session;
|
|
165
161
|
this.sessionCsrfToken = csrfToken;
|
|
166
162
|
} catch (e) {
|
|
@@ -175,7 +171,7 @@ class DbAuthHandler {
|
|
|
175
171
|
// is parsed async
|
|
176
172
|
async init() {
|
|
177
173
|
if (!this._normalizedRequest) {
|
|
178
|
-
this._normalizedRequest = await
|
|
174
|
+
this._normalizedRequest = await normalizeRequest(
|
|
179
175
|
this.event
|
|
180
176
|
);
|
|
181
177
|
}
|
|
@@ -205,11 +201,28 @@ class DbAuthHandler {
|
|
|
205
201
|
if (this.httpMethod !== DbAuthHandler.VERBS[method]) {
|
|
206
202
|
return this.createResponse(this._notFound(), corsHeaders);
|
|
207
203
|
}
|
|
204
|
+
if (requiresOriginValidation(this.httpMethod) && !isRequestOriginTrusted(
|
|
205
|
+
{
|
|
206
|
+
method: this.httpMethod,
|
|
207
|
+
headers: this.normalizedRequest.headers,
|
|
208
|
+
host: this._requestHost(),
|
|
209
|
+
protocol: this._requestProtocol(),
|
|
210
|
+
proxied: isProxiedRequest(this.normalizedRequest.headers)
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
trustedOrigins: this.options.trustedOrigins,
|
|
214
|
+
corsOrigin: this.options.cors?.origin
|
|
215
|
+
}
|
|
216
|
+
)) {
|
|
217
|
+
throw new DbAuthError.UntrustedOriginError();
|
|
218
|
+
}
|
|
208
219
|
const [body, headers, options = { statusCode: 200 }] = await this[method]();
|
|
209
220
|
return this.createResponse(this._ok(body, headers, options), corsHeaders);
|
|
210
221
|
} catch (e) {
|
|
211
222
|
if (e instanceof DbAuthError.WrongVerbError) {
|
|
212
223
|
return this.createResponse(this._notFound(), corsHeaders);
|
|
224
|
+
} else if (e instanceof DbAuthError.UntrustedOriginError) {
|
|
225
|
+
return this.createResponse(this._forbidden(e.message), corsHeaders);
|
|
213
226
|
} else {
|
|
214
227
|
return this.createResponse(
|
|
215
228
|
this._badRequest(e.message || e),
|
|
@@ -218,6 +231,25 @@ class DbAuthHandler {
|
|
|
218
231
|
}
|
|
219
232
|
}
|
|
220
233
|
}
|
|
234
|
+
// best-effort host the request was sent to, used by origin validation to
|
|
235
|
+
// allow same-origin requests through with no extra configuration. Prefers
|
|
236
|
+
// `X-Forwarded-Host` over the connection-level host/URL -- see
|
|
237
|
+
// `resolveRequestHost` for why that's safe behind a proxy
|
|
238
|
+
_requestHost() {
|
|
239
|
+
return resolveRequestHost(
|
|
240
|
+
this.normalizedRequest.headers,
|
|
241
|
+
isFetchApiRequest(this.event) ? this.event.url : void 0
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
// best-effort scheme the request arrived over, used alongside
|
|
245
|
+
// `_requestHost` for origin validation. See `resolveRequestProtocol` for
|
|
246
|
+
// when it can and can't be determined reliably
|
|
247
|
+
_requestProtocol() {
|
|
248
|
+
return resolveRequestProtocol(
|
|
249
|
+
this.normalizedRequest.headers,
|
|
250
|
+
isFetchApiRequest(this.event) ? this.event.url : void 0
|
|
251
|
+
);
|
|
252
|
+
}
|
|
221
253
|
async forgotPassword() {
|
|
222
254
|
const { enabled = true } = this.options.forgotPassword;
|
|
223
255
|
if (!enabled) {
|
|
@@ -244,10 +276,10 @@ class DbAuthHandler {
|
|
|
244
276
|
tokenExpires.setSeconds(
|
|
245
277
|
tokenExpires.getSeconds() + this.options.forgotPassword.expires
|
|
246
278
|
);
|
|
247
|
-
let token = (
|
|
279
|
+
let token = md5(uuidv4());
|
|
248
280
|
const buffer = Buffer.from(token);
|
|
249
281
|
token = buffer.toString("base64").replace("=", "").substring(0, 16);
|
|
250
|
-
const tokenHash =
|
|
282
|
+
const tokenHash = hashToken(token);
|
|
251
283
|
try {
|
|
252
284
|
user = await this.dbAccessor.update({
|
|
253
285
|
where: {
|
|
@@ -276,7 +308,7 @@ class DbAuthHandler {
|
|
|
276
308
|
try {
|
|
277
309
|
const user = await this._getCurrentUser();
|
|
278
310
|
let headers = new Headers();
|
|
279
|
-
if (
|
|
311
|
+
if (isLegacySession(this.cookie)) {
|
|
280
312
|
headers = this._loginResponse(user)[1];
|
|
281
313
|
}
|
|
282
314
|
return [user[this.options.authFields.id], headers];
|
|
@@ -327,10 +359,10 @@ class DbAuthHandler {
|
|
|
327
359
|
;
|
|
328
360
|
this.options.signup.passwordValidation?.(password);
|
|
329
361
|
let user = await this._findUserByToken(resetToken);
|
|
330
|
-
const [hashedPassword] =
|
|
362
|
+
const [hashedPassword] = hashPassword(password, {
|
|
331
363
|
salt: user.salt
|
|
332
364
|
});
|
|
333
|
-
const [legacyHashedPassword] =
|
|
365
|
+
const [legacyHashedPassword] = legacyHashPassword(password, user.salt);
|
|
334
366
|
if (!this.options.resetPassword.allowReusedPassword && user.hashedPassword === hashedPassword || user.hashedPassword === legacyHashedPassword) {
|
|
335
367
|
throw new DbAuthError.ReusedPasswordError(
|
|
336
368
|
this.options.resetPassword?.errors?.reusedPassword
|
|
@@ -416,11 +448,9 @@ class DbAuthHandler {
|
|
|
416
448
|
expectedChallenge: user[this.options.authFields.challenge],
|
|
417
449
|
expectedOrigin: webAuthnOptions.origin,
|
|
418
450
|
expectedRPID: webAuthnOptions.domain,
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
),
|
|
423
|
-
credentialPublicKey: credential[webAuthnOptions.credentialFields.publicKey],
|
|
451
|
+
credential: {
|
|
452
|
+
id: credential[webAuthnOptions.credentialFields.id],
|
|
453
|
+
publicKey: credential[webAuthnOptions.credentialFields.publicKey],
|
|
424
454
|
counter: credential[webAuthnOptions.credentialFields.counter],
|
|
425
455
|
transports: credential[webAuthnOptions.credentialFields.transports] ? JSON.parse(
|
|
426
456
|
credential[webAuthnOptions.credentialFields.transports]
|
|
@@ -435,16 +465,17 @@ class DbAuthHandler {
|
|
|
435
465
|
await this._saveChallenge(user[this.options.authFields.id], null);
|
|
436
466
|
}
|
|
437
467
|
const { verified, authenticationInfo } = verification;
|
|
438
|
-
if (verified) {
|
|
439
|
-
|
|
440
|
-
where: {
|
|
441
|
-
[webAuthnOptions.credentialFields.id]: credential[webAuthnOptions.credentialFields.id]
|
|
442
|
-
},
|
|
443
|
-
data: {
|
|
444
|
-
[webAuthnOptions.credentialFields.counter]: authenticationInfo.newCounter
|
|
445
|
-
}
|
|
446
|
-
});
|
|
468
|
+
if (!verified) {
|
|
469
|
+
throw new DbAuthError.WebAuthnError("Authentication failed");
|
|
447
470
|
}
|
|
471
|
+
await this.dbCredentialAccessor.update({
|
|
472
|
+
where: {
|
|
473
|
+
[webAuthnOptions.credentialFields.id]: credential[webAuthnOptions.credentialFields.id]
|
|
474
|
+
},
|
|
475
|
+
data: {
|
|
476
|
+
[webAuthnOptions.credentialFields.counter]: authenticationInfo.newCounter
|
|
477
|
+
}
|
|
478
|
+
});
|
|
448
479
|
const [, headers] = this._loginResponse(user);
|
|
449
480
|
headers.append(
|
|
450
481
|
"set-cookie",
|
|
@@ -459,7 +490,7 @@ class DbAuthHandler {
|
|
|
459
490
|
throw new DbAuthError.WebAuthnError("WebAuthn is not enabled");
|
|
460
491
|
}
|
|
461
492
|
const webAuthnOptions = this.options.webAuthn;
|
|
462
|
-
const credentialId =
|
|
493
|
+
const credentialId = webAuthnSession(this.event);
|
|
463
494
|
let user;
|
|
464
495
|
if (credentialId) {
|
|
465
496
|
const credential = await this.dbCredentialAccessor.findUnique({
|
|
@@ -485,8 +516,7 @@ class DbAuthHandler {
|
|
|
485
516
|
const someOptions = {
|
|
486
517
|
timeout: webAuthnOptions.timeout || 6e4,
|
|
487
518
|
allowCredentials: credentials.map((cred) => ({
|
|
488
|
-
id:
|
|
489
|
-
type: "public-key",
|
|
519
|
+
id: cred[webAuthnOptions.credentialFields.id],
|
|
490
520
|
transports: cred[webAuthnOptions.credentialFields.transports] ? JSON.parse(cred[webAuthnOptions.credentialFields.transports]) : DbAuthHandler.AVAILABLE_WEBAUTHN_TRANSPORTS
|
|
491
521
|
})),
|
|
492
522
|
userVerification: "required",
|
|
@@ -502,6 +532,7 @@ class DbAuthHandler {
|
|
|
502
532
|
// get options for WebAuthn registration
|
|
503
533
|
async webAuthnRegOptions() {
|
|
504
534
|
const { generateRegistrationOptions } = await import("@simplewebauthn/server");
|
|
535
|
+
const { isoUint8Array } = await import("@simplewebauthn/server/helpers");
|
|
505
536
|
if (!this.options?.webAuthn?.enabled) {
|
|
506
537
|
throw new DbAuthError.WebAuthnError("WebAuthn is not enabled");
|
|
507
538
|
}
|
|
@@ -510,8 +541,11 @@ class DbAuthHandler {
|
|
|
510
541
|
const options = {
|
|
511
542
|
rpName: webAuthnOptions.name,
|
|
512
543
|
rpID: webAuthnOptions.domain,
|
|
513
|
-
userID:
|
|
544
|
+
userID: isoUint8Array.fromUTF8String(
|
|
545
|
+
String(user[this.options.authFields.id])
|
|
546
|
+
),
|
|
514
547
|
userName: user[this.options.authFields.username],
|
|
548
|
+
userDisplayName: user[this.options.authFields.username],
|
|
515
549
|
timeout: webAuthnOptions?.timeout || 6e4,
|
|
516
550
|
excludeCredentials: [],
|
|
517
551
|
authenticatorSelection: {
|
|
@@ -555,36 +589,37 @@ class DbAuthHandler {
|
|
|
555
589
|
throw new DbAuthError.WebAuthnError(e.message);
|
|
556
590
|
}
|
|
557
591
|
const { verified, registrationInfo } = verification;
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
592
|
+
if (!verified || !registrationInfo) {
|
|
593
|
+
throw new DbAuthError.WebAuthnError("Registration failed");
|
|
594
|
+
}
|
|
595
|
+
const {
|
|
596
|
+
id: credentialID,
|
|
597
|
+
publicKey: credentialPublicKey,
|
|
598
|
+
counter
|
|
599
|
+
} = registrationInfo.credential;
|
|
600
|
+
const existingDevice = await this.dbCredentialAccessor.findFirst({
|
|
601
|
+
where: {
|
|
602
|
+
[this.options.webAuthn.credentialFields.id]: credentialID,
|
|
603
|
+
[this.options.webAuthn.credentialFields.userId]: user[this.options.authFields.id]
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
if (!existingDevice) {
|
|
607
|
+
const { transports } = this.normalizedRequest.jsonBody || {};
|
|
608
|
+
await this.dbCredentialAccessor.create({
|
|
609
|
+
data: {
|
|
610
|
+
[this.options.webAuthn.credentialFields.id]: credentialID,
|
|
611
|
+
[this.options.webAuthn.credentialFields.userId]: user[this.options.authFields.id],
|
|
612
|
+
[this.options.webAuthn.credentialFields.publicKey]: credentialPublicKey,
|
|
613
|
+
[this.options.webAuthn.credentialFields.transports]: transports ? JSON.stringify(transports) : null,
|
|
614
|
+
[this.options.webAuthn.credentialFields.counter]: counter
|
|
566
615
|
}
|
|
567
616
|
});
|
|
568
|
-
if (!existingDevice) {
|
|
569
|
-
const { transports } = this.normalizedRequest.jsonBody || {};
|
|
570
|
-
await this.dbCredentialAccessor.create({
|
|
571
|
-
data: {
|
|
572
|
-
[this.options.webAuthn.credentialFields.id]: plainCredentialId,
|
|
573
|
-
[this.options.webAuthn.credentialFields.userId]: user[this.options.authFields.id],
|
|
574
|
-
[this.options.webAuthn.credentialFields.publicKey]: credentialPublicKey,
|
|
575
|
-
[this.options.webAuthn.credentialFields.transports]: transports ? JSON.stringify(transports) : null,
|
|
576
|
-
[this.options.webAuthn.credentialFields.counter]: counter
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
} else {
|
|
581
|
-
throw new DbAuthError.WebAuthnError("Registration failed");
|
|
582
617
|
}
|
|
583
618
|
await this._saveChallenge(user[this.options.authFields.id], null);
|
|
584
619
|
const headers = new Headers([
|
|
585
620
|
[
|
|
586
621
|
"set-cookie",
|
|
587
|
-
this._webAuthnCookie(
|
|
622
|
+
this._webAuthnCookie(credentialID, this.webAuthnExpiresDate)
|
|
588
623
|
]
|
|
589
624
|
]);
|
|
590
625
|
return [verified, headers];
|
|
@@ -640,13 +675,7 @@ class DbAuthHandler {
|
|
|
640
675
|
// removes any fields not explicitly allowed to be sent to the client before
|
|
641
676
|
// sending a response over the wire
|
|
642
677
|
_sanitizeUser(user) {
|
|
643
|
-
|
|
644
|
-
Object.keys(sanitized).forEach((key) => {
|
|
645
|
-
if (!this.allowedUserFields.includes(key)) {
|
|
646
|
-
delete sanitized[key];
|
|
647
|
-
}
|
|
648
|
-
});
|
|
649
|
-
return sanitized;
|
|
678
|
+
return sanitizeUser(user, this.allowedUserFields);
|
|
650
679
|
}
|
|
651
680
|
// Converts LambdaEvent or FetchRequest to
|
|
652
681
|
_decodeEvent() {
|
|
@@ -659,56 +688,34 @@ class DbAuthHandler {
|
|
|
659
688
|
expires = "now",
|
|
660
689
|
options = {}
|
|
661
690
|
}) {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const meta = Object.keys(cookieOptions).map((key) => {
|
|
668
|
-
const optionValue = cookieOptions[key];
|
|
669
|
-
if (optionValue === true) {
|
|
670
|
-
return key;
|
|
671
|
-
} else if (optionValue === false) {
|
|
672
|
-
return null;
|
|
673
|
-
} else {
|
|
674
|
-
return `${key}=${optionValue}`;
|
|
675
|
-
}
|
|
676
|
-
}).filter((v) => v);
|
|
677
|
-
const expiresAt = expires === "now" ? DbAuthHandler.PAST_EXPIRES_DATE : expires;
|
|
678
|
-
meta.push(`Expires=${expiresAt}`);
|
|
679
|
-
return meta;
|
|
691
|
+
return buildCookieAttributes({
|
|
692
|
+
cookieConfig: this.options.cookie,
|
|
693
|
+
expires,
|
|
694
|
+
overrideAttributes: options
|
|
695
|
+
});
|
|
680
696
|
}
|
|
681
697
|
_createAuthProviderCookieString() {
|
|
682
|
-
return
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
698
|
+
return createAuthProviderCookieString({
|
|
699
|
+
cookieConfig: this.options.cookie,
|
|
700
|
+
expiresAt: this.sessionExpiresDate
|
|
701
|
+
});
|
|
686
702
|
}
|
|
687
703
|
// returns the set-cookie header to be returned in the request (effectively
|
|
688
704
|
// creates the session)
|
|
689
705
|
_createSessionCookieString(data, csrfToken) {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
return sessionCookieString;
|
|
697
|
-
}
|
|
698
|
-
// checks the CSRF token in the header against the CSRF token in the session
|
|
699
|
-
// and throw an error if they are not the same (not used yet)
|
|
700
|
-
async _validateCsrf() {
|
|
701
|
-
if (this.sessionCsrfToken !== this.normalizedRequest.headers.get("csrf-token")) {
|
|
702
|
-
throw new DbAuthError.CsrfTokenMismatchError();
|
|
703
|
-
}
|
|
704
|
-
return true;
|
|
706
|
+
return createSessionCookieString({
|
|
707
|
+
data,
|
|
708
|
+
csrfToken,
|
|
709
|
+
cookieConfig: this.options.cookie,
|
|
710
|
+
expiresAt: this.sessionExpiresDate
|
|
711
|
+
});
|
|
705
712
|
}
|
|
706
713
|
async _findUserByToken(token) {
|
|
707
714
|
const tokenExpires = /* @__PURE__ */ new Date();
|
|
708
715
|
tokenExpires.setSeconds(
|
|
709
716
|
tokenExpires.getSeconds() - this.options.forgotPassword.expires
|
|
710
717
|
);
|
|
711
|
-
const tokenHash =
|
|
718
|
+
const tokenHash = hashToken(token);
|
|
712
719
|
const user = await this.dbAccessor.findFirst({
|
|
713
720
|
where: {
|
|
714
721
|
[this.options.authFields.resetToken]: tokenHash
|
|
@@ -774,11 +781,11 @@ class DbAuthHandler {
|
|
|
774
781
|
// with the one in the database. Falls back to the legacy CryptoJS algorihtm
|
|
775
782
|
// if no options are present.
|
|
776
783
|
async _verifyPassword(user, password) {
|
|
777
|
-
const options =
|
|
784
|
+
const options = extractHashingOptions(
|
|
778
785
|
user[this.options.authFields.hashedPassword]
|
|
779
786
|
);
|
|
780
787
|
if (Object.keys(options).length) {
|
|
781
|
-
const [hashedPassword] =
|
|
788
|
+
const [hashedPassword] = hashPassword(password, {
|
|
782
789
|
salt: user[this.options.authFields.salt],
|
|
783
790
|
options
|
|
784
791
|
});
|
|
@@ -786,12 +793,12 @@ class DbAuthHandler {
|
|
|
786
793
|
return user;
|
|
787
794
|
}
|
|
788
795
|
} else {
|
|
789
|
-
const [legacyHashedPassword] =
|
|
796
|
+
const [legacyHashedPassword] = legacyHashPassword(
|
|
790
797
|
password,
|
|
791
798
|
user[this.options.authFields.salt]
|
|
792
799
|
);
|
|
793
800
|
if (legacyHashedPassword === user[this.options.authFields.hashedPassword]) {
|
|
794
|
-
const [newHashedPassword] =
|
|
801
|
+
const [newHashedPassword] = hashPassword(password, {
|
|
795
802
|
salt: user[this.options.authFields.salt]
|
|
796
803
|
});
|
|
797
804
|
await this.dbAccessor.update({
|
|
@@ -850,7 +857,7 @@ class DbAuthHandler {
|
|
|
850
857
|
this.options.signup?.errors?.usernameTaken
|
|
851
858
|
);
|
|
852
859
|
}
|
|
853
|
-
const [hashedPassword, salt] =
|
|
860
|
+
const [hashedPassword, salt] = hashPassword(password);
|
|
854
861
|
const newUser = await this.options.signup.handler({
|
|
855
862
|
username,
|
|
856
863
|
hashedPassword,
|
|
@@ -884,16 +891,12 @@ class DbAuthHandler {
|
|
|
884
891
|
}
|
|
885
892
|
}
|
|
886
893
|
_loginResponse(user, statusCode = 200) {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
"set-cookie",
|
|
894
|
-
this._createSessionCookieString(sessionData, csrfToken)
|
|
895
|
-
);
|
|
896
|
-
return [sessionData, headers, { statusCode }];
|
|
894
|
+
return createLoginResponse(user, {
|
|
895
|
+
cookie: this.options.cookie,
|
|
896
|
+
allowedUserFields: this.allowedUserFields,
|
|
897
|
+
expiresAt: this.sessionExpiresDate,
|
|
898
|
+
statusCode
|
|
899
|
+
});
|
|
897
900
|
}
|
|
898
901
|
_logoutResponse(response) {
|
|
899
902
|
return [response ? JSON.stringify(response) : "", this._deleteSessionHeader];
|
|
@@ -918,6 +921,13 @@ class DbAuthHandler {
|
|
|
918
921
|
headers: new Headers({ "content-type": "application/json" })
|
|
919
922
|
};
|
|
920
923
|
}
|
|
924
|
+
_forbidden(message) {
|
|
925
|
+
return {
|
|
926
|
+
statusCode: 403,
|
|
927
|
+
body: JSON.stringify({ error: message }),
|
|
928
|
+
headers: new Headers({ "content-type": "application/json" })
|
|
929
|
+
};
|
|
930
|
+
}
|
|
921
931
|
_getUserMatchCriteriaOptions(username, usernameMatchFlowOption) {
|
|
922
932
|
const findUniqueUserMatchCriteriaOptions = !usernameMatchFlowOption ? { [this.options.authFields.username]: username } : {
|
|
923
933
|
[this.options.authFields.username]: {
|
|
@@ -928,7 +938,6 @@ class DbAuthHandler {
|
|
|
928
938
|
return findUniqueUserMatchCriteriaOptions;
|
|
929
939
|
}
|
|
930
940
|
}
|
|
931
|
-
|
|
932
|
-
0 && (module.exports = {
|
|
941
|
+
export {
|
|
933
942
|
DbAuthHandler
|
|
934
|
-
}
|
|
943
|
+
};
|
package/dist/decoder.js
CHANGED
|
@@ -1,34 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var decoder_exports = {};
|
|
20
|
-
__export(decoder_exports, {
|
|
21
|
-
authDecoder: () => authDecoder,
|
|
22
|
-
createAuthDecoder: () => createAuthDecoder
|
|
23
|
-
});
|
|
24
|
-
module.exports = __toCommonJS(decoder_exports);
|
|
25
|
-
var import_shared = require("./shared");
|
|
1
|
+
import { dbAuthSession } from "./shared.js";
|
|
26
2
|
const createAuthDecoder = (cookieNameTemplate) => {
|
|
27
3
|
return async (_token, type, req) => {
|
|
28
4
|
if (type !== "dbAuth") {
|
|
29
5
|
return null;
|
|
30
6
|
}
|
|
31
|
-
const session =
|
|
7
|
+
const session = dbAuthSession(req.event, cookieNameTemplate);
|
|
32
8
|
return session;
|
|
33
9
|
};
|
|
34
10
|
};
|
|
@@ -36,11 +12,10 @@ const authDecoder = async (_authHeaderValue, type, req) => {
|
|
|
36
12
|
if (type !== "dbAuth") {
|
|
37
13
|
return null;
|
|
38
14
|
}
|
|
39
|
-
const session =
|
|
15
|
+
const session = dbAuthSession(req.event, void 0);
|
|
40
16
|
return session;
|
|
41
17
|
};
|
|
42
|
-
|
|
43
|
-
0 && (module.exports = {
|
|
18
|
+
export {
|
|
44
19
|
authDecoder,
|
|
45
20
|
createAuthDecoder
|
|
46
|
-
}
|
|
21
|
+
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -49,8 +49,8 @@ export declare class DuplicateUsernameError extends Error {
|
|
|
49
49
|
export declare class IncorrectPasswordError extends Error {
|
|
50
50
|
constructor(username: string, message?: string | undefined);
|
|
51
51
|
}
|
|
52
|
-
export declare class
|
|
53
|
-
constructor();
|
|
52
|
+
export declare class UntrustedOriginError extends Error {
|
|
53
|
+
constructor(message?: string);
|
|
54
54
|
}
|
|
55
55
|
export declare class SessionDecryptionError extends Error {
|
|
56
56
|
constructor();
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;;CAO9C;AAED,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAK7C;AAED,qBAAa,oBAAqB,SAAQ,KAAK;;CAK9C;AAED,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED,qBAAa,2BAA4B,SAAQ,KAAK;;CAKrD;AAED,qBAAa,qBAAsB,SAAQ,KAAK;;CAO/C;AAED,qBAAa,0BAA2B,SAAQ,KAAK;;CAOpD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,UAAU,EAAE,MAAM;CAI/B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAExC,QAAQ,GAAE,MAAM,GAAG,SAAqB,EACxC,OAAO,GAAE,MAAM,GAAG,SAA4C;CAUjE;AAED,qBAAa,gCAAiC,SAAQ,KAAK;gBAEvD,OAAO,GAAE,MAAM,GAAG,SAAqD;CAK1E;AAED,qBAAa,aAAc,SAAQ,KAAK;;CAOvC;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAEzC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,GAAG,SAAkC;CAKvD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBAE7C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAM,GAAG,SAAmD;CAKxE;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBAE7C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAM,GAAG,SAAgD;CAKrE;AAED,qBAAa,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;;CAO9C;AAED,qBAAa,wBAAyB,SAAQ,KAAK;;CAKlD;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAK7C;AAED,qBAAa,oBAAqB,SAAQ,KAAK;;CAK9C;AAED,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED,qBAAa,2BAA4B,SAAQ,KAAK;;CAKrD;AAED,qBAAa,qBAAsB,SAAQ,KAAK;;CAO/C;AAED,qBAAa,0BAA2B,SAAQ,KAAK;;CAOpD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,IAAI,EAAE,MAAM;CAIzB;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,UAAU,EAAE,MAAM;CAI/B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAExC,QAAQ,GAAE,MAAM,GAAG,SAAqB,EACxC,OAAO,GAAE,MAAM,GAAG,SAA4C;CAUjE;AAED,qBAAa,gCAAiC,SAAQ,KAAK;gBAEvD,OAAO,GAAE,MAAM,GAAG,SAAqD;CAK1E;AAED,qBAAa,aAAc,SAAQ,KAAK;;CAOvC;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAEzC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,GAAG,SAAkC;CAKvD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBAE7C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAM,GAAG,SAAmD;CAKxE;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBAE7C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAM,GAAG,SAAgD;CAKrE;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,SAAkC;CAItD;AAED,qBAAa,sBAAuB,SAAQ,KAAK;;CAKhD;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,SAAwB;CAI5C;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,SAAyB;CAI7C;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,SAAyB;CAI7C;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,SAAuB;CAI3C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,SAA0B;CAI9C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,SAA0B;CAI9C;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,SAA2B;CAI/C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,SAA+B;CAInD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,SAAwB;CAI5C;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,SAA2B;CAI/C;AAED,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,SAAmB;CAIvC;AAED,qBAAa,sBAAuB,SAAQ,aAAa;gBAErD,OAAO,SAAyD;CAKnE"}
|