auth-vir 2.3.8 → 2.4.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.
|
@@ -119,14 +119,16 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
119
119
|
protected cachedParsedJwtKeys: Record<string, Readonly<JwtKeys>>;
|
|
120
120
|
constructor(config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams, CsrfHeaderName>);
|
|
121
121
|
/** Get all the parameters used for cookie generation. */
|
|
122
|
-
protected getCookieParams({ isSignUpCookie, }: {
|
|
122
|
+
protected getCookieParams({ isSignUpCookie, serviceOrigin, }: {
|
|
123
123
|
/**
|
|
124
124
|
* Set this to `true` when we are setting the initial cookie right after a user signs up.
|
|
125
125
|
* This allows them to auto-authorize when they verify their email address.
|
|
126
126
|
*
|
|
127
127
|
* This should only be set to `true` when a new user is signing up.
|
|
128
128
|
*/
|
|
129
|
-
isSignUpCookie
|
|
129
|
+
isSignUpCookie: boolean;
|
|
130
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
131
|
+
serviceOrigin: string | undefined;
|
|
130
132
|
}): Promise<Readonly<CookieParams>>;
|
|
131
133
|
/** Calls the provided `getUserFromDatabase` config. */
|
|
132
134
|
protected getDatabaseUser({ isSignUpCookie, userId, assumingUser, }: {
|
|
@@ -144,9 +146,15 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
144
146
|
headers: IncomingHttpHeaders;
|
|
145
147
|
}): Promise<DatabaseUser | undefined>;
|
|
146
148
|
/** Securely extract a user from their request headers. */
|
|
147
|
-
getSecureUser({ requestHeaders, isSignUpCookie, }: {
|
|
149
|
+
getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }: {
|
|
148
150
|
requestHeaders: IncomingHttpHeaders;
|
|
149
|
-
isSignUpCookie
|
|
151
|
+
isSignUpCookie: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
154
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
155
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
156
|
+
*/
|
|
157
|
+
allowUserAuthRefresh: boolean;
|
|
150
158
|
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
151
159
|
/**
|
|
152
160
|
* Get all the JWT params used when creating the auth cookie, in case you need them for
|
|
@@ -157,19 +165,29 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
157
165
|
createLogoutHeaders(params: RequireExactlyOne<{
|
|
158
166
|
allCookies: true;
|
|
159
167
|
isSignUpCookie: boolean;
|
|
168
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
169
|
+
serviceOrigin?: string | undefined;
|
|
160
170
|
}>): Promise<Partial<Record<CsrfHeaderName, string>> & {
|
|
161
171
|
'set-cookie': string[];
|
|
162
172
|
}>;
|
|
163
173
|
/** Use these headers to log a user in. */
|
|
164
|
-
createLoginHeaders({ userId, requestHeaders, isSignUpCookie, }: {
|
|
174
|
+
createLoginHeaders({ userId, requestHeaders, isSignUpCookie, serviceOrigin, }: {
|
|
165
175
|
userId: UserId;
|
|
166
176
|
requestHeaders: IncomingHttpHeaders;
|
|
167
177
|
isSignUpCookie: boolean;
|
|
178
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
179
|
+
serviceOrigin?: string | undefined;
|
|
168
180
|
}): Promise<OutgoingHttpHeaders>;
|
|
169
181
|
/** Combines `.getInsecureUser()` and `.getSecureUser()` into one method. */
|
|
170
182
|
getInsecureOrSecureUser(params: {
|
|
171
183
|
requestHeaders: IncomingHttpHeaders;
|
|
172
|
-
isSignUpCookie
|
|
184
|
+
isSignUpCookie: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
187
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
188
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
189
|
+
*/
|
|
190
|
+
allowUserAuthRefresh: boolean;
|
|
173
191
|
}): Promise<RequireOneOrNone<{
|
|
174
192
|
secureUser: GetUserResult<DatabaseUser>;
|
|
175
193
|
/**
|
|
@@ -185,7 +203,13 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
|
|
|
185
203
|
* where JavaScript cannot be used to attach the CSRF token header to the request (like when
|
|
186
204
|
* opening a PDF file). Use `.getSecureUser()` instead, whenever possible.
|
|
187
205
|
*/
|
|
188
|
-
getInsecureUser({ requestHeaders, }: {
|
|
206
|
+
getInsecureUser({ requestHeaders, allowUserAuthRefresh, }: {
|
|
189
207
|
requestHeaders: IncomingHttpHeaders;
|
|
208
|
+
/**
|
|
209
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
210
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
211
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
212
|
+
*/
|
|
213
|
+
allowUserAuthRefresh: boolean;
|
|
190
214
|
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
191
215
|
}
|
|
@@ -24,10 +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, serviceOrigin, }) {
|
|
28
28
|
return {
|
|
29
29
|
cookieDuration: this.config.userSessionIdleTimeout || defaultSessionIdleTimeout,
|
|
30
|
-
hostOrigin: this.config.serviceOrigin,
|
|
30
|
+
hostOrigin: serviceOrigin || this.config.serviceOrigin,
|
|
31
31
|
jwtParams: await this.getJwtParams(),
|
|
32
32
|
isDev: this.config.isDev,
|
|
33
33
|
cookieName: isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth,
|
|
@@ -110,7 +110,7 @@ export class BackendAuthClient {
|
|
|
110
110
|
return assumedUser;
|
|
111
111
|
}
|
|
112
112
|
/** Securely extract a user from their request headers. */
|
|
113
|
-
async getSecureUser({ requestHeaders, isSignUpCookie, }) {
|
|
113
|
+
async getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }) {
|
|
114
114
|
const userIdResult = await extractUserIdFromRequestHeaders(requestHeaders, await this.getJwtParams(), isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth, this.config.overrides);
|
|
115
115
|
if (!userIdResult) {
|
|
116
116
|
return undefined;
|
|
@@ -118,7 +118,7 @@ export class BackendAuthClient {
|
|
|
118
118
|
const user = await this.getDatabaseUser({
|
|
119
119
|
userId: userIdResult.userId,
|
|
120
120
|
assumingUser: undefined,
|
|
121
|
-
isSignUpCookie
|
|
121
|
+
isSignUpCookie,
|
|
122
122
|
});
|
|
123
123
|
if (!user) {
|
|
124
124
|
return undefined;
|
|
@@ -133,7 +133,7 @@ export class BackendAuthClient {
|
|
|
133
133
|
return {
|
|
134
134
|
user: assumedUser || user,
|
|
135
135
|
isAssumed: !!assumedUser,
|
|
136
|
-
responseHeaders: cookieRefreshHeaders,
|
|
136
|
+
responseHeaders: allowUserAuthRefresh ? cookieRefreshHeaders : {},
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
@@ -160,11 +160,13 @@ export class BackendAuthClient {
|
|
|
160
160
|
const signUpCookieHeaders = params.allCookies || params.isSignUpCookie
|
|
161
161
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
162
162
|
isSignUpCookie: true,
|
|
163
|
+
serviceOrigin: params.serviceOrigin,
|
|
163
164
|
}), this.config.overrides)
|
|
164
165
|
: undefined;
|
|
165
166
|
const authCookieHeaders = params.allCookies || !params.isSignUpCookie
|
|
166
167
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
167
168
|
isSignUpCookie: false,
|
|
169
|
+
serviceOrigin: params.serviceOrigin,
|
|
168
170
|
}), this.config.overrides)
|
|
169
171
|
: undefined;
|
|
170
172
|
const setCookieHeader = {
|
|
@@ -180,16 +182,18 @@ export class BackendAuthClient {
|
|
|
180
182
|
};
|
|
181
183
|
}
|
|
182
184
|
/** Use these headers to log a user in. */
|
|
183
|
-
async createLoginHeaders({ userId, requestHeaders, isSignUpCookie, }) {
|
|
185
|
+
async createLoginHeaders({ userId, requestHeaders, isSignUpCookie, serviceOrigin, }) {
|
|
184
186
|
const oppositeCookieName = isSignUpCookie ? AuthCookieName.Auth : AuthCookieName.SignUp;
|
|
185
187
|
const hasExistingOppositeCookie = requestHeaders.cookie?.includes(`${oppositeCookieName}=`);
|
|
186
188
|
const discardOppositeCookieHeaders = hasExistingOppositeCookie
|
|
187
189
|
? generateLogoutHeaders(await this.getCookieParams({
|
|
188
190
|
isSignUpCookie: !isSignUpCookie,
|
|
191
|
+
serviceOrigin,
|
|
189
192
|
}), this.config.overrides)
|
|
190
193
|
: undefined;
|
|
191
194
|
const newCookieHeaders = await generateSuccessfulLoginHeaders(userId, await this.getCookieParams({
|
|
192
195
|
isSignUpCookie,
|
|
196
|
+
serviceOrigin,
|
|
193
197
|
}), this.config.overrides);
|
|
194
198
|
return {
|
|
195
199
|
...newCookieHeaders,
|
|
@@ -216,7 +220,7 @@ export class BackendAuthClient {
|
|
|
216
220
|
* where JavaScript cannot be used to attach the CSRF token header to the request (like when
|
|
217
221
|
* opening a PDF file). Use `.getSecureUser()` instead, whenever possible.
|
|
218
222
|
*/
|
|
219
|
-
async getInsecureUser({ requestHeaders, }) {
|
|
223
|
+
async getInsecureUser({ requestHeaders, allowUserAuthRefresh, }) {
|
|
220
224
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
221
225
|
const userIdResult = await insecureExtractUserIdFromCookieAlone(requestHeaders, await this.getJwtParams(), AuthCookieName.Auth);
|
|
222
226
|
if (!userIdResult) {
|
|
@@ -230,12 +234,14 @@ export class BackendAuthClient {
|
|
|
230
234
|
if (!user) {
|
|
231
235
|
return undefined;
|
|
232
236
|
}
|
|
237
|
+
const refreshHeaders = allowUserAuthRefresh &&
|
|
238
|
+
(await this.createCookieRefreshHeaders({
|
|
239
|
+
userIdResult,
|
|
240
|
+
}));
|
|
233
241
|
return {
|
|
234
242
|
user,
|
|
235
243
|
isAssumed: false,
|
|
236
|
-
responseHeaders:
|
|
237
|
-
userIdResult,
|
|
238
|
-
})) || {},
|
|
244
|
+
responseHeaders: refreshHeaders || {},
|
|
239
245
|
};
|
|
240
246
|
}
|
|
241
247
|
}
|
package/package.json
CHANGED
|
@@ -168,6 +168,7 @@ export class BackendAuthClient<
|
|
|
168
168
|
/** Get all the parameters used for cookie generation. */
|
|
169
169
|
protected async getCookieParams({
|
|
170
170
|
isSignUpCookie,
|
|
171
|
+
serviceOrigin,
|
|
171
172
|
}: {
|
|
172
173
|
/**
|
|
173
174
|
* Set this to `true` when we are setting the initial cookie right after a user signs up.
|
|
@@ -175,11 +176,13 @@ export class BackendAuthClient<
|
|
|
175
176
|
*
|
|
176
177
|
* This should only be set to `true` when a new user is signing up.
|
|
177
178
|
*/
|
|
178
|
-
isSignUpCookie
|
|
179
|
+
isSignUpCookie: boolean;
|
|
180
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
181
|
+
serviceOrigin: string | undefined;
|
|
179
182
|
}): Promise<Readonly<CookieParams>> {
|
|
180
183
|
return {
|
|
181
184
|
cookieDuration: this.config.userSessionIdleTimeout || defaultSessionIdleTimeout,
|
|
182
|
-
hostOrigin: this.config.serviceOrigin,
|
|
185
|
+
hostOrigin: serviceOrigin || this.config.serviceOrigin,
|
|
183
186
|
jwtParams: await this.getJwtParams(),
|
|
184
187
|
isDev: this.config.isDev,
|
|
185
188
|
cookieName: isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth,
|
|
@@ -305,9 +308,16 @@ export class BackendAuthClient<
|
|
|
305
308
|
public async getSecureUser({
|
|
306
309
|
requestHeaders,
|
|
307
310
|
isSignUpCookie,
|
|
311
|
+
allowUserAuthRefresh,
|
|
308
312
|
}: {
|
|
309
313
|
requestHeaders: IncomingHttpHeaders;
|
|
310
|
-
isSignUpCookie
|
|
314
|
+
isSignUpCookie: boolean;
|
|
315
|
+
/**
|
|
316
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
317
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
318
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
319
|
+
*/
|
|
320
|
+
allowUserAuthRefresh: boolean;
|
|
311
321
|
}): Promise<GetUserResult<DatabaseUser> | undefined> {
|
|
312
322
|
const userIdResult = await extractUserIdFromRequestHeaders<UserId>(
|
|
313
323
|
requestHeaders,
|
|
@@ -322,7 +332,7 @@ export class BackendAuthClient<
|
|
|
322
332
|
const user = await this.getDatabaseUser({
|
|
323
333
|
userId: userIdResult.userId,
|
|
324
334
|
assumingUser: undefined,
|
|
325
|
-
isSignUpCookie
|
|
335
|
+
isSignUpCookie,
|
|
326
336
|
});
|
|
327
337
|
|
|
328
338
|
if (!user) {
|
|
@@ -342,7 +352,7 @@ export class BackendAuthClient<
|
|
|
342
352
|
return {
|
|
343
353
|
user: assumedUser || user,
|
|
344
354
|
isAssumed: !!assumedUser,
|
|
345
|
-
responseHeaders: cookieRefreshHeaders,
|
|
355
|
+
responseHeaders: allowUserAuthRefresh ? cookieRefreshHeaders : {},
|
|
346
356
|
};
|
|
347
357
|
}
|
|
348
358
|
|
|
@@ -374,6 +384,8 @@ export class BackendAuthClient<
|
|
|
374
384
|
params: RequireExactlyOne<{
|
|
375
385
|
allCookies: true;
|
|
376
386
|
isSignUpCookie: boolean;
|
|
387
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
388
|
+
serviceOrigin?: string | undefined;
|
|
377
389
|
}>,
|
|
378
390
|
): Promise<
|
|
379
391
|
Partial<Record<CsrfHeaderName, string>> & {
|
|
@@ -385,6 +397,7 @@ export class BackendAuthClient<
|
|
|
385
397
|
? (generateLogoutHeaders(
|
|
386
398
|
await this.getCookieParams({
|
|
387
399
|
isSignUpCookie: true,
|
|
400
|
+
serviceOrigin: params.serviceOrigin,
|
|
388
401
|
}),
|
|
389
402
|
this.config.overrides,
|
|
390
403
|
) satisfies Record<CsrfHeaderName, string>)
|
|
@@ -394,6 +407,7 @@ export class BackendAuthClient<
|
|
|
394
407
|
? (generateLogoutHeaders(
|
|
395
408
|
await this.getCookieParams({
|
|
396
409
|
isSignUpCookie: false,
|
|
410
|
+
serviceOrigin: params.serviceOrigin,
|
|
397
411
|
}),
|
|
398
412
|
this.config.overrides,
|
|
399
413
|
) satisfies Record<CsrfHeaderName, string>)
|
|
@@ -423,10 +437,13 @@ export class BackendAuthClient<
|
|
|
423
437
|
userId,
|
|
424
438
|
requestHeaders,
|
|
425
439
|
isSignUpCookie,
|
|
440
|
+
serviceOrigin,
|
|
426
441
|
}: {
|
|
427
442
|
userId: UserId;
|
|
428
443
|
requestHeaders: IncomingHttpHeaders;
|
|
429
444
|
isSignUpCookie: boolean;
|
|
445
|
+
/** Overrides the client's already established `serviceOrigin`. */
|
|
446
|
+
serviceOrigin?: string | undefined;
|
|
430
447
|
}): Promise<OutgoingHttpHeaders> {
|
|
431
448
|
const oppositeCookieName = isSignUpCookie ? AuthCookieName.Auth : AuthCookieName.SignUp;
|
|
432
449
|
const hasExistingOppositeCookie = requestHeaders.cookie?.includes(`${oppositeCookieName}=`);
|
|
@@ -435,6 +452,7 @@ export class BackendAuthClient<
|
|
|
435
452
|
? generateLogoutHeaders(
|
|
436
453
|
await this.getCookieParams({
|
|
437
454
|
isSignUpCookie: !isSignUpCookie,
|
|
455
|
+
serviceOrigin,
|
|
438
456
|
}),
|
|
439
457
|
this.config.overrides,
|
|
440
458
|
)
|
|
@@ -444,6 +462,7 @@ export class BackendAuthClient<
|
|
|
444
462
|
userId,
|
|
445
463
|
await this.getCookieParams({
|
|
446
464
|
isSignUpCookie,
|
|
465
|
+
serviceOrigin,
|
|
447
466
|
}),
|
|
448
467
|
this.config.overrides,
|
|
449
468
|
);
|
|
@@ -465,7 +484,13 @@ export class BackendAuthClient<
|
|
|
465
484
|
/** Combines `.getInsecureUser()` and `.getSecureUser()` into one method. */
|
|
466
485
|
public async getInsecureOrSecureUser(params: {
|
|
467
486
|
requestHeaders: IncomingHttpHeaders;
|
|
468
|
-
isSignUpCookie
|
|
487
|
+
isSignUpCookie: boolean;
|
|
488
|
+
/**
|
|
489
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
490
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
491
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
492
|
+
*/
|
|
493
|
+
allowUserAuthRefresh: boolean;
|
|
469
494
|
}): Promise<
|
|
470
495
|
RequireOneOrNone<{
|
|
471
496
|
secureUser: GetUserResult<DatabaseUser>;
|
|
@@ -497,8 +522,15 @@ export class BackendAuthClient<
|
|
|
497
522
|
*/
|
|
498
523
|
public async getInsecureUser({
|
|
499
524
|
requestHeaders,
|
|
525
|
+
allowUserAuthRefresh,
|
|
500
526
|
}: {
|
|
501
527
|
requestHeaders: IncomingHttpHeaders;
|
|
528
|
+
/**
|
|
529
|
+
* If true, this method will generate headers to refresh the user's auth session. This
|
|
530
|
+
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
531
|
+
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
532
|
+
*/
|
|
533
|
+
allowUserAuthRefresh: boolean;
|
|
502
534
|
}): Promise<GetUserResult<DatabaseUser> | undefined> {
|
|
503
535
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
504
536
|
const userIdResult = await insecureExtractUserIdFromCookieAlone<UserId>(
|
|
@@ -521,13 +553,16 @@ export class BackendAuthClient<
|
|
|
521
553
|
return undefined;
|
|
522
554
|
}
|
|
523
555
|
|
|
556
|
+
const refreshHeaders =
|
|
557
|
+
allowUserAuthRefresh &&
|
|
558
|
+
(await this.createCookieRefreshHeaders({
|
|
559
|
+
userIdResult,
|
|
560
|
+
}));
|
|
561
|
+
|
|
524
562
|
return {
|
|
525
563
|
user,
|
|
526
564
|
isAssumed: false,
|
|
527
|
-
responseHeaders:
|
|
528
|
-
(await this.createCookieRefreshHeaders({
|
|
529
|
-
userIdResult,
|
|
530
|
-
})) || {},
|
|
565
|
+
responseHeaders: refreshHeaders || {},
|
|
531
566
|
};
|
|
532
567
|
}
|
|
533
568
|
}
|