auth-vir 2.4.2 → 2.5.0
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.
|
@@ -58,6 +58,13 @@ export type BackendAuthClientConfig<DatabaseUser extends AnyObject, UserId exten
|
|
|
58
58
|
*/
|
|
59
59
|
isDev: boolean;
|
|
60
60
|
} & PartialWithUndefined<{
|
|
61
|
+
/**
|
|
62
|
+
* Optionally generate a service origin from request headers. The generated origin is used
|
|
63
|
+
* for set-cookie headers.
|
|
64
|
+
*/
|
|
65
|
+
generateServiceOrigin(params: {
|
|
66
|
+
requestHeaders: Readonly<IncomingHttpHeaders>;
|
|
67
|
+
}): MaybePromise<undefined | string>;
|
|
61
68
|
/**
|
|
62
69
|
* Set this to allow specific users (determined by `canAssumeUser`) to assume the identity
|
|
63
70
|
* of other users. This should only be used for admins so that they can troubleshoot user
|
|
@@ -119,7 +126,7 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
119
126
|
protected cachedParsedJwtKeys: Record<string, Readonly<JwtKeys>>;
|
|
120
127
|
constructor(config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams, CsrfHeaderName>);
|
|
121
128
|
/** Get all the parameters used for cookie generation. */
|
|
122
|
-
protected getCookieParams({ isSignUpCookie,
|
|
129
|
+
protected getCookieParams({ isSignUpCookie, requestHeaders, }: {
|
|
123
130
|
/**
|
|
124
131
|
* Set this to `true` when we are setting the initial cookie right after a user signs up.
|
|
125
132
|
* This allows them to auto-authorize when they verify their email address.
|
|
@@ -127,8 +134,7 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
127
134
|
* This should only be set to `true` when a new user is signing up.
|
|
128
135
|
*/
|
|
129
136
|
isSignUpCookie: boolean;
|
|
130
|
-
|
|
131
|
-
serviceOrigin?: string | undefined;
|
|
137
|
+
requestHeaders: Readonly<IncomingHttpHeaders> | undefined;
|
|
132
138
|
}): Promise<Readonly<CookieParams>>;
|
|
133
139
|
/** Calls the provided `getUserFromDatabase` config. */
|
|
134
140
|
protected getDatabaseUser({ isSignUpCookie, userId, assumingUser, }: {
|
|
@@ -137,10 +143,9 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
137
143
|
isSignUpCookie: boolean;
|
|
138
144
|
}): Promise<undefined | DatabaseUser>;
|
|
139
145
|
/** Creates a `'cookie-set'` header to refresh the user's session cookie. */
|
|
140
|
-
protected createCookieRefreshHeaders({ userIdResult,
|
|
146
|
+
protected createCookieRefreshHeaders({ userIdResult, requestHeaders, }: {
|
|
141
147
|
userIdResult: Readonly<UserIdResult<UserId>>;
|
|
142
|
-
|
|
143
|
-
serviceOrigin?: string | undefined;
|
|
148
|
+
requestHeaders: IncomingHttpHeaders;
|
|
144
149
|
}): Promise<OutgoingHttpHeaders | undefined>;
|
|
145
150
|
/** Reads the user's assumed user headers and, if configured, gets the assumed user. */
|
|
146
151
|
protected getAssumedUser({ headers, user, }: {
|
|
@@ -148,7 +153,7 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
148
153
|
headers: IncomingHttpHeaders;
|
|
149
154
|
}): Promise<DatabaseUser | undefined>;
|
|
150
155
|
/** Securely extract a user from their request headers. */
|
|
151
|
-
getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh,
|
|
156
|
+
getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }: {
|
|
152
157
|
requestHeaders: IncomingHttpHeaders;
|
|
153
158
|
isSignUpCookie: boolean;
|
|
154
159
|
/**
|
|
@@ -157,8 +162,6 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
157
162
|
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
158
163
|
*/
|
|
159
164
|
allowUserAuthRefresh: boolean;
|
|
160
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
161
|
-
serviceOrigin?: string | undefined;
|
|
162
165
|
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
163
166
|
/**
|
|
164
167
|
* Get all the JWT params used when creating the auth cookie, in case you need them for
|
|
@@ -176,12 +179,10 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
176
179
|
'set-cookie': string[];
|
|
177
180
|
}>;
|
|
178
181
|
/** Use these headers to log a user in. */
|
|
179
|
-
createLoginHeaders({ userId, requestHeaders, isSignUpCookie,
|
|
182
|
+
createLoginHeaders({ userId, requestHeaders, isSignUpCookie, }: {
|
|
180
183
|
userId: UserId;
|
|
181
184
|
requestHeaders: IncomingHttpHeaders;
|
|
182
185
|
isSignUpCookie: boolean;
|
|
183
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
184
|
-
serviceOrigin?: string | undefined;
|
|
185
186
|
}): Promise<OutgoingHttpHeaders>;
|
|
186
187
|
/** Combines `.getInsecureUser()` and `.getSecureUser()` into one method. */
|
|
187
188
|
getInsecureOrSecureUser(params: {
|
|
@@ -210,7 +211,7 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
210
211
|
* where JavaScript cannot be used to attach the CSRF token header to the request (like when
|
|
211
212
|
* opening a PDF file). Use `.getSecureUser()` instead, whenever possible.
|
|
212
213
|
*/
|
|
213
|
-
getInsecureUser({ requestHeaders, allowUserAuthRefresh,
|
|
214
|
+
getInsecureUser({ requestHeaders, allowUserAuthRefresh, }: {
|
|
214
215
|
requestHeaders: IncomingHttpHeaders;
|
|
215
216
|
/**
|
|
216
217
|
* If true, this method will generate headers to refresh the user's auth session. This
|
|
@@ -218,7 +219,5 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
218
219
|
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
219
220
|
*/
|
|
220
221
|
allowUserAuthRefresh: boolean;
|
|
221
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
222
|
-
serviceOrigin?: string | undefined;
|
|
223
222
|
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
224
223
|
}
|
|
@@ -24,7 +24,10 @@ export class BackendAuthClient {
|
|
|
24
24
|
this.config = config;
|
|
25
25
|
}
|
|
26
26
|
/** Get all the parameters used for cookie generation. */
|
|
27
|
-
async getCookieParams({ isSignUpCookie,
|
|
27
|
+
async getCookieParams({ isSignUpCookie, requestHeaders, }) {
|
|
28
|
+
const serviceOrigin = requestHeaders
|
|
29
|
+
? await this.config.generateServiceOrigin?.({ requestHeaders })
|
|
30
|
+
: undefined;
|
|
28
31
|
return {
|
|
29
32
|
cookieDuration: this.config.userSessionIdleTimeout || defaultSessionIdleTimeout,
|
|
30
33
|
hostOrigin: serviceOrigin || this.config.serviceOrigin,
|
|
@@ -49,7 +52,7 @@ export class BackendAuthClient {
|
|
|
49
52
|
return authenticatedUser;
|
|
50
53
|
}
|
|
51
54
|
/** Creates a `'cookie-set'` header to refresh the user's session cookie. */
|
|
52
|
-
async createCookieRefreshHeaders({ userIdResult,
|
|
55
|
+
async createCookieRefreshHeaders({ userIdResult, requestHeaders, }) {
|
|
53
56
|
const now = getNowInUtcTimezone();
|
|
54
57
|
/** Double check that the JWT hasn't already expired. */
|
|
55
58
|
const isExpiredAlready = isDateAfter({
|
|
@@ -80,10 +83,9 @@ export class BackendAuthClient {
|
|
|
80
83
|
});
|
|
81
84
|
if (isRefreshReady) {
|
|
82
85
|
return this.createLoginHeaders({
|
|
83
|
-
requestHeaders
|
|
86
|
+
requestHeaders,
|
|
84
87
|
userId: userIdResult.userId,
|
|
85
88
|
isSignUpCookie: userIdResult.cookieName === AuthCookieName.SignUp,
|
|
86
|
-
serviceOrigin,
|
|
87
89
|
});
|
|
88
90
|
}
|
|
89
91
|
else {
|
|
@@ -111,7 +113,7 @@ export class BackendAuthClient {
|
|
|
111
113
|
return assumedUser;
|
|
112
114
|
}
|
|
113
115
|
/** Securely extract a user from their request headers. */
|
|
114
|
-
async getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh,
|
|
116
|
+
async getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }) {
|
|
115
117
|
const userIdResult = await extractUserIdFromRequestHeaders(requestHeaders, await this.getJwtParams(), isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth, this.config.overrides);
|
|
116
118
|
if (!userIdResult) {
|
|
117
119
|
return undefined;
|
|
@@ -130,7 +132,7 @@ export class BackendAuthClient {
|
|
|
130
132
|
});
|
|
131
133
|
const cookieRefreshHeaders = (await this.createCookieRefreshHeaders({
|
|
132
134
|
userIdResult,
|
|
133
|
-
|
|
135
|
+
requestHeaders,
|
|
134
136
|
})) || {};
|
|
135
137
|
return {
|
|
136
138
|
user: assumedUser || user,
|
|
@@ -162,13 +164,13 @@ export class BackendAuthClient {
|
|
|
162
164
|
const signUpCookieHeaders = params.allCookies || params.isSignUpCookie
|
|
163
165
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
164
166
|
isSignUpCookie: true,
|
|
165
|
-
|
|
167
|
+
requestHeaders: undefined,
|
|
166
168
|
}), this.config.overrides)
|
|
167
169
|
: undefined;
|
|
168
170
|
const authCookieHeaders = params.allCookies || !params.isSignUpCookie
|
|
169
171
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
170
172
|
isSignUpCookie: false,
|
|
171
|
-
|
|
173
|
+
requestHeaders: undefined,
|
|
172
174
|
}), this.config.overrides)
|
|
173
175
|
: undefined;
|
|
174
176
|
const setCookieHeader = {
|
|
@@ -184,18 +186,18 @@ export class BackendAuthClient {
|
|
|
184
186
|
};
|
|
185
187
|
}
|
|
186
188
|
/** Use these headers to log a user in. */
|
|
187
|
-
async createLoginHeaders({ userId, requestHeaders, isSignUpCookie,
|
|
189
|
+
async createLoginHeaders({ userId, requestHeaders, isSignUpCookie, }) {
|
|
188
190
|
const oppositeCookieName = isSignUpCookie ? AuthCookieName.Auth : AuthCookieName.SignUp;
|
|
189
191
|
const hasExistingOppositeCookie = requestHeaders.cookie?.includes(`${oppositeCookieName}=`);
|
|
190
192
|
const discardOppositeCookieHeaders = hasExistingOppositeCookie
|
|
191
193
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
192
194
|
isSignUpCookie: !isSignUpCookie,
|
|
193
|
-
|
|
195
|
+
requestHeaders,
|
|
194
196
|
}), this.config.overrides)
|
|
195
197
|
: undefined;
|
|
196
198
|
const newCookieHeaders = await generateSuccessfulLoginHeaders(userId, await this.getCookieParams({
|
|
197
199
|
isSignUpCookie,
|
|
198
|
-
|
|
200
|
+
requestHeaders,
|
|
199
201
|
}), this.config.overrides);
|
|
200
202
|
return {
|
|
201
203
|
...newCookieHeaders,
|
|
@@ -222,7 +224,7 @@ export class BackendAuthClient {
|
|
|
222
224
|
* where JavaScript cannot be used to attach the CSRF token header to the request (like when
|
|
223
225
|
* opening a PDF file). Use `.getSecureUser()` instead, whenever possible.
|
|
224
226
|
*/
|
|
225
|
-
async getInsecureUser({ requestHeaders, allowUserAuthRefresh,
|
|
227
|
+
async getInsecureUser({ requestHeaders, allowUserAuthRefresh, }) {
|
|
226
228
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
227
229
|
const userIdResult = await insecureExtractUserIdFromCookieAlone(requestHeaders, await this.getJwtParams(), AuthCookieName.Auth);
|
|
228
230
|
if (!userIdResult) {
|
|
@@ -239,7 +241,7 @@ export class BackendAuthClient {
|
|
|
239
241
|
const refreshHeaders = allowUserAuthRefresh &&
|
|
240
242
|
(await this.createCookieRefreshHeaders({
|
|
241
243
|
userIdResult,
|
|
242
|
-
|
|
244
|
+
requestHeaders,
|
|
243
245
|
}));
|
|
244
246
|
return {
|
|
245
247
|
user,
|
package/package.json
CHANGED
|
@@ -78,6 +78,13 @@ export type BackendAuthClientConfig<
|
|
|
78
78
|
*/
|
|
79
79
|
isDev: boolean;
|
|
80
80
|
} & PartialWithUndefined<{
|
|
81
|
+
/**
|
|
82
|
+
* Optionally generate a service origin from request headers. The generated origin is used
|
|
83
|
+
* for set-cookie headers.
|
|
84
|
+
*/
|
|
85
|
+
generateServiceOrigin(params: {
|
|
86
|
+
requestHeaders: Readonly<IncomingHttpHeaders>;
|
|
87
|
+
}): MaybePromise<undefined | string>;
|
|
81
88
|
/**
|
|
82
89
|
* Set this to allow specific users (determined by `canAssumeUser`) to assume the identity
|
|
83
90
|
* of other users. This should only be used for admins so that they can troubleshoot user
|
|
@@ -168,7 +175,7 @@ export class BackendAuthClient<
|
|
|
168
175
|
/** Get all the parameters used for cookie generation. */
|
|
169
176
|
protected async getCookieParams({
|
|
170
177
|
isSignUpCookie,
|
|
171
|
-
|
|
178
|
+
requestHeaders,
|
|
172
179
|
}: {
|
|
173
180
|
/**
|
|
174
181
|
* Set this to `true` when we are setting the initial cookie right after a user signs up.
|
|
@@ -177,9 +184,12 @@ export class BackendAuthClient<
|
|
|
177
184
|
* This should only be set to `true` when a new user is signing up.
|
|
178
185
|
*/
|
|
179
186
|
isSignUpCookie: boolean;
|
|
180
|
-
|
|
181
|
-
serviceOrigin?: string | undefined;
|
|
187
|
+
requestHeaders: Readonly<IncomingHttpHeaders> | undefined;
|
|
182
188
|
}): Promise<Readonly<CookieParams>> {
|
|
189
|
+
const serviceOrigin = requestHeaders
|
|
190
|
+
? await this.config.generateServiceOrigin?.({requestHeaders})
|
|
191
|
+
: undefined;
|
|
192
|
+
|
|
183
193
|
return {
|
|
184
194
|
cookieDuration: this.config.userSessionIdleTimeout || defaultSessionIdleTimeout,
|
|
185
195
|
hostOrigin: serviceOrigin || this.config.serviceOrigin,
|
|
@@ -219,11 +229,10 @@ export class BackendAuthClient<
|
|
|
219
229
|
/** Creates a `'cookie-set'` header to refresh the user's session cookie. */
|
|
220
230
|
protected async createCookieRefreshHeaders({
|
|
221
231
|
userIdResult,
|
|
222
|
-
|
|
232
|
+
requestHeaders,
|
|
223
233
|
}: {
|
|
224
234
|
userIdResult: Readonly<UserIdResult<UserId>>;
|
|
225
|
-
|
|
226
|
-
serviceOrigin?: string | undefined;
|
|
235
|
+
requestHeaders: IncomingHttpHeaders;
|
|
227
236
|
}): Promise<OutgoingHttpHeaders | undefined> {
|
|
228
237
|
const now = getNowInUtcTimezone();
|
|
229
238
|
|
|
@@ -262,10 +271,9 @@ export class BackendAuthClient<
|
|
|
262
271
|
|
|
263
272
|
if (isRefreshReady) {
|
|
264
273
|
return this.createLoginHeaders({
|
|
265
|
-
requestHeaders
|
|
274
|
+
requestHeaders,
|
|
266
275
|
userId: userIdResult.userId,
|
|
267
276
|
isSignUpCookie: userIdResult.cookieName === AuthCookieName.SignUp,
|
|
268
|
-
serviceOrigin,
|
|
269
277
|
});
|
|
270
278
|
} else {
|
|
271
279
|
return undefined;
|
|
@@ -313,7 +321,6 @@ export class BackendAuthClient<
|
|
|
313
321
|
requestHeaders,
|
|
314
322
|
isSignUpCookie,
|
|
315
323
|
allowUserAuthRefresh,
|
|
316
|
-
serviceOrigin,
|
|
317
324
|
}: {
|
|
318
325
|
requestHeaders: IncomingHttpHeaders;
|
|
319
326
|
isSignUpCookie: boolean;
|
|
@@ -323,8 +330,6 @@ export class BackendAuthClient<
|
|
|
323
330
|
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
324
331
|
*/
|
|
325
332
|
allowUserAuthRefresh: boolean;
|
|
326
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
327
|
-
serviceOrigin?: string | undefined;
|
|
328
333
|
}): Promise<GetUserResult<DatabaseUser> | undefined> {
|
|
329
334
|
const userIdResult = await extractUserIdFromRequestHeaders<UserId>(
|
|
330
335
|
requestHeaders,
|
|
@@ -354,7 +359,7 @@ export class BackendAuthClient<
|
|
|
354
359
|
const cookieRefreshHeaders =
|
|
355
360
|
(await this.createCookieRefreshHeaders({
|
|
356
361
|
userIdResult,
|
|
357
|
-
|
|
362
|
+
requestHeaders,
|
|
358
363
|
})) || {};
|
|
359
364
|
|
|
360
365
|
return {
|
|
@@ -408,7 +413,7 @@ export class BackendAuthClient<
|
|
|
408
413
|
? (generateLogoutHeaders(
|
|
409
414
|
await this.getCookieParams({
|
|
410
415
|
isSignUpCookie: true,
|
|
411
|
-
|
|
416
|
+
requestHeaders: undefined,
|
|
412
417
|
}),
|
|
413
418
|
this.config.overrides,
|
|
414
419
|
) satisfies Record<CsrfHeaderName, string>)
|
|
@@ -418,7 +423,7 @@ export class BackendAuthClient<
|
|
|
418
423
|
? (generateLogoutHeaders(
|
|
419
424
|
await this.getCookieParams({
|
|
420
425
|
isSignUpCookie: false,
|
|
421
|
-
|
|
426
|
+
requestHeaders: undefined,
|
|
422
427
|
}),
|
|
423
428
|
this.config.overrides,
|
|
424
429
|
) satisfies Record<CsrfHeaderName, string>)
|
|
@@ -448,13 +453,10 @@ export class BackendAuthClient<
|
|
|
448
453
|
userId,
|
|
449
454
|
requestHeaders,
|
|
450
455
|
isSignUpCookie,
|
|
451
|
-
serviceOrigin,
|
|
452
456
|
}: {
|
|
453
457
|
userId: UserId;
|
|
454
458
|
requestHeaders: IncomingHttpHeaders;
|
|
455
459
|
isSignUpCookie: boolean;
|
|
456
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
457
|
-
serviceOrigin?: string | undefined;
|
|
458
460
|
}): Promise<OutgoingHttpHeaders> {
|
|
459
461
|
const oppositeCookieName = isSignUpCookie ? AuthCookieName.Auth : AuthCookieName.SignUp;
|
|
460
462
|
const hasExistingOppositeCookie = requestHeaders.cookie?.includes(`${oppositeCookieName}=`);
|
|
@@ -463,7 +465,7 @@ export class BackendAuthClient<
|
|
|
463
465
|
? generateLogoutHeaders(
|
|
464
466
|
await this.getCookieParams({
|
|
465
467
|
isSignUpCookie: !isSignUpCookie,
|
|
466
|
-
|
|
468
|
+
requestHeaders,
|
|
467
469
|
}),
|
|
468
470
|
this.config.overrides,
|
|
469
471
|
)
|
|
@@ -473,7 +475,7 @@ export class BackendAuthClient<
|
|
|
473
475
|
userId,
|
|
474
476
|
await this.getCookieParams({
|
|
475
477
|
isSignUpCookie,
|
|
476
|
-
|
|
478
|
+
requestHeaders,
|
|
477
479
|
}),
|
|
478
480
|
this.config.overrides,
|
|
479
481
|
);
|
|
@@ -536,7 +538,6 @@ export class BackendAuthClient<
|
|
|
536
538
|
public async getInsecureUser({
|
|
537
539
|
requestHeaders,
|
|
538
540
|
allowUserAuthRefresh,
|
|
539
|
-
serviceOrigin,
|
|
540
541
|
}: {
|
|
541
542
|
requestHeaders: IncomingHttpHeaders;
|
|
542
543
|
/**
|
|
@@ -545,8 +546,6 @@ export class BackendAuthClient<
|
|
|
545
546
|
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
546
547
|
*/
|
|
547
548
|
allowUserAuthRefresh: boolean;
|
|
548
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
549
|
-
serviceOrigin?: string | undefined;
|
|
550
549
|
}): Promise<GetUserResult<DatabaseUser> | undefined> {
|
|
551
550
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
552
551
|
const userIdResult = await insecureExtractUserIdFromCookieAlone<UserId>(
|
|
@@ -573,7 +572,7 @@ export class BackendAuthClient<
|
|
|
573
572
|
allowUserAuthRefresh &&
|
|
574
573
|
(await this.createCookieRefreshHeaders({
|
|
575
574
|
userIdResult,
|
|
576
|
-
|
|
575
|
+
requestHeaders,
|
|
577
576
|
}));
|
|
578
577
|
|
|
579
578
|
return {
|