@cedarjs/auth-dbauth-api 7.0.0-canary.3073 → 7.0.0-canary.3075
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 +23 -33
- package/dist/DbAuthHandler.d.ts.map +1 -1
- package/dist/DbAuthHandler.js +85 -61
- package/dist/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- 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/package.json +4 -4
package/dist/DbAuthHandler.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AuthenticationResponseJSON, RegistrationResponseJSON } from '@simplewebauthn/server';
|
|
2
2
|
import type { APIGatewayProxyEvent, Context as LambdaContext } from 'aws-lambda';
|
|
3
3
|
import type { CorsConfig, CorsContext, PartialRequest } from '@cedarjs/api';
|
|
4
|
+
import type { DbAuthCookieConfig } from './session.js';
|
|
4
5
|
interface SignupFlowOptions<TUserAttributes = Record<string, unknown>> {
|
|
5
6
|
/**
|
|
6
7
|
* Allow users to sign up. Defaults to true.
|
|
@@ -170,33 +171,7 @@ export interface DbAuthHandlerOptions<TUser = UserType, TUserAttributes = Record
|
|
|
170
171
|
/**
|
|
171
172
|
* Object containing cookie config options
|
|
172
173
|
*/
|
|
173
|
-
cookie?:
|
|
174
|
-
/** @deprecated set this option in `cookie.attributes` */
|
|
175
|
-
Path?: string;
|
|
176
|
-
/** @deprecated set this option in `cookie.attributes` */
|
|
177
|
-
HttpOnly?: boolean;
|
|
178
|
-
/** @deprecated set this option in `cookie.attributes` */
|
|
179
|
-
Secure?: boolean;
|
|
180
|
-
/** @deprecated set this option in `cookie.attributes` */
|
|
181
|
-
SameSite?: string;
|
|
182
|
-
/** @deprecated set this option in `cookie.attributes` */
|
|
183
|
-
Domain?: string;
|
|
184
|
-
attributes?: {
|
|
185
|
-
Path?: string;
|
|
186
|
-
HttpOnly?: boolean;
|
|
187
|
-
Secure?: boolean;
|
|
188
|
-
SameSite?: string;
|
|
189
|
-
Domain?: string;
|
|
190
|
-
};
|
|
191
|
-
/**
|
|
192
|
-
* The name of the cookie that dbAuth sets
|
|
193
|
-
*
|
|
194
|
-
* %port% will be replaced with the port the api server is running on.
|
|
195
|
-
* If you have multiple RW apps running on the same host, you'll need to
|
|
196
|
-
* make sure they all use unique cookie names
|
|
197
|
-
*/
|
|
198
|
-
name?: string;
|
|
199
|
-
};
|
|
174
|
+
cookie?: DbAuthCookieConfig;
|
|
200
175
|
/**
|
|
201
176
|
* Object containing forgot password options
|
|
202
177
|
*/
|
|
@@ -231,6 +206,17 @@ export interface DbAuthHandlerOptions<TUser = UserType, TUserAttributes = Record
|
|
|
231
206
|
* CORS settings, same as in createGraphqlHandler
|
|
232
207
|
*/
|
|
233
208
|
cors?: CorsConfig;
|
|
209
|
+
/**
|
|
210
|
+
* Extra origins that are trusted for state-changing (non-GET) requests,
|
|
211
|
+
* on top of the request's own host and any origins already listed in
|
|
212
|
+
* `cors.origin`.
|
|
213
|
+
*
|
|
214
|
+
* Needed when the web side and API are on different origins and
|
|
215
|
+
* `cors.origin` isn't set to those origins, or when `cors.origin` is set
|
|
216
|
+
* to `true` -- reflecting any request origin is never treated as trust,
|
|
217
|
+
* so that combination requires listing trusted origins here explicitly.
|
|
218
|
+
*/
|
|
219
|
+
trustedOrigins?: string | string[];
|
|
234
220
|
}
|
|
235
221
|
export interface SignupHandlerOptions<TUserAttributes> {
|
|
236
222
|
username: string;
|
|
@@ -312,6 +298,8 @@ export declare class DbAuthHandler<TUser extends UserType, TUserAttributes = Rec
|
|
|
312
298
|
body?: string | undefined;
|
|
313
299
|
statusCode: number;
|
|
314
300
|
}>;
|
|
301
|
+
_requestHost(): string | null;
|
|
302
|
+
_requestProtocol(): string | null;
|
|
315
303
|
forgotPassword(): Promise<AuthMethodOutput>;
|
|
316
304
|
getToken(): Promise<AuthMethodOutput>;
|
|
317
305
|
login(): Promise<AuthMethodOutput>;
|
|
@@ -326,15 +314,14 @@ export declare class DbAuthHandler<TUser extends UserType, TUserAttributes = Rec
|
|
|
326
314
|
_validateOptions(): void;
|
|
327
315
|
_saveChallenge(userId: string | number, value: string | null): Promise<void>;
|
|
328
316
|
_webAuthnCookie(id: string, expires: string): string;
|
|
329
|
-
_sanitizeUser(user: Record<string, unknown>):
|
|
317
|
+
_sanitizeUser(user: Record<string, unknown>): Record<string, unknown>;
|
|
330
318
|
_decodeEvent(): void;
|
|
331
319
|
_cookieAttributes({ expires, options, }: {
|
|
332
320
|
expires?: 'now' | string;
|
|
333
321
|
options?: DbAuthHandlerOptions['cookie'];
|
|
334
|
-
}):
|
|
322
|
+
}): string[];
|
|
335
323
|
_createAuthProviderCookieString(): string;
|
|
336
324
|
_createSessionCookieString<TIdType = any>(data: DbAuthSession<TIdType>, csrfToken: string): string;
|
|
337
|
-
_validateCsrf(): Promise<boolean>;
|
|
338
325
|
_findUserByToken(token: string): Promise<any>;
|
|
339
326
|
_clearResetToken(user: Record<string, unknown>): Promise<void>;
|
|
340
327
|
_verifyUser(username: string | undefined, password: string | undefined): Promise<any>;
|
|
@@ -343,9 +330,7 @@ export declare class DbAuthHandler<TUser extends UserType, TUserAttributes = Rec
|
|
|
343
330
|
_createUser(): Promise<any>;
|
|
344
331
|
_getAuthMethod(): Promise<AuthMethodNames>;
|
|
345
332
|
_validateField(name: string, value: string | undefined): value is string;
|
|
346
|
-
_loginResponse(user: Record<string, any>, statusCode?: number): [{
|
|
347
|
-
id: string;
|
|
348
|
-
}, Headers, {
|
|
333
|
+
_loginResponse(user: Record<string, any>, statusCode?: number): [Record<string, any>, Headers, {
|
|
349
334
|
statusCode: number;
|
|
350
335
|
}];
|
|
351
336
|
_logoutResponse(response?: Record<string, unknown>): AuthMethodOutput;
|
|
@@ -364,6 +349,11 @@ export declare class DbAuthHandler<TUser extends UserType, TUserAttributes = Rec
|
|
|
364
349
|
body: string;
|
|
365
350
|
headers: Headers;
|
|
366
351
|
};
|
|
352
|
+
_forbidden(message: string): {
|
|
353
|
+
statusCode: number;
|
|
354
|
+
body: string;
|
|
355
|
+
headers: Headers;
|
|
356
|
+
};
|
|
367
357
|
_getUserMatchCriteriaOptions(username: string, usernameMatchFlowOption: string | undefined): {
|
|
368
358
|
[x: string]: string;
|
|
369
359
|
} | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbAuthHandler.d.ts","sourceRoot":"","sources":["../src/DbAuthHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAG1B,wBAAwB,EAKzB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,YAAY,CAAA;AAIhF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"DbAuthHandler.d.ts","sourceRoot":"","sources":["../src/DbAuthHandler.ts"],"names":[],"mappings":"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"}
|
package/dist/DbAuthHandler.js
CHANGED
|
@@ -6,9 +6,25 @@ import {
|
|
|
6
6
|
normalizeRequest
|
|
7
7
|
} from "@cedarjs/api";
|
|
8
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";
|
|
9
26
|
import {
|
|
10
27
|
decryptSession,
|
|
11
|
-
encryptSession,
|
|
12
28
|
extractCookie,
|
|
13
29
|
extractHashingOptions,
|
|
14
30
|
generateCookieName,
|
|
@@ -20,7 +36,6 @@ import {
|
|
|
20
36
|
legacyHashPassword,
|
|
21
37
|
webAuthnSession
|
|
22
38
|
} from "./shared.js";
|
|
23
|
-
const DEFAULT_ALLOWED_USER_FIELDS = ["id", "email"];
|
|
24
39
|
class DbAuthHandler {
|
|
25
40
|
event;
|
|
26
41
|
_normalizedRequest;
|
|
@@ -85,7 +100,7 @@ class DbAuthHandler {
|
|
|
85
100
|
}
|
|
86
101
|
// generate a new token (standard UUID)
|
|
87
102
|
static get CSRF_TOKEN() {
|
|
88
|
-
return
|
|
103
|
+
return createCsrfToken();
|
|
89
104
|
}
|
|
90
105
|
static get AVAILABLE_WEBAUTHN_TRANSPORTS() {
|
|
91
106
|
return ["usb", "ble", "nfc", "internal"];
|
|
@@ -128,11 +143,9 @@ class DbAuthHandler {
|
|
|
128
143
|
this.dbCredentialAccessor = this.options.credentialModelAccessor ? this.db[this.options.credentialModelAccessor] : null;
|
|
129
144
|
this.hasInvalidSession = false;
|
|
130
145
|
this.allowedUserFields = this.options.allowedUserFields || DEFAULT_ALLOWED_USER_FIELDS;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
sessionExpiresAt.getSeconds() + this.options.login.expires
|
|
146
|
+
this.sessionExpiresDate = createExpiresAtDate(
|
|
147
|
+
this.options.login.expires
|
|
134
148
|
);
|
|
135
|
-
this.sessionExpiresDate = sessionExpiresAt.toUTCString();
|
|
136
149
|
const webAuthnExpiresAt = /* @__PURE__ */ new Date();
|
|
137
150
|
webAuthnExpiresAt.setSeconds(
|
|
138
151
|
webAuthnExpiresAt.getSeconds() + (this.options?.webAuthn?.expires || 0)
|
|
@@ -188,11 +201,28 @@ class DbAuthHandler {
|
|
|
188
201
|
if (this.httpMethod !== DbAuthHandler.VERBS[method]) {
|
|
189
202
|
return this.createResponse(this._notFound(), corsHeaders);
|
|
190
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
|
+
}
|
|
191
219
|
const [body, headers, options = { statusCode: 200 }] = await this[method]();
|
|
192
220
|
return this.createResponse(this._ok(body, headers, options), corsHeaders);
|
|
193
221
|
} catch (e) {
|
|
194
222
|
if (e instanceof DbAuthError.WrongVerbError) {
|
|
195
223
|
return this.createResponse(this._notFound(), corsHeaders);
|
|
224
|
+
} else if (e instanceof DbAuthError.UntrustedOriginError) {
|
|
225
|
+
return this.createResponse(this._forbidden(e.message), corsHeaders);
|
|
196
226
|
} else {
|
|
197
227
|
return this.createResponse(
|
|
198
228
|
this._badRequest(e.message || e),
|
|
@@ -201,6 +231,25 @@ class DbAuthHandler {
|
|
|
201
231
|
}
|
|
202
232
|
}
|
|
203
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
|
+
}
|
|
204
253
|
async forgotPassword() {
|
|
205
254
|
const { enabled = true } = this.options.forgotPassword;
|
|
206
255
|
if (!enabled) {
|
|
@@ -626,13 +675,7 @@ class DbAuthHandler {
|
|
|
626
675
|
// removes any fields not explicitly allowed to be sent to the client before
|
|
627
676
|
// sending a response over the wire
|
|
628
677
|
_sanitizeUser(user) {
|
|
629
|
-
|
|
630
|
-
Object.keys(sanitized).forEach((key) => {
|
|
631
|
-
if (!this.allowedUserFields.includes(key)) {
|
|
632
|
-
delete sanitized[key];
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
return sanitized;
|
|
678
|
+
return sanitizeUser(user, this.allowedUserFields);
|
|
636
679
|
}
|
|
637
680
|
// Converts LambdaEvent or FetchRequest to
|
|
638
681
|
_decodeEvent() {
|
|
@@ -645,49 +688,27 @@ class DbAuthHandler {
|
|
|
645
688
|
expires = "now",
|
|
646
689
|
options = {}
|
|
647
690
|
}) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const meta = Object.keys(cookieOptions).map((key) => {
|
|
654
|
-
const optionValue = cookieOptions[key];
|
|
655
|
-
if (optionValue === true) {
|
|
656
|
-
return key;
|
|
657
|
-
} else if (optionValue === false) {
|
|
658
|
-
return null;
|
|
659
|
-
} else {
|
|
660
|
-
return `${key}=${optionValue}`;
|
|
661
|
-
}
|
|
662
|
-
}).filter((v) => v);
|
|
663
|
-
const expiresAt = expires === "now" ? DbAuthHandler.PAST_EXPIRES_DATE : expires;
|
|
664
|
-
meta.push(`Expires=${expiresAt}`);
|
|
665
|
-
return meta;
|
|
691
|
+
return buildCookieAttributes({
|
|
692
|
+
cookieConfig: this.options.cookie,
|
|
693
|
+
expires,
|
|
694
|
+
overrideAttributes: options
|
|
695
|
+
});
|
|
666
696
|
}
|
|
667
697
|
_createAuthProviderCookieString() {
|
|
668
|
-
return
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
698
|
+
return createAuthProviderCookieString({
|
|
699
|
+
cookieConfig: this.options.cookie,
|
|
700
|
+
expiresAt: this.sessionExpiresDate
|
|
701
|
+
});
|
|
672
702
|
}
|
|
673
703
|
// returns the set-cookie header to be returned in the request (effectively
|
|
674
704
|
// creates the session)
|
|
675
705
|
_createSessionCookieString(data, csrfToken) {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
return sessionCookieString;
|
|
683
|
-
}
|
|
684
|
-
// checks the CSRF token in the header against the CSRF token in the session
|
|
685
|
-
// and throw an error if they are not the same (not used yet)
|
|
686
|
-
async _validateCsrf() {
|
|
687
|
-
if (this.sessionCsrfToken !== this.normalizedRequest.headers.get("csrf-token")) {
|
|
688
|
-
throw new DbAuthError.CsrfTokenMismatchError();
|
|
689
|
-
}
|
|
690
|
-
return true;
|
|
706
|
+
return createSessionCookieString({
|
|
707
|
+
data,
|
|
708
|
+
csrfToken,
|
|
709
|
+
cookieConfig: this.options.cookie,
|
|
710
|
+
expiresAt: this.sessionExpiresDate
|
|
711
|
+
});
|
|
691
712
|
}
|
|
692
713
|
async _findUserByToken(token) {
|
|
693
714
|
const tokenExpires = /* @__PURE__ */ new Date();
|
|
@@ -870,16 +891,12 @@ class DbAuthHandler {
|
|
|
870
891
|
}
|
|
871
892
|
}
|
|
872
893
|
_loginResponse(user, statusCode = 200) {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
"set-cookie",
|
|
880
|
-
this._createSessionCookieString(sessionData, csrfToken)
|
|
881
|
-
);
|
|
882
|
-
return [sessionData, headers, { statusCode }];
|
|
894
|
+
return createLoginResponse(user, {
|
|
895
|
+
cookie: this.options.cookie,
|
|
896
|
+
allowedUserFields: this.allowedUserFields,
|
|
897
|
+
expiresAt: this.sessionExpiresDate,
|
|
898
|
+
statusCode
|
|
899
|
+
});
|
|
883
900
|
}
|
|
884
901
|
_logoutResponse(response) {
|
|
885
902
|
return [response ? JSON.stringify(response) : "", this._deleteSessionHeader];
|
|
@@ -904,6 +921,13 @@ class DbAuthHandler {
|
|
|
904
921
|
headers: new Headers({ "content-type": "application/json" })
|
|
905
922
|
};
|
|
906
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
|
+
}
|
|
907
931
|
_getUserMatchCriteriaOptions(username, usernameMatchFlowOption) {
|
|
908
932
|
const findUniqueUserMatchCriteriaOptions = !usernameMatchFlowOption ? { [this.options.authFields.username]: username } : {
|
|
909
933
|
[this.options.authFields.username]: {
|
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"}
|
package/dist/errors.js
CHANGED
|
@@ -112,10 +112,10 @@ class IncorrectPasswordError extends Error {
|
|
|
112
112
|
this.name = "IncorrectPasswordError";
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
class
|
|
116
|
-
constructor() {
|
|
117
|
-
super(
|
|
118
|
-
this.name = "
|
|
115
|
+
class UntrustedOriginError extends Error {
|
|
116
|
+
constructor(message = "Request origin is not trusted") {
|
|
117
|
+
super(message);
|
|
118
|
+
this.name = "UntrustedOriginError";
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
class SessionDecryptionError extends Error {
|
|
@@ -197,7 +197,6 @@ class NoWebAuthnSessionError extends WebAuthnError {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
export {
|
|
200
|
-
CsrfTokenMismatchError,
|
|
201
200
|
DuplicateUsernameError,
|
|
202
201
|
FieldRequiredError,
|
|
203
202
|
FlowNotEnabledError,
|
|
@@ -222,6 +221,7 @@ export {
|
|
|
222
221
|
ReusedPasswordError,
|
|
223
222
|
SessionDecryptionError,
|
|
224
223
|
UnknownAuthMethodError,
|
|
224
|
+
UntrustedOriginError,
|
|
225
225
|
UserNotFoundError,
|
|
226
226
|
UsernameAndPasswordRequiredError,
|
|
227
227
|
UsernameNotFoundError,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './DbAuthHandler.js';
|
|
2
2
|
export { PasswordValidationError } from './errors.js';
|
|
3
|
+
export * from './session.js';
|
|
3
4
|
export * from './shared.js';
|
|
4
5
|
export { authDecoder, createAuthDecoder } from './decoder.js';
|
|
6
|
+
export * from './originValidation.js';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACrD,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACrD,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC7D,cAAc,uBAAuB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from "./DbAuthHandler.js";
|
|
2
2
|
import { PasswordValidationError } from "./errors.js";
|
|
3
|
+
export * from "./session.js";
|
|
3
4
|
export * from "./shared.js";
|
|
4
5
|
import { authDecoder, createAuthDecoder } from "./decoder.js";
|
|
6
|
+
export * from "./originValidation.js";
|
|
5
7
|
export {
|
|
6
8
|
PasswordValidationError,
|
|
7
9
|
authDecoder,
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { CorsConfig } from '@cedarjs/api';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal, transport-agnostic shape of an incoming request needed to decide
|
|
4
|
+
* whether its `Origin` header should be trusted for a state-changing
|
|
5
|
+
* request. Deliberately decoupled from any specific request/event type (no
|
|
6
|
+
* `DbAuthHandler` coupling) so this helper can be reused by other handler
|
|
7
|
+
* packages.
|
|
8
|
+
*/
|
|
9
|
+
export interface OriginValidationRequest {
|
|
10
|
+
/**
|
|
11
|
+
* HTTP method of the request, e.g. `GET`, `POST`. Used by
|
|
12
|
+
* {@link requiresOriginValidation} to decide whether a request needs to be
|
|
13
|
+
* checked at all.
|
|
14
|
+
*/
|
|
15
|
+
method: string;
|
|
16
|
+
/**
|
|
17
|
+
* Request headers, including `origin` if the browser sent one.
|
|
18
|
+
*/
|
|
19
|
+
headers: Headers;
|
|
20
|
+
/**
|
|
21
|
+
* Host (and port, if non-default) the request was sent to, resolved with
|
|
22
|
+
* {@link resolveRequestHost}. Used to allow same-origin requests through
|
|
23
|
+
* with no extra configuration, which covers the standard Cedar setup
|
|
24
|
+
* where the web side proxies API requests through its own origin. Pass
|
|
25
|
+
* `null` when the host can't be determined.
|
|
26
|
+
*/
|
|
27
|
+
host?: string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Scheme (`http`/`https`) the request is considered to have arrived
|
|
30
|
+
* over, resolved with {@link resolveRequestProtocol}, when it can be
|
|
31
|
+
* determined reliably. Used as an extra check alongside `host` when
|
|
32
|
+
* deciding whether the `Origin` header matches the request's own
|
|
33
|
+
* origin. Pass `null`/`undefined` when it can't be determined -- in that
|
|
34
|
+
* case only the host is compared, unless `proxied` narrows that further
|
|
35
|
+
* (see {@link isProxiedRequest}).
|
|
36
|
+
*/
|
|
37
|
+
protocol?: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the request declares itself as arriving through a forwarding
|
|
40
|
+
* proxy, resolved with {@link isProxiedRequest}. Scopes the
|
|
41
|
+
* unknown-scheme same-host restriction to requests a proxy actually
|
|
42
|
+
* touched -- see `isSameOrigin`.
|
|
43
|
+
*/
|
|
44
|
+
proxied?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface OriginValidationConfig {
|
|
47
|
+
/**
|
|
48
|
+
* Extra origins that are always trusted for state-changing requests, on
|
|
49
|
+
* top of the request's own host and any origins already listed in
|
|
50
|
+
* `cors.origin`.
|
|
51
|
+
*/
|
|
52
|
+
trustedOrigins?: string | string[];
|
|
53
|
+
/**
|
|
54
|
+
* The `origin` value from a handler's `cors` config (same shape as passed
|
|
55
|
+
* to `createCorsContext`). String and array values are treated as
|
|
56
|
+
* trusted origins.
|
|
57
|
+
*
|
|
58
|
+
* `true` (reflect any request origin back in
|
|
59
|
+
* `Access-Control-Allow-Origin`) is intentionally NOT treated as trust --
|
|
60
|
+
* combined with `credentials: true` that is the exact misconfiguration
|
|
61
|
+
* this check protects against. Apps that need to accept requests from an
|
|
62
|
+
* arbitrary set of origins must list them explicitly in `trustedOrigins`
|
|
63
|
+
* instead.
|
|
64
|
+
*/
|
|
65
|
+
corsOrigin?: CorsConfig['origin'];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* HTTP methods that can change server-side state and therefore need their
|
|
69
|
+
* `Origin` validated. `GET` and `HEAD` requests are read-only and are never
|
|
70
|
+
* checked.
|
|
71
|
+
*/
|
|
72
|
+
export declare function requiresOriginValidation(method: string): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Resolves the host a request should be considered as having arrived at,
|
|
75
|
+
* preferring a forwarding proxy's advertised host over the connection-level
|
|
76
|
+
* one.
|
|
77
|
+
*
|
|
78
|
+
* A proxy in front of the api side (this framework's own `cedar serve
|
|
79
|
+
* --ud`, or an external nginx/CDN) terminates the browser's connection and
|
|
80
|
+
* opens a new one to the api server, so the request's own URL/`Host` header
|
|
81
|
+
* reflects that internal hop rather than the origin-facing host the
|
|
82
|
+
* browser actually targeted. `X-Forwarded-Host` carries the origin-facing
|
|
83
|
+
* host instead.
|
|
84
|
+
*
|
|
85
|
+
* Trusting `X-Forwarded-Host` here is safe for CSRF purposes: a cross-site
|
|
86
|
+
* HTML form can't set arbitrary request headers, and a cross-origin
|
|
87
|
+
* `fetch()` that sets a custom header triggers a CORS preflight, so an
|
|
88
|
+
* attacker can't forge it without already having crossed the browser's
|
|
89
|
+
* CORS checks.
|
|
90
|
+
*
|
|
91
|
+
* @param url - The request's own URL (Fetch API requests only), used as a
|
|
92
|
+
* fallback when neither `X-Forwarded-Host` nor `Host` is present.
|
|
93
|
+
*/
|
|
94
|
+
export declare function resolveRequestHost(headers: Headers, url?: string | null): string | null;
|
|
95
|
+
/**
|
|
96
|
+
* Resolves the scheme (`http`/`https`) a request should be considered as
|
|
97
|
+
* having arrived over, mirroring {@link resolveRequestHost}.
|
|
98
|
+
*
|
|
99
|
+
* The request's own URL is only used as a fallback when no
|
|
100
|
+
* `X-Forwarded-Host` is present -- once a proxy has declared itself by
|
|
101
|
+
* setting that header, the request's own URL reflects the internal hop to
|
|
102
|
+
* the proxy, and its scheme can't be assumed to match what the browser
|
|
103
|
+
* actually used unless the proxy also set `X-Forwarded-Proto`.
|
|
104
|
+
*
|
|
105
|
+
* @param url - The request's own URL (Fetch API requests only).
|
|
106
|
+
*/
|
|
107
|
+
export declare function resolveRequestProtocol(headers: Headers, url?: string | null): string | null;
|
|
108
|
+
/**
|
|
109
|
+
* Whether a request declares itself as arriving through a forwarding
|
|
110
|
+
* proxy, i.e. carries an `X-Forwarded-Host` header.
|
|
111
|
+
*
|
|
112
|
+
* Used to scope the unknown-scheme same-host restriction (see
|
|
113
|
+
* `isSameOrigin`) to requests a proxy actually touched. A request with no
|
|
114
|
+
* forwarding headers at all is a direct connection -- the normal case for
|
|
115
|
+
* dev servers, classic `cedar serve`, and most self-hosts -- not evidence
|
|
116
|
+
* of a proxy.
|
|
117
|
+
*/
|
|
118
|
+
export declare function isProxiedRequest(headers: Headers): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Decides whether a request's `Origin` header should be trusted.
|
|
121
|
+
*
|
|
122
|
+
* Requests with no `Origin` header are always trusted: non-browser clients
|
|
123
|
+
* (server-to-server calls, CLIs, mobile apps) don't send one and don't carry
|
|
124
|
+
* ambient browser cookies, so they aren't CSRF vectors.
|
|
125
|
+
*
|
|
126
|
+
* When an `Origin` header is present, it's trusted when it matches the
|
|
127
|
+
* request's own host, is listed in `trustedOrigins`, or is listed in
|
|
128
|
+
* `corsOrigin`. Everything else is untrusted.
|
|
129
|
+
*/
|
|
130
|
+
export declare function isRequestOriginTrusted(request: OriginValidationRequest, config: OriginValidationConfig): boolean;
|
|
131
|
+
//# sourceMappingURL=originValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"originValidation.d.ts","sourceRoot":"","sources":["../src/originValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAClC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;CAClC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGhE;AAgBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,GAAG,IAAI,CAef;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE1D;AA+CD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CA6BT"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
function requiresOriginValidation(method) {
|
|
2
|
+
const upperMethod = method.toUpperCase();
|
|
3
|
+
return upperMethod !== "GET" && upperMethod !== "HEAD";
|
|
4
|
+
}
|
|
5
|
+
function toOriginList(value) {
|
|
6
|
+
if (!value) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return Array.isArray(value) ? value : [value];
|
|
10
|
+
}
|
|
11
|
+
function firstForwardedValue(headerValue) {
|
|
12
|
+
return headerValue.split(",")[0].trim();
|
|
13
|
+
}
|
|
14
|
+
function resolveRequestHost(headers, url) {
|
|
15
|
+
const forwardedHost = headers.get("x-forwarded-host");
|
|
16
|
+
if (forwardedHost) {
|
|
17
|
+
return firstForwardedValue(forwardedHost);
|
|
18
|
+
}
|
|
19
|
+
const host = headers.get("host");
|
|
20
|
+
if (host) {
|
|
21
|
+
return host;
|
|
22
|
+
}
|
|
23
|
+
if (url) {
|
|
24
|
+
try {
|
|
25
|
+
return new URL(url).host;
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function resolveRequestProtocol(headers, url) {
|
|
33
|
+
const forwardedProto = headers.get("x-forwarded-proto");
|
|
34
|
+
if (forwardedProto) {
|
|
35
|
+
return firstForwardedValue(forwardedProto).toLowerCase();
|
|
36
|
+
}
|
|
37
|
+
if (!headers.get("x-forwarded-host") && url) {
|
|
38
|
+
try {
|
|
39
|
+
return new URL(url).protocol.replace(":", "");
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
function isProxiedRequest(headers) {
|
|
47
|
+
return headers.get("x-forwarded-host") !== null;
|
|
48
|
+
}
|
|
49
|
+
function isSameOrigin(origin, host, protocol, proxied) {
|
|
50
|
+
try {
|
|
51
|
+
const originUrl = new URL(origin);
|
|
52
|
+
if (originUrl.host !== host) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (protocol) {
|
|
56
|
+
return originUrl.protocol === `${protocol}:`;
|
|
57
|
+
}
|
|
58
|
+
if (proxied) {
|
|
59
|
+
return originUrl.protocol === "https:";
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function isRequestOriginTrusted(request, config) {
|
|
67
|
+
const origin = request.headers.get("origin");
|
|
68
|
+
if (!origin) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (request.host && isSameOrigin(origin, request.host, request.protocol, request.proxied)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
const trustedOrigins = toOriginList(config.trustedOrigins);
|
|
75
|
+
if (trustedOrigins.includes(origin)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const corsOrigins = toOriginList(
|
|
79
|
+
typeof config.corsOrigin === "string" || Array.isArray(config.corsOrigin) ? config.corsOrigin : void 0
|
|
80
|
+
);
|
|
81
|
+
if (corsOrigins.includes(origin)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
isProxiedRequest,
|
|
88
|
+
isRequestOriginTrusted,
|
|
89
|
+
requiresOriginValidation,
|
|
90
|
+
resolveRequestHost,
|
|
91
|
+
resolveRequestProtocol
|
|
92
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie attributes that can be set on a dbAuth cookie, either as
|
|
3
|
+
* `cookie.attributes` or (deprecated) directly on `cookie`.
|
|
4
|
+
*/
|
|
5
|
+
export interface DbAuthCookieAttributes {
|
|
6
|
+
Path?: string;
|
|
7
|
+
HttpOnly?: boolean;
|
|
8
|
+
Secure?: boolean;
|
|
9
|
+
SameSite?: string;
|
|
10
|
+
Domain?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for the cookies dbAuth sets: the session cookie's name, and
|
|
14
|
+
* the attributes applied to every cookie dbAuth writes (the session cookie
|
|
15
|
+
* and the `auth-provider` cookie).
|
|
16
|
+
*/
|
|
17
|
+
export interface DbAuthCookieConfig extends DbAuthCookieAttributes {
|
|
18
|
+
attributes?: DbAuthCookieAttributes;
|
|
19
|
+
/**
|
|
20
|
+
* The name of the cookie that dbAuth sets
|
|
21
|
+
*
|
|
22
|
+
* %port% will be replaced with the port the api server is running on.
|
|
23
|
+
* If you have multiple RW apps running on the same host, you'll need to
|
|
24
|
+
* make sure they all use unique cookie names
|
|
25
|
+
*/
|
|
26
|
+
name?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns a UTC date string `expiresInSeconds` seconds in the future. Used as
|
|
30
|
+
* the `Expires` cookie attribute for a session that should stay valid for
|
|
31
|
+
* that long from now.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createExpiresAtDate(expiresInSeconds: number): string;
|
|
34
|
+
/**
|
|
35
|
+
* Generates a new CSRF token (a standard UUID) to pair with a session.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createCsrfToken(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Removes any fields not explicitly allowed to be sent to the client before
|
|
40
|
+
* sending a user record over the wire.
|
|
41
|
+
*/
|
|
42
|
+
export declare function sanitizeUser(user: Record<string, unknown>, allowedUserFields: string[]): Record<string, unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Builds the Set-Cookie attribute strings (`Path`, `HttpOnly`, `SameSite`,
|
|
45
|
+
* `Secure`, `Domain`, `Expires`) for a dbAuth cookie.
|
|
46
|
+
*
|
|
47
|
+
* Pass `expires: 'now'` (the default) to get the attributes needed to expire
|
|
48
|
+
* the cookie, or a UTC date string (e.g. from `createExpiresAtDate`) to set a
|
|
49
|
+
* future expiration.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildCookieAttributes({ cookieConfig, expires, overrideAttributes, }: {
|
|
52
|
+
cookieConfig?: DbAuthCookieConfig;
|
|
53
|
+
expires?: 'now' | string;
|
|
54
|
+
overrideAttributes?: DbAuthCookieAttributes;
|
|
55
|
+
}): string[];
|
|
56
|
+
/**
|
|
57
|
+
* Builds the Set-Cookie header string for the `auth-provider` cookie dbAuth
|
|
58
|
+
* sets alongside the session cookie.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createAuthProviderCookieString({ cookieConfig, expiresAt, }: {
|
|
61
|
+
cookieConfig?: DbAuthCookieConfig;
|
|
62
|
+
expiresAt: string;
|
|
63
|
+
}): string;
|
|
64
|
+
/**
|
|
65
|
+
* Builds the Set-Cookie header string for the dbAuth session cookie: the
|
|
66
|
+
* `data;csrfToken` payload, encrypted, under the configured cookie name and
|
|
67
|
+
* attributes.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createSessionCookieString<TIdType = unknown>({ data, csrfToken, cookieConfig, expiresAt, }: {
|
|
70
|
+
data: Record<string, TIdType>;
|
|
71
|
+
csrfToken: string;
|
|
72
|
+
cookieConfig?: DbAuthCookieConfig;
|
|
73
|
+
expiresAt: string;
|
|
74
|
+
}): string;
|
|
75
|
+
/** Fields returned from the user record when none are explicitly allowed */
|
|
76
|
+
export declare const DEFAULT_ALLOWED_USER_FIELDS: string[];
|
|
77
|
+
export interface CreateLoginResponseOptions {
|
|
78
|
+
/**
|
|
79
|
+
* Object containing cookie config options: the cookie name (with %port%
|
|
80
|
+
* support) and the attributes applied to it (`Path`, `HttpOnly`,
|
|
81
|
+
* `SameSite`, `Secure`, `Domain`).
|
|
82
|
+
*/
|
|
83
|
+
cookie?: DbAuthCookieConfig;
|
|
84
|
+
/**
|
|
85
|
+
* The fields that are allowed to be returned from the user record.
|
|
86
|
+
* Defaults to `id` and `email`.
|
|
87
|
+
*/
|
|
88
|
+
allowedUserFields?: string[];
|
|
89
|
+
/**
|
|
90
|
+
* The `Expires` cookie attribute value for the session and `auth-provider`
|
|
91
|
+
* cookies: a UTC date string in the future. Build one with
|
|
92
|
+
* `createExpiresAtDate(expiresInSeconds)`.
|
|
93
|
+
*/
|
|
94
|
+
expiresAt: string;
|
|
95
|
+
/**
|
|
96
|
+
* The HTTP status code to return in the response tuple. Defaults to 200.
|
|
97
|
+
*/
|
|
98
|
+
statusCode?: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Mints a dbAuth session for the given user: a CSRF token, a session cookie
|
|
102
|
+
* (the sanitized user data paired with the CSRF token, encrypted), and the
|
|
103
|
+
* `auth-provider` cookie, in the same `[body, headers, { statusCode }]` shape
|
|
104
|
+
* every dbAuth auth method returns.
|
|
105
|
+
*
|
|
106
|
+
* Callable without a `DbAuthHandler` instance, so any code that has already
|
|
107
|
+
* verified a user's identity — a WebAuthn assertion, an OAuth callback, a
|
|
108
|
+
* magic link — can issue a session the same way the built-in login flow
|
|
109
|
+
* does.
|
|
110
|
+
*/
|
|
111
|
+
export declare function createLoginResponse(user: Record<string, unknown>, options: CreateLoginResponseOptions): [Record<string, unknown>, Headers, {
|
|
112
|
+
statusCode: number;
|
|
113
|
+
}];
|
|
114
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,UAAU,CAAC,EAAE,sBAAsB,CAAA;IACnC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAOD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,iBAAiB,EAAE,MAAM,EAAE,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,YAAY,EACZ,OAAe,EACf,kBAAuB,GACxB,EAAE;IACD,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,sBAAsB,CAAA;CAC5C,GAAG,MAAM,EAAE,CAiCX;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,EAC7C,YAAY,EACZ,SAAS,GACV,EAAE;IACD,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAKT;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAG,OAAO,EAAE,EAC3D,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAQT;AAED,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,UAAkB,CAAA;AAE1D,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,0BAA0B,GAClC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B5D"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from "uuid";
|
|
2
|
+
import { encryptSession, generateCookieName } from "./shared.js";
|
|
3
|
+
const PAST_EXPIRES_DATE = (/* @__PURE__ */ new Date(
|
|
4
|
+
"1970-01-01T00:00:00.000+00:00"
|
|
5
|
+
)).toUTCString();
|
|
6
|
+
function createExpiresAtDate(expiresInSeconds) {
|
|
7
|
+
const expiresAt = /* @__PURE__ */ new Date();
|
|
8
|
+
expiresAt.setSeconds(expiresAt.getSeconds() + expiresInSeconds);
|
|
9
|
+
return expiresAt.toUTCString();
|
|
10
|
+
}
|
|
11
|
+
function createCsrfToken() {
|
|
12
|
+
return uuidv4();
|
|
13
|
+
}
|
|
14
|
+
function sanitizeUser(user, allowedUserFields) {
|
|
15
|
+
const sanitized = JSON.parse(JSON.stringify(user));
|
|
16
|
+
Object.keys(sanitized).forEach((key) => {
|
|
17
|
+
if (!allowedUserFields.includes(key)) {
|
|
18
|
+
delete sanitized[key];
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return sanitized;
|
|
22
|
+
}
|
|
23
|
+
function buildCookieAttributes({
|
|
24
|
+
cookieConfig,
|
|
25
|
+
expires = "now",
|
|
26
|
+
overrideAttributes = {}
|
|
27
|
+
}) {
|
|
28
|
+
const userCookieAttributes = cookieConfig?.attributes ? { ...cookieConfig.attributes } : { ...cookieConfig };
|
|
29
|
+
if (!cookieConfig?.attributes) {
|
|
30
|
+
delete userCookieAttributes.name;
|
|
31
|
+
}
|
|
32
|
+
const cookieOptions = { ...userCookieAttributes, ...overrideAttributes };
|
|
33
|
+
const meta = Object.keys(cookieOptions).map((key) => {
|
|
34
|
+
const optionValue = cookieOptions[key];
|
|
35
|
+
if (optionValue === true) {
|
|
36
|
+
return key;
|
|
37
|
+
} else if (optionValue === false) {
|
|
38
|
+
return null;
|
|
39
|
+
} else {
|
|
40
|
+
return `${key}=${optionValue}`;
|
|
41
|
+
}
|
|
42
|
+
}).filter((v) => v !== null);
|
|
43
|
+
const expiresAt = expires === "now" ? PAST_EXPIRES_DATE : expires;
|
|
44
|
+
meta.push(`Expires=${expiresAt}`);
|
|
45
|
+
return meta;
|
|
46
|
+
}
|
|
47
|
+
function createAuthProviderCookieString({
|
|
48
|
+
cookieConfig,
|
|
49
|
+
expiresAt
|
|
50
|
+
}) {
|
|
51
|
+
return [
|
|
52
|
+
`auth-provider=dbAuth`,
|
|
53
|
+
...buildCookieAttributes({ cookieConfig, expires: expiresAt })
|
|
54
|
+
].join(";");
|
|
55
|
+
}
|
|
56
|
+
function createSessionCookieString({
|
|
57
|
+
data,
|
|
58
|
+
csrfToken,
|
|
59
|
+
cookieConfig,
|
|
60
|
+
expiresAt
|
|
61
|
+
}) {
|
|
62
|
+
const session = JSON.stringify(data) + ";" + csrfToken;
|
|
63
|
+
const encrypted = encryptSession(session);
|
|
64
|
+
return [
|
|
65
|
+
`${generateCookieName(cookieConfig?.name)}=${encrypted}`,
|
|
66
|
+
...buildCookieAttributes({ cookieConfig, expires: expiresAt })
|
|
67
|
+
].join(";");
|
|
68
|
+
}
|
|
69
|
+
const DEFAULT_ALLOWED_USER_FIELDS = ["id", "email"];
|
|
70
|
+
function createLoginResponse(user, options) {
|
|
71
|
+
const allowedUserFields = options.allowedUserFields ?? DEFAULT_ALLOWED_USER_FIELDS;
|
|
72
|
+
const sessionData = sanitizeUser(user, allowedUserFields);
|
|
73
|
+
const csrfToken = createCsrfToken();
|
|
74
|
+
const headers = new Headers();
|
|
75
|
+
headers.append("csrf-token", csrfToken);
|
|
76
|
+
headers.append(
|
|
77
|
+
"set-cookie",
|
|
78
|
+
createAuthProviderCookieString({
|
|
79
|
+
cookieConfig: options.cookie,
|
|
80
|
+
expiresAt: options.expiresAt
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
headers.append(
|
|
84
|
+
"set-cookie",
|
|
85
|
+
createSessionCookieString({
|
|
86
|
+
data: sessionData,
|
|
87
|
+
csrfToken,
|
|
88
|
+
cookieConfig: options.cookie,
|
|
89
|
+
expiresAt: options.expiresAt
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
return [sessionData, headers, { statusCode: options.statusCode ?? 200 }];
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
DEFAULT_ALLOWED_USER_FIELDS,
|
|
96
|
+
buildCookieAttributes,
|
|
97
|
+
createAuthProviderCookieString,
|
|
98
|
+
createCsrfToken,
|
|
99
|
+
createExpiresAtDate,
|
|
100
|
+
createLoginResponse,
|
|
101
|
+
createSessionCookieString,
|
|
102
|
+
sanitizeUser
|
|
103
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/auth-dbauth-api",
|
|
3
|
-
"version": "7.0.0-canary.
|
|
3
|
+
"version": "7.0.0-canary.3075",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/cedarjs/cedar.git",
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"test:watch": "vitest watch"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@cedarjs/project-config": "7.0.0-canary.
|
|
60
|
+
"@cedarjs/project-config": "7.0.0-canary.3075",
|
|
61
61
|
"md5": "2.3.0",
|
|
62
62
|
"uuid": "11.1.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@cedarjs/api": "7.0.0-canary.
|
|
66
|
-
"@cedarjs/framework-tools": "7.0.0-canary.
|
|
65
|
+
"@cedarjs/api": "7.0.0-canary.3075",
|
|
66
|
+
"@cedarjs/framework-tools": "7.0.0-canary.3075",
|
|
67
67
|
"@simplewebauthn/server": "13.3.3",
|
|
68
68
|
"@types/aws-lambda": "8.10.162",
|
|
69
69
|
"@types/md5": "2.3.6",
|