auth-vir 3.0.1 → 3.1.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.
@@ -60,6 +60,12 @@ export type BackendAuthClientConfig<DatabaseUser extends AnyObject, UserId exten
60
60
  */
61
61
  isDev: boolean;
62
62
  } & PartialWithUndefined<{
63
+ /** If this returns true, logging will be enabled while handling the relevant session. */
64
+ enableLogging(params: {
65
+ user: DatabaseUser | undefined;
66
+ userId: UserId | undefined;
67
+ assumedUserParams: AssumedUserParams | undefined;
68
+ }): boolean;
63
69
  /**
64
70
  * Overwrite the header name used for tracking is an admin is assuming the identity of
65
71
  * another user.
@@ -72,6 +78,8 @@ export type BackendAuthClientConfig<DatabaseUser extends AnyObject, UserId exten
72
78
  generateServiceOrigin(params: {
73
79
  requestHeaders: Readonly<IncomingHttpHeaders>;
74
80
  }): MaybePromise<undefined | string>;
81
+ /** If provided, logs will be sent to this method. */
82
+ log?: (message: string, extraData: AnyObject) => void;
75
83
  /**
76
84
  * Set this to allow specific users (determined by `canAssumeUser`) to assume the identity
77
85
  * of other users. This should only be used for admins so that they can troubleshoot user
@@ -141,6 +149,12 @@ export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId ex
141
149
  protected readonly config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams>;
142
150
  protected cachedParsedJwtKeys: Record<string, Readonly<JwtKeys>>;
143
151
  constructor(config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams>);
152
+ /** Conditionally logs a message if logging is enabled for the given user context. */
153
+ protected logForUser(params: {
154
+ user: DatabaseUser | undefined;
155
+ userId: UserId | undefined;
156
+ assumedUserParams: AssumedUserParams | undefined;
157
+ }, message: string, extra?: Record<string, unknown>): void;
144
158
  /** Get all the parameters used for cookie generation. */
145
159
  protected getCookieParams({ isSignUpCookie, requestHeaders, }: {
146
160
  /**
@@ -28,10 +28,27 @@ export class BackendAuthClient {
28
28
  constructor(config) {
29
29
  this.config = config;
30
30
  }
31
+ /** Conditionally logs a message if logging is enabled for the given user context. */
32
+ logForUser(params, message, extra) {
33
+ if (this.config.enableLogging?.(params)) {
34
+ const extraData = {
35
+ userId: params.userId,
36
+ ...extra,
37
+ };
38
+ if (this.config.log) {
39
+ this.config.log(message, extraData);
40
+ }
41
+ else {
42
+ console.info(`[auth-vir] ${message}`, extraData);
43
+ }
44
+ }
45
+ }
31
46
  /** Get all the parameters used for cookie generation. */
32
47
  async getCookieParams({ isSignUpCookie, requestHeaders, }) {
33
48
  const serviceOrigin = requestHeaders
34
- ? await this.config.generateServiceOrigin?.({ requestHeaders })
49
+ ? await this.config.generateServiceOrigin?.({
50
+ requestHeaders,
51
+ })
35
52
  : undefined;
36
53
  return {
37
54
  cookieDuration: this.config.userSessionIdleTimeout || defaultSessionIdleTimeout,
@@ -53,6 +70,13 @@ export class BackendAuthClient {
53
70
  requestHeaders,
54
71
  });
55
72
  if (!authenticatedUser) {
73
+ this.logForUser({
74
+ user: undefined,
75
+ userId,
76
+ assumedUserParams: assumingUser,
77
+ }, 'getUserFromDatabase returned no user', {
78
+ isSignUpCookie,
79
+ });
56
80
  return undefined;
57
81
  }
58
82
  return authenticatedUser;
@@ -67,6 +91,14 @@ export class BackendAuthClient {
67
91
  relativeTo: calculateRelativeDate(userIdResult.jwtExpiration, clockSkew),
68
92
  });
69
93
  if (isExpiredAlready) {
94
+ this.logForUser({
95
+ user: undefined,
96
+ userId: userIdResult.userId,
97
+ assumedUserParams: undefined,
98
+ }, 'Session refresh denied: JWT already expired (even with clock skew tolerance)', {
99
+ jwtExpiration: userIdResult.jwtExpiration,
100
+ now: JSON.stringify(now),
101
+ });
70
102
  return undefined;
71
103
  }
72
104
  /**
@@ -82,6 +114,15 @@ export class BackendAuthClient {
82
114
  relativeTo: maxSessionEndDate,
83
115
  });
84
116
  if (isSessionExpired) {
117
+ this.logForUser({
118
+ user: undefined,
119
+ userId: userIdResult.userId,
120
+ assumedUserParams: undefined,
121
+ }, 'Session refresh denied: max session duration exceeded', {
122
+ sessionStartedAt: userIdResult.sessionStartedAt,
123
+ maxSessionEndDate: JSON.stringify(maxSessionEndDate),
124
+ now: JSON.stringify(now),
125
+ });
85
126
  return undefined;
86
127
  }
87
128
  }
@@ -112,6 +153,14 @@ export class BackendAuthClient {
112
153
  };
113
154
  }
114
155
  else {
156
+ this.logForUser({
157
+ user: undefined,
158
+ userId: userIdResult.userId,
159
+ assumedUserParams: undefined,
160
+ }, 'Session refresh skipped: not yet ready for refresh', {
161
+ jwtIssuedAt: userIdResult.jwtIssuedAt,
162
+ sessionRefreshStartTime,
163
+ });
115
164
  return undefined;
116
165
  }
117
166
  }
@@ -140,6 +189,13 @@ export class BackendAuthClient {
140
189
  async getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }) {
141
190
  const userIdResult = await extractUserIdFromRequestHeaders(requestHeaders, await this.getJwtParams(), this.config.csrf, isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth);
142
191
  if (!userIdResult) {
192
+ this.logForUser({
193
+ user: undefined,
194
+ userId: undefined,
195
+ assumedUserParams: undefined,
196
+ }, 'getSecureUser: failed to extract user ID from request headers (invalid JWT, missing cookie, or CSRF mismatch)', {
197
+ isSignUpCookie,
198
+ });
143
199
  return undefined;
144
200
  }
145
201
  const user = await this.getDatabaseUser({
@@ -149,6 +205,13 @@ export class BackendAuthClient {
149
205
  requestHeaders,
150
206
  });
151
207
  if (!user) {
208
+ this.logForUser({
209
+ user: undefined,
210
+ userId: userIdResult.userId,
211
+ assumedUserParams: undefined,
212
+ }, 'getSecureUser: user not found in database', {
213
+ isSignUpCookie,
214
+ });
152
215
  return undefined;
153
216
  }
154
217
  const assumedUser = await this.getAssumedUser({
@@ -175,7 +238,9 @@ export class BackendAuthClient {
175
238
  const cachedParsedKeys = this.cachedParsedJwtKeys[cacheKey];
176
239
  const parsedKeys = cachedParsedKeys || (await parseJwtKeys(rawJwtKeys));
177
240
  if (!cachedParsedKeys) {
178
- this.cachedParsedJwtKeys = { [cacheKey]: parsedKeys };
241
+ this.cachedParsedJwtKeys = {
242
+ [cacheKey]: parsedKeys,
243
+ };
179
244
  }
180
245
  return {
181
246
  jwtKeys: parsedKeys,
@@ -241,11 +306,17 @@ export class BackendAuthClient {
241
306
  async getInsecureOrSecureUser(params) {
242
307
  const secureUser = await this.getSecureUser(params);
243
308
  if (secureUser) {
244
- return { secureUser };
309
+ return {
310
+ secureUser,
311
+ };
245
312
  }
246
313
  // eslint-disable-next-line @typescript-eslint/no-deprecated
247
314
  const insecureUser = await this.getInsecureUser(params);
248
- return insecureUser ? { insecureUser } : {};
315
+ return insecureUser
316
+ ? {
317
+ insecureUser,
318
+ }
319
+ : {};
249
320
  }
250
321
  /**
251
322
  * @deprecated This only half authenticates the user. It should only be used in circumstances
@@ -256,6 +327,11 @@ export class BackendAuthClient {
256
327
  // eslint-disable-next-line @typescript-eslint/no-deprecated
257
328
  const userIdResult = await insecureExtractUserIdFromCookieAlone(requestHeaders, await this.getJwtParams(), AuthCookieName.Auth);
258
329
  if (!userIdResult) {
330
+ this.logForUser({
331
+ user: undefined,
332
+ userId: undefined,
333
+ assumedUserParams: undefined,
334
+ }, 'getInsecureUser: failed to extract user ID from cookie (invalid JWT or missing cookie)');
259
335
  return undefined;
260
336
  }
261
337
  const user = await this.getDatabaseUser({
@@ -265,6 +341,11 @@ export class BackendAuthClient {
265
341
  requestHeaders,
266
342
  });
267
343
  if (!user) {
344
+ this.logForUser({
345
+ user: undefined,
346
+ userId: userIdResult.userId,
347
+ assumedUserParams: undefined,
348
+ }, 'getInsecureUser: user not found in database');
268
349
  return undefined;
269
350
  }
270
351
  const refreshHeaders = allowUserAuthRefresh &&
@@ -26,7 +26,9 @@ export class FrontendAuthClient {
26
26
  });
27
27
  }
28
28
  },
29
- debounce: config.checkUser.debounce || { minutes: 1 },
29
+ debounce: config.checkUser.debounce || {
30
+ minutes: 1,
31
+ },
30
32
  fireImmediately: false,
31
33
  });
32
34
  }
package/dist/cookie.js CHANGED
@@ -29,7 +29,9 @@ export async function generateAuthCookie(userJwtData, cookieConfig) {
29
29
  HttpOnly: true,
30
30
  Path: '/',
31
31
  SameSite: 'Strict',
32
- 'MAX-AGE': convertDuration(cookieConfig.cookieDuration, { seconds: true }).seconds,
32
+ 'MAX-AGE': convertDuration(cookieConfig.cookieDuration, {
33
+ seconds: true,
34
+ }).seconds,
33
35
  Secure: !cookieConfig.isDev,
34
36
  }),
35
37
  expiration,
@@ -17,7 +17,9 @@ export const csrfTokenShape = defineShape({
17
17
  * @category Internal
18
18
  * @default {minutes: 5}
19
19
  */
20
- export const defaultAllowedClockSkew = { minutes: 5 };
20
+ export const defaultAllowedClockSkew = {
21
+ minutes: 5,
22
+ };
21
23
  /**
22
24
  * Generates a random, cryptographically secure CSRF token.
23
25
  *
package/dist/jwt/jwt.js CHANGED
@@ -2,8 +2,13 @@ import { assertWrap, check } from '@augment-vir/assert';
2
2
  import { calculateRelativeDate, convertDuration, createFullDateInUserTimezone, createUtcFullDate, getNowInUtcTimezone, toTimestamp, } from 'date-vir';
3
3
  import { EncryptJWT, jwtDecrypt, jwtVerify, SignJWT } from 'jose';
4
4
  import { defaultAllowedClockSkew } from '../csrf-token.js';
5
- const encryptionProtectedHeader = { alg: 'dir', enc: 'A256GCM' };
6
- const signingProtectedHeader = { alg: 'HS512' };
5
+ const encryptionProtectedHeader = {
6
+ alg: 'dir',
7
+ enc: 'A256GCM',
8
+ };
9
+ const signingProtectedHeader = {
10
+ alg: 'HS512',
11
+ };
7
12
  /**
8
13
  * JWT uses seconds since the epoch per RFC 7519, whereas `toTimestamp` uses milliseconds.
9
14
  *
@@ -28,7 +33,9 @@ export function parseJwtTimestamp(seconds) {
28
33
  export async function createJwt(
29
34
  /** The data to be included in the JWT. */
30
35
  data, params) {
31
- const rawJwt = new SignJWT({ data })
36
+ const rawJwt = new SignJWT({
37
+ data,
38
+ })
32
39
  .setProtectedHeader(signingProtectedHeader)
33
40
  .setIssuedAt(params.issuedAt
34
41
  ? toJwtTimestamp(createFullDateInUserTimezone(params.issuedAt))
@@ -40,7 +47,9 @@ data, params) {
40
47
  rawJwt.setNotBefore(toJwtTimestamp(createFullDateInUserTimezone(params.notValidUntil)));
41
48
  }
42
49
  const signedJwt = await rawJwt.sign(params.jwtKeys.signingKey);
43
- return await new EncryptJWT({ jwt: signedJwt })
50
+ return await new EncryptJWT({
51
+ jwt: signedJwt,
52
+ })
44
53
  .setProtectedHeader(encryptionProtectedHeader)
45
54
  .encrypt(params.jwtKeys.encryptionKey);
46
55
  }
@@ -58,7 +67,9 @@ export async function parseJwt(encryptedJwt, params) {
58
67
  else if (!check.isString(decryptedJwt.payload.jwt)) {
59
68
  throw new TypeError('Decrypted jwt is not a string.');
60
69
  }
61
- const clockToleranceSeconds = convertDuration(params.allowedClockSkew || defaultAllowedClockSkew, { seconds: true }).seconds;
70
+ const clockToleranceSeconds = convertDuration(params.allowedClockSkew || defaultAllowedClockSkew, {
71
+ seconds: true,
72
+ }).seconds;
62
73
  const verifiedJwt = await jwtVerify(decryptedJwt.payload.jwt, params.jwtKeys.signingKey, {
63
74
  issuer: params.issuer,
64
75
  audience: params.audience,
@@ -19,7 +19,9 @@ export const userJwtDataShape = defineShape({
19
19
  * enforce the max session duration. If not present, the session is considered to have started
20
20
  * when the JWT was issued.
21
21
  */
22
- sessionStartedAt: optionalShape(0, { alsoUndefined: true }),
22
+ sessionStartedAt: optionalShape(0, {
23
+ alsoUndefined: true,
24
+ }),
23
25
  });
24
26
  /**
25
27
  * Creates a new signed and encrypted {@link JwtUserData} when a client (frontend) successfully
@@ -44,7 +44,10 @@ init = {}) {
44
44
  delete store[key];
45
45
  },
46
46
  setItem(key, value) {
47
- accessRecord.setItem.push({ key, value });
47
+ accessRecord.setItem.push({
48
+ key,
49
+ value,
50
+ });
48
51
  store[key] = value;
49
52
  },
50
53
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth-vir",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "Auth made easy and secure via JWT cookies, CSRF tokens, and password hashing helpers.",
5
5
  "keywords": [
6
6
  "auth",
@@ -41,9 +41,9 @@
41
41
  "test:web": "virmator test web"
42
42
  },
43
43
  "dependencies": {
44
- "@augment-vir/assert": "^31.65.0",
45
- "@augment-vir/common": "^31.65.0",
46
- "date-vir": "^8.1.1",
44
+ "@augment-vir/assert": "^31.67.1",
45
+ "@augment-vir/common": "^31.67.1",
46
+ "date-vir": "^8.2.0",
47
47
  "detect-activity": "^1.0.0",
48
48
  "hash-wasm": "^4.12.0",
49
49
  "jose": "^6.1.3",
@@ -52,9 +52,9 @@
52
52
  "url-vir": "^2.1.7"
53
53
  },
54
54
  "devDependencies": {
55
- "@augment-vir/test": "^31.65.0",
55
+ "@augment-vir/test": "^31.67.1",
56
56
  "@prisma/client": "^6.19.2",
57
- "@types/node": "^25.3.0",
57
+ "@types/node": "^25.3.3",
58
58
  "@web/dev-server-esbuild": "^1.0.5",
59
59
  "@web/test-runner": "^0.20.2",
60
60
  "@web/test-runner-commands": "^0.9.0",
@@ -91,6 +91,12 @@ export type BackendAuthClientConfig<
91
91
  */
92
92
  isDev: boolean;
93
93
  } & PartialWithUndefined<{
94
+ /** If this returns true, logging will be enabled while handling the relevant session. */
95
+ enableLogging(params: {
96
+ user: DatabaseUser | undefined;
97
+ userId: UserId | undefined;
98
+ assumedUserParams: AssumedUserParams | undefined;
99
+ }): boolean;
94
100
  /**
95
101
  * Overwrite the header name used for tracking is an admin is assuming the identity of
96
102
  * another user.
@@ -103,6 +109,8 @@ export type BackendAuthClientConfig<
103
109
  generateServiceOrigin(params: {
104
110
  requestHeaders: Readonly<IncomingHttpHeaders>;
105
111
  }): MaybePromise<undefined | string>;
112
+ /** If provided, logs will be sent to this method. */
113
+ log?: (message: string, extraData: AnyObject) => void;
106
114
  /**
107
115
  * Set this to allow specific users (determined by `canAssumeUser`) to assume the identity
108
116
  * of other users. This should only be used for admins so that they can troubleshoot user
@@ -197,6 +205,30 @@ export class BackendAuthClient<
197
205
  protected readonly config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams>,
198
206
  ) {}
199
207
 
208
+ /** Conditionally logs a message if logging is enabled for the given user context. */
209
+ protected logForUser(
210
+ params: {
211
+ user: DatabaseUser | undefined;
212
+ userId: UserId | undefined;
213
+ assumedUserParams: AssumedUserParams | undefined;
214
+ },
215
+ message: string,
216
+ extra?: Record<string, unknown>,
217
+ ): void {
218
+ if (this.config.enableLogging?.(params)) {
219
+ const extraData = {
220
+ userId: params.userId,
221
+ ...extra,
222
+ };
223
+
224
+ if (this.config.log) {
225
+ this.config.log(message, extraData);
226
+ } else {
227
+ console.info(`[auth-vir] ${message}`, extraData);
228
+ }
229
+ }
230
+ }
231
+
200
232
  /** Get all the parameters used for cookie generation. */
201
233
  protected async getCookieParams({
202
234
  isSignUpCookie,
@@ -212,7 +244,9 @@ export class BackendAuthClient<
212
244
  requestHeaders: Readonly<IncomingHttpHeaders> | undefined;
213
245
  }): Promise<Readonly<CookieParams>> {
214
246
  const serviceOrigin = requestHeaders
215
- ? await this.config.generateServiceOrigin?.({requestHeaders})
247
+ ? await this.config.generateServiceOrigin?.({
248
+ requestHeaders,
249
+ })
216
250
  : undefined;
217
251
 
218
252
  return {
@@ -248,6 +282,17 @@ export class BackendAuthClient<
248
282
  });
249
283
 
250
284
  if (!authenticatedUser) {
285
+ this.logForUser(
286
+ {
287
+ user: undefined,
288
+ userId,
289
+ assumedUserParams: assumingUser,
290
+ },
291
+ 'getUserFromDatabase returned no user',
292
+ {
293
+ isSignUpCookie,
294
+ },
295
+ );
251
296
  return undefined;
252
297
  }
253
298
 
@@ -273,6 +318,18 @@ export class BackendAuthClient<
273
318
  });
274
319
 
275
320
  if (isExpiredAlready) {
321
+ this.logForUser(
322
+ {
323
+ user: undefined,
324
+ userId: userIdResult.userId,
325
+ assumedUserParams: undefined,
326
+ },
327
+ 'Session refresh denied: JWT already expired (even with clock skew tolerance)',
328
+ {
329
+ jwtExpiration: userIdResult.jwtExpiration,
330
+ now: JSON.stringify(now),
331
+ },
332
+ );
276
333
  return undefined;
277
334
  }
278
335
 
@@ -290,6 +347,19 @@ export class BackendAuthClient<
290
347
  });
291
348
 
292
349
  if (isSessionExpired) {
350
+ this.logForUser(
351
+ {
352
+ user: undefined,
353
+ userId: userIdResult.userId,
354
+ assumedUserParams: undefined,
355
+ },
356
+ 'Session refresh denied: max session duration exceeded',
357
+ {
358
+ sessionStartedAt: userIdResult.sessionStartedAt,
359
+ maxSessionEndDate: JSON.stringify(maxSessionEndDate),
360
+ now: JSON.stringify(now),
361
+ },
362
+ );
293
363
  return undefined;
294
364
  }
295
365
  }
@@ -327,6 +397,18 @@ export class BackendAuthClient<
327
397
  }),
328
398
  };
329
399
  } else {
400
+ this.logForUser(
401
+ {
402
+ user: undefined,
403
+ userId: userIdResult.userId,
404
+ assumedUserParams: undefined,
405
+ },
406
+ 'Session refresh skipped: not yet ready for refresh',
407
+ {
408
+ jwtIssuedAt: userIdResult.jwtIssuedAt,
409
+ sessionRefreshStartTime,
410
+ },
411
+ );
330
412
  return undefined;
331
413
  }
332
414
  }
@@ -390,6 +472,17 @@ export class BackendAuthClient<
390
472
  isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth,
391
473
  );
392
474
  if (!userIdResult) {
475
+ this.logForUser(
476
+ {
477
+ user: undefined,
478
+ userId: undefined,
479
+ assumedUserParams: undefined,
480
+ },
481
+ 'getSecureUser: failed to extract user ID from request headers (invalid JWT, missing cookie, or CSRF mismatch)',
482
+ {
483
+ isSignUpCookie,
484
+ },
485
+ );
393
486
  return undefined;
394
487
  }
395
488
 
@@ -401,6 +494,17 @@ export class BackendAuthClient<
401
494
  });
402
495
 
403
496
  if (!user) {
497
+ this.logForUser(
498
+ {
499
+ user: undefined,
500
+ userId: userIdResult.userId,
501
+ assumedUserParams: undefined,
502
+ },
503
+ 'getSecureUser: user not found in database',
504
+ {
505
+ isSignUpCookie,
506
+ },
507
+ );
404
508
  return undefined;
405
509
  }
406
510
 
@@ -435,7 +539,9 @@ export class BackendAuthClient<
435
539
  const parsedKeys = cachedParsedKeys || (await parseJwtKeys(rawJwtKeys));
436
540
 
437
541
  if (!cachedParsedKeys) {
438
- this.cachedParsedJwtKeys = {[cacheKey]: parsedKeys};
542
+ this.cachedParsedJwtKeys = {
543
+ [cacheKey]: parsedKeys,
544
+ };
439
545
  }
440
546
  return {
441
547
  jwtKeys: parsedKeys,
@@ -584,13 +690,19 @@ export class BackendAuthClient<
584
690
  const secureUser = await this.getSecureUser(params);
585
691
 
586
692
  if (secureUser) {
587
- return {secureUser};
693
+ return {
694
+ secureUser,
695
+ };
588
696
  }
589
697
 
590
698
  // eslint-disable-next-line @typescript-eslint/no-deprecated
591
699
  const insecureUser = await this.getInsecureUser(params);
592
700
 
593
- return insecureUser ? {insecureUser} : {};
701
+ return insecureUser
702
+ ? {
703
+ insecureUser,
704
+ }
705
+ : {};
594
706
  }
595
707
 
596
708
  /**
@@ -618,6 +730,14 @@ export class BackendAuthClient<
618
730
  );
619
731
 
620
732
  if (!userIdResult) {
733
+ this.logForUser(
734
+ {
735
+ user: undefined,
736
+ userId: undefined,
737
+ assumedUserParams: undefined,
738
+ },
739
+ 'getInsecureUser: failed to extract user ID from cookie (invalid JWT or missing cookie)',
740
+ );
621
741
  return undefined;
622
742
  }
623
743
 
@@ -629,6 +749,14 @@ export class BackendAuthClient<
629
749
  });
630
750
 
631
751
  if (!user) {
752
+ this.logForUser(
753
+ {
754
+ user: undefined,
755
+ userId: userIdResult.userId,
756
+ assumedUserParams: undefined,
757
+ },
758
+ 'getInsecureUser: user not found in database',
759
+ );
632
760
  return undefined;
633
761
  }
634
762
 
@@ -112,7 +112,9 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
112
112
  });
113
113
  }
114
114
  },
115
- debounce: config.checkUser.debounce || {minutes: 1},
115
+ debounce: config.checkUser.debounce || {
116
+ minutes: 1,
117
+ },
116
118
  fireImmediately: false,
117
119
  });
118
120
  }
package/src/cookie.ts CHANGED
@@ -91,7 +91,9 @@ export async function generateAuthCookie(
91
91
  HttpOnly: true,
92
92
  Path: '/',
93
93
  SameSite: 'Strict',
94
- 'MAX-AGE': convertDuration(cookieConfig.cookieDuration, {seconds: true}).seconds,
94
+ 'MAX-AGE': convertDuration(cookieConfig.cookieDuration, {
95
+ seconds: true,
96
+ }).seconds,
95
97
  Secure: !cookieConfig.isDev,
96
98
  }),
97
99
  expiration,
package/src/csrf-token.ts CHANGED
@@ -38,7 +38,9 @@ export type CsrfToken = typeof csrfTokenShape.runtimeType;
38
38
  * @category Internal
39
39
  * @default {minutes: 5}
40
40
  */
41
- export const defaultAllowedClockSkew: Readonly<AnyDuration> = {minutes: 5};
41
+ export const defaultAllowedClockSkew: Readonly<AnyDuration> = {
42
+ minutes: 5,
43
+ };
42
44
 
43
45
  /**
44
46
  * Generates a random, cryptographically secure CSRF token.
package/src/jwt/jwt.ts CHANGED
@@ -16,8 +16,13 @@ import {EncryptJWT, jwtDecrypt, jwtVerify, SignJWT} from 'jose';
16
16
  import {defaultAllowedClockSkew} from '../csrf-token.js';
17
17
  import {type JwtKeys} from './jwt-keys.js';
18
18
 
19
- const encryptionProtectedHeader = {alg: 'dir', enc: 'A256GCM'};
20
- const signingProtectedHeader = {alg: 'HS512'};
19
+ const encryptionProtectedHeader = {
20
+ alg: 'dir',
21
+ enc: 'A256GCM',
22
+ };
23
+ const signingProtectedHeader = {
24
+ alg: 'HS512',
25
+ };
21
26
 
22
27
  /**
23
28
  * Params for {@link createJwt}.
@@ -110,7 +115,9 @@ export async function createJwt<JwtData extends AnyObject = AnyObject>(
110
115
  data: JwtData,
111
116
  params: Readonly<CreateJwtParams>,
112
117
  ): Promise<string> {
113
- const rawJwt = new SignJWT({data})
118
+ const rawJwt = new SignJWT({
119
+ data,
120
+ })
114
121
  .setProtectedHeader(signingProtectedHeader)
115
122
  .setIssuedAt(
116
123
  params.issuedAt
@@ -129,7 +136,9 @@ export async function createJwt<JwtData extends AnyObject = AnyObject>(
129
136
 
130
137
  const signedJwt = await rawJwt.sign(params.jwtKeys.signingKey);
131
138
 
132
- return await new EncryptJWT({jwt: signedJwt})
139
+ return await new EncryptJWT({
140
+ jwt: signedJwt,
141
+ })
133
142
  .setProtectedHeader(encryptionProtectedHeader)
134
143
  .encrypt(params.jwtKeys.encryptionKey);
135
144
  }
@@ -182,7 +191,9 @@ export async function parseJwt<JwtData extends AnyObject = AnyObject>(
182
191
 
183
192
  const clockToleranceSeconds = convertDuration(
184
193
  params.allowedClockSkew || defaultAllowedClockSkew,
185
- {seconds: true},
194
+ {
195
+ seconds: true,
196
+ },
186
197
  ).seconds;
187
198
 
188
199
  const verifiedJwt = await jwtVerify(decryptedJwt.payload.jwt, params.jwtKeys.signingKey, {
@@ -27,7 +27,9 @@ export const userJwtDataShape = defineShape({
27
27
  * enforce the max session duration. If not present, the session is considered to have started
28
28
  * when the JWT was issued.
29
29
  */
30
- sessionStartedAt: optionalShape(0, {alsoUndefined: true}),
30
+ sessionStartedAt: optionalShape(0, {
31
+ alsoUndefined: true,
32
+ }),
31
33
  });
32
34
 
33
35
  /**
@@ -59,7 +59,10 @@ export function createMockLocalStorage(
59
59
  delete store[key];
60
60
  },
61
61
  setItem(key, value) {
62
- accessRecord.setItem.push({key, value});
62
+ accessRecord.setItem.push({
63
+ key,
64
+ value,
65
+ });
63
66
  store[key] = value;
64
67
  },
65
68
  };