auth-vir 2.6.0 → 2.7.1

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.
@@ -4,6 +4,7 @@ import { extractUserIdFromRequestHeaders, generateLogoutHeaders, generateSuccess
4
4
  import { AuthCookieName } from '../cookie.js';
5
5
  import { AuthHeaderName, mergeHeaderValues } from '../headers.js';
6
6
  import { parseJwtKeys } from '../jwt/jwt-keys.js';
7
+ import { authLog } from '../log.js';
7
8
  const defaultSessionIdleTimeout = {
8
9
  minutes: 20,
9
10
  };
@@ -63,6 +64,10 @@ export class BackendAuthClient {
63
64
  relativeTo: userIdResult.jwtExpiration,
64
65
  });
65
66
  if (isExpiredAlready) {
67
+ authLog('auth-vir: SESSION EXPIRED - JWT already expired, user will be logged out', {
68
+ userId: userIdResult.userId,
69
+ jwtExpiration: userIdResult.jwtExpiration,
70
+ });
66
71
  return undefined;
67
72
  }
68
73
  /**
@@ -78,6 +83,11 @@ export class BackendAuthClient {
78
83
  relativeTo: maxSessionEndDate,
79
84
  });
80
85
  if (isSessionExpired) {
86
+ authLog('auth-vir: SESSION EXPIRED - max session duration exceeded, user will be logged out', {
87
+ userId: userIdResult.userId,
88
+ sessionStartedAt: userIdResult.sessionStartedAt,
89
+ maxSessionDuration,
90
+ });
81
91
  return undefined;
82
92
  }
83
93
  }
@@ -136,6 +146,7 @@ export class BackendAuthClient {
136
146
  async getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }) {
137
147
  const userIdResult = await extractUserIdFromRequestHeaders(requestHeaders, await this.getJwtParams(), isSignUpCookie ? AuthCookieName.SignUp : AuthCookieName.Auth, this.config.overrides);
138
148
  if (!userIdResult) {
149
+ authLog('auth-vir: getSecureUser failed - could not extract user from request');
139
150
  return undefined;
140
151
  }
141
152
  const user = await this.getDatabaseUser({
@@ -144,6 +155,9 @@ export class BackendAuthClient {
144
155
  isSignUpCookie,
145
156
  });
146
157
  if (!user) {
158
+ authLog('auth-vir: getSecureUser failed - user not found in database', {
159
+ userId: userIdResult.userId,
160
+ });
147
161
  return undefined;
148
162
  }
149
163
  const assumedUser = await this.getAssumedUser({
@@ -181,6 +195,10 @@ export class BackendAuthClient {
181
195
  }
182
196
  /** Use these headers to log out the user. */
183
197
  async createLogoutHeaders(params) {
198
+ authLog('auth-vir: LOGOUT - BackendAuthClient.createLogoutHeaders called', {
199
+ allCookies: 'allCookies' in params ? params.allCookies : undefined,
200
+ isSignUpCookie: 'isSignUpCookie' in params ? params.isSignUpCookie : undefined,
201
+ }, new Error().stack);
184
202
  const signUpCookieHeaders = params.allCookies || params.isSignUpCookie
185
203
  ? generateLogoutHeaders(await this.getCookieParams({
186
204
  isSignUpCookie: true,
@@ -250,6 +268,7 @@ export class BackendAuthClient {
250
268
  // eslint-disable-next-line @typescript-eslint/no-deprecated
251
269
  const userIdResult = await insecureExtractUserIdFromCookieAlone(requestHeaders, await this.getJwtParams(), AuthCookieName.Auth);
252
270
  if (!userIdResult) {
271
+ authLog('auth-vir: getInsecureUser failed - could not extract user from request');
253
272
  return undefined;
254
273
  }
255
274
  const user = await this.getDatabaseUser({
@@ -258,6 +277,9 @@ export class BackendAuthClient {
258
277
  assumingUser: undefined,
259
278
  });
260
279
  if (!user) {
280
+ authLog('auth-vir: getInsecureUser failed - user not found in database', {
281
+ userId: userIdResult.userId,
282
+ });
261
283
  return undefined;
262
284
  }
263
285
  const refreshHeaders = allowUserAuthRefresh &&
@@ -2,6 +2,7 @@ import { HttpStatus, } from '@augment-vir/common';
2
2
  import { listenToActivity } from 'detect-activity';
3
3
  import { CsrfTokenFailureReason, extractCsrfTokenHeader, getCurrentCsrfToken, storeCsrfToken, wipeCurrentCsrfToken, } from '../csrf-token.js';
4
4
  import { AuthHeaderName } from '../headers.js';
5
+ import { authLog } from '../log.js';
5
6
  /**
6
7
  * An auth client for sending and validating client requests to a backend. This should only be used
7
8
  * in a frontend environment as it accesses native browser APIs.
@@ -44,6 +45,9 @@ export class FrontendAuthClient {
44
45
  const csrfTokenResult = getCurrentCsrfToken(this.config.overrides);
45
46
  if (csrfTokenResult.failure &&
46
47
  csrfTokenResult.failure !== CsrfTokenFailureReason.DoesNotExist) {
48
+ authLog('auth-vir: LOGOUT - getCurrentCsrfToken: invalid CSRF token', {
49
+ failure: csrfTokenResult.failure,
50
+ });
47
51
  await this.logout();
48
52
  return undefined;
49
53
  }
@@ -110,6 +114,7 @@ export class FrontendAuthClient {
110
114
  }
111
115
  /** Wipes the current user auth. */
112
116
  async logout() {
117
+ authLog('auth-vir: LOGOUT - FrontendAuthClient.logout called', new Error().stack);
113
118
  await this.config.authClearedCallback?.();
114
119
  wipeCurrentCsrfToken(this.config.overrides);
115
120
  }
@@ -121,11 +126,13 @@ export class FrontendAuthClient {
121
126
  */
122
127
  async handleLoginResponse(response) {
123
128
  if (!response.ok) {
129
+ authLog('auth-vir: LOGOUT - handleLoginResponse: response not ok');
124
130
  await this.logout();
125
131
  throw new Error('Login response failed.');
126
132
  }
127
133
  const { csrfToken } = extractCsrfTokenHeader(response, this.config.overrides);
128
134
  if (!csrfToken) {
135
+ authLog('auth-vir: LOGOUT - handleLoginResponse: no CSRF token in response');
129
136
  await this.logout();
130
137
  throw new Error('Did not receive any CSRF token.');
131
138
  }
@@ -140,6 +147,9 @@ export class FrontendAuthClient {
140
147
  async verifyResponseAuth(response) {
141
148
  if (response.status === HttpStatus.Unauthorized &&
142
149
  !response.headers?.get(AuthHeaderName.IsSignUpAuth)) {
150
+ authLog('auth-vir: LOGOUT - verifyResponseAuth: unauthorized response (401)', {
151
+ status: response.status,
152
+ });
143
153
  await this.logout();
144
154
  return false;
145
155
  }
package/dist/auth.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AuthCookieName, clearAuthCookie, extractCookieJwt, generateAuthCookie, } from './cookie.js';
2
2
  import { extractCsrfTokenHeader, generateCsrfToken, parseCsrfToken, storeCsrfToken, wipeCurrentCsrfToken, } from './csrf-token.js';
3
3
  import { AuthHeaderName } from './headers.js';
4
+ import { authLog } from './log.js';
4
5
  function readHeader(headers, headerName) {
5
6
  if (headers instanceof Headers) {
6
7
  return headers.get(headerName) || undefined;
@@ -38,10 +39,20 @@ export async function extractUserIdFromRequestHeaders(headers, jwtParams, cookie
38
39
  const csrfToken = readCsrfTokenHeader(headers, overrides);
39
40
  const cookie = readHeader(headers, 'cookie');
40
41
  if (!cookie || !csrfToken) {
42
+ authLog('auth-vir: extractUserIdFromRequestHeaders failed - missing cookie or CSRF token', {
43
+ hasCookie: !!cookie,
44
+ hasCsrfToken: !!csrfToken,
45
+ cookieName,
46
+ });
41
47
  return undefined;
42
48
  }
43
49
  const jwt = await extractCookieJwt(cookie, jwtParams, cookieName);
44
50
  if (!jwt || jwt.data.csrfToken !== csrfToken) {
51
+ authLog('auth-vir: extractUserIdFromRequestHeaders failed - JWT invalid or CSRF mismatch', {
52
+ hasJwt: !!jwt,
53
+ csrfMatch: jwt ? jwt.data.csrfToken === csrfToken : false,
54
+ cookieName,
55
+ });
45
56
  return undefined;
46
57
  }
47
58
  return {
@@ -51,7 +62,8 @@ export async function extractUserIdFromRequestHeaders(headers, jwtParams, cookie
51
62
  sessionStartedAt: jwt.data.sessionStartedAt,
52
63
  };
53
64
  }
54
- catch {
65
+ catch (error) {
66
+ authLog('auth-vir: extractUserIdFromRequestHeaders error', { error, cookieName });
55
67
  return undefined;
56
68
  }
57
69
  }
@@ -67,10 +79,12 @@ export async function insecureExtractUserIdFromCookieAlone(headers, jwtParams, c
67
79
  try {
68
80
  const cookie = readHeader(headers, 'cookie');
69
81
  if (!cookie) {
82
+ authLog('auth-vir: insecureExtractUserIdFromCookieAlone failed - no cookie');
70
83
  return undefined;
71
84
  }
72
85
  const jwt = await extractCookieJwt(cookie, jwtParams, cookieName);
73
86
  if (!jwt) {
87
+ authLog('auth-vir: insecureExtractUserIdFromCookieAlone failed - JWT extraction failed');
74
88
  return undefined;
75
89
  }
76
90
  return {
@@ -80,7 +94,8 @@ export async function insecureExtractUserIdFromCookieAlone(headers, jwtParams, c
80
94
  sessionStartedAt: jwt.data.sessionStartedAt,
81
95
  };
82
96
  }
83
- catch {
97
+ catch (error) {
98
+ authLog('auth-vir: insecureExtractUserIdFromCookieAlone error', { error });
84
99
  return undefined;
85
100
  }
86
101
  }
@@ -115,6 +130,9 @@ sessionStartedAt) {
115
130
  * @category Auth : Host
116
131
  */
117
132
  export function generateLogoutHeaders(cookieConfig, overrides = {}) {
133
+ authLog('auth-vir: LOGOUT - generateLogoutHeaders called', {
134
+ cookieName: cookieConfig.cookieName,
135
+ }, new Error().stack);
118
136
  const csrfHeaderName = (overrides.csrfHeaderName || AuthHeaderName.CsrfToken);
119
137
  return {
120
138
  'set-cookie': clearAuthCookie(cookieConfig),
@@ -132,13 +150,16 @@ export function generateLogoutHeaders(cookieConfig, overrides = {}) {
132
150
  */
133
151
  export function handleAuthResponse(response, overrides = {}) {
134
152
  if (!response.ok) {
153
+ authLog('auth-vir: LOGOUT - handleAuthResponse: response not ok, wiping CSRF token');
135
154
  wipeCurrentCsrfToken(overrides);
136
155
  return;
137
156
  }
138
157
  const { csrfToken } = extractCsrfTokenHeader(response, overrides);
139
158
  if (!csrfToken) {
159
+ authLog('auth-vir: LOGOUT - handleAuthResponse: no CSRF token in response, wiping');
140
160
  wipeCurrentCsrfToken(overrides);
141
161
  throw new Error('Did not receive any CSRF token.');
142
162
  }
163
+ authLog('auth-vir: handleAuthResponse - successfully stored CSRF token');
143
164
  storeCsrfToken(csrfToken, overrides);
144
165
  }
@@ -2,6 +2,7 @@ import { randomString, wrapInTry, } from '@augment-vir/common';
2
2
  import { calculateRelativeDate, fullDateShape, getNowInUtcTimezone, isDateAfter, } from 'date-vir';
3
3
  import { defineShape, parseJsonWithShape } from 'object-shape-tester';
4
4
  import { AuthHeaderName } from './headers.js';
5
+ import { authLog } from './log.js';
5
6
  /**
6
7
  * Shape definition for {@link CsrfToken}.
7
8
  *
@@ -74,6 +75,7 @@ export function parseCsrfToken(value) {
74
75
  fallbackValue: undefined,
75
76
  });
76
77
  if (!csrfToken) {
78
+ authLog('auth-vir: CSRF token parse failed - will cause logout if used');
77
79
  return {
78
80
  failure: CsrfTokenFailureReason.ParseFailed,
79
81
  };
@@ -82,6 +84,9 @@ export function parseCsrfToken(value) {
82
84
  fullDate: getNowInUtcTimezone(),
83
85
  relativeTo: csrfToken.expiration,
84
86
  })) {
87
+ authLog('auth-vir: CSRF token expired - will cause logout', {
88
+ expiration: csrfToken.expiration,
89
+ });
85
90
  return {
86
91
  failure: CsrfTokenFailureReason.Expired,
87
92
  };
@@ -107,5 +112,6 @@ export function getCurrentCsrfToken(overrides = {}) {
107
112
  * @category Auth : Client
108
113
  */
109
114
  export function wipeCurrentCsrfToken(overrides = {}) {
115
+ authLog('auth-vir: wipeCurrentCsrfToken called', new Error().stack);
110
116
  return (overrides.localStorage || globalThis.localStorage).removeItem(overrides.csrfHeaderName || AuthHeaderName.CsrfToken);
111
117
  }
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export * from './headers.js';
8
8
  export * from './jwt/jwt-keys.js';
9
9
  export * from './jwt/jwt.js';
10
10
  export * from './jwt/user-jwt.js';
11
+ export * from './log.js';
11
12
  export * from './mock-local-storage.js';
package/dist/index.js CHANGED
@@ -8,4 +8,5 @@ export * from './headers.js';
8
8
  export * from './jwt/jwt-keys.js';
9
9
  export * from './jwt/jwt.js';
10
10
  export * from './jwt/user-jwt.js';
11
+ export * from './log.js';
11
12
  export * from './mock-local-storage.js';
package/dist/log.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Send logs to the console for debugging.
3
+ *
4
+ * @category Internal
5
+ */
6
+ export declare function authLog(...params: any[]): void;
7
+ /**
8
+ * Set to `false` to disable logging.
9
+ *
10
+ * @category Internal
11
+ */
12
+ export declare function setShouldLogAuth(value: boolean): void;
package/dist/log.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Send logs to the console for debugging.
3
+ *
4
+ * @category Internal
5
+ */
6
+ export function authLog(...params) {
7
+ if (!shouldLogAuth) {
8
+ return;
9
+ }
10
+ console.info(...params);
11
+ }
12
+ let shouldLogAuth = true;
13
+ /**
14
+ * Set to `false` to disable logging.
15
+ *
16
+ * @category Internal
17
+ */
18
+ export function setShouldLogAuth(value) {
19
+ shouldLogAuth = value;
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth-vir",
3
- "version": "2.6.0",
3
+ "version": "2.7.1",
4
4
  "description": "Auth made easy and secure via JWT cookies, CSRF tokens, and password hashing helpers.",
5
5
  "keywords": [
6
6
  "auth",
@@ -26,6 +26,7 @@ import {AuthCookieName, type CookieParams} from '../cookie.js';
26
26
  import {AuthHeaderName, mergeHeaderValues} from '../headers.js';
27
27
  import {generateNewJwtKeys, parseJwtKeys, type JwtKeys, type RawJwtKeys} from '../jwt/jwt-keys.js';
28
28
  import {type CreateJwtParams} from '../jwt/jwt.js';
29
+ import {authLog} from '../log.js';
29
30
 
30
31
  /**
31
32
  * Output from `BackendAuthClient.getSecureUser()`.
@@ -260,6 +261,10 @@ export class BackendAuthClient<
260
261
  });
261
262
 
262
263
  if (isExpiredAlready) {
264
+ authLog('auth-vir: SESSION EXPIRED - JWT already expired, user will be logged out', {
265
+ userId: userIdResult.userId,
266
+ jwtExpiration: userIdResult.jwtExpiration,
267
+ });
263
268
  return undefined;
264
269
  }
265
270
 
@@ -277,6 +282,14 @@ export class BackendAuthClient<
277
282
  });
278
283
 
279
284
  if (isSessionExpired) {
285
+ authLog(
286
+ 'auth-vir: SESSION EXPIRED - max session duration exceeded, user will be logged out',
287
+ {
288
+ userId: userIdResult.userId,
289
+ sessionStartedAt: userIdResult.sessionStartedAt,
290
+ maxSessionDuration,
291
+ },
292
+ );
280
293
  return undefined;
281
294
  }
282
295
  }
@@ -375,6 +388,7 @@ export class BackendAuthClient<
375
388
  this.config.overrides,
376
389
  );
377
390
  if (!userIdResult) {
391
+ authLog('auth-vir: getSecureUser failed - could not extract user from request');
378
392
  return undefined;
379
393
  }
380
394
 
@@ -385,6 +399,9 @@ export class BackendAuthClient<
385
399
  });
386
400
 
387
401
  if (!user) {
402
+ authLog('auth-vir: getSecureUser failed - user not found in database', {
403
+ userId: userIdResult.userId,
404
+ });
388
405
  return undefined;
389
406
  }
390
407
 
@@ -445,6 +462,14 @@ export class BackendAuthClient<
445
462
  'set-cookie': string[];
446
463
  }
447
464
  > {
465
+ authLog(
466
+ 'auth-vir: LOGOUT - BackendAuthClient.createLogoutHeaders called',
467
+ {
468
+ allCookies: 'allCookies' in params ? params.allCookies : undefined,
469
+ isSignUpCookie: 'isSignUpCookie' in params ? params.isSignUpCookie : undefined,
470
+ },
471
+ new Error().stack,
472
+ );
448
473
  const signUpCookieHeaders =
449
474
  params.allCookies || params.isSignUpCookie
450
475
  ? (generateLogoutHeaders(
@@ -601,6 +626,7 @@ export class BackendAuthClient<
601
626
  );
602
627
 
603
628
  if (!userIdResult) {
629
+ authLog('auth-vir: getInsecureUser failed - could not extract user from request');
604
630
  return undefined;
605
631
  }
606
632
 
@@ -611,6 +637,9 @@ export class BackendAuthClient<
611
637
  });
612
638
 
613
639
  if (!user) {
640
+ authLog('auth-vir: getInsecureUser failed - user not found in database', {
641
+ userId: userIdResult.userId,
642
+ });
614
643
  return undefined;
615
644
  }
616
645
 
@@ -17,6 +17,7 @@ import {
17
17
  wipeCurrentCsrfToken,
18
18
  } from '../csrf-token.js';
19
19
  import {AuthHeaderName} from '../headers.js';
20
+ import {authLog} from '../log.js';
20
21
 
21
22
  /**
22
23
  * Config for {@link FrontendAuthClient}.
@@ -119,6 +120,9 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
119
120
  csrfTokenResult.failure &&
120
121
  csrfTokenResult.failure !== CsrfTokenFailureReason.DoesNotExist
121
122
  ) {
123
+ authLog('auth-vir: LOGOUT - getCurrentCsrfToken: invalid CSRF token', {
124
+ failure: csrfTokenResult.failure,
125
+ });
122
126
  await this.logout();
123
127
  return undefined;
124
128
  } else {
@@ -200,6 +204,7 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
200
204
 
201
205
  /** Wipes the current user auth. */
202
206
  public async logout() {
207
+ authLog('auth-vir: LOGOUT - FrontendAuthClient.logout called', new Error().stack);
203
208
  await this.config.authClearedCallback?.();
204
209
  wipeCurrentCsrfToken(this.config.overrides);
205
210
  }
@@ -222,6 +227,7 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
222
227
  >,
223
228
  ): Promise<void> {
224
229
  if (!response.ok) {
230
+ authLog('auth-vir: LOGOUT - handleLoginResponse: response not ok');
225
231
  await this.logout();
226
232
  throw new Error('Login response failed.');
227
233
  }
@@ -229,6 +235,7 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
229
235
  const {csrfToken} = extractCsrfTokenHeader(response, this.config.overrides);
230
236
 
231
237
  if (!csrfToken) {
238
+ authLog('auth-vir: LOGOUT - handleLoginResponse: no CSRF token in response');
232
239
  await this.logout();
233
240
  throw new Error('Did not receive any CSRF token.');
234
241
  }
@@ -259,6 +266,9 @@ export class FrontendAuthClient<AssumedUserParams extends JsonCompatibleObject =
259
266
  response.status === HttpStatus.Unauthorized &&
260
267
  !response.headers?.get(AuthHeaderName.IsSignUpAuth)
261
268
  ) {
269
+ authLog('auth-vir: LOGOUT - verifyResponseAuth: unauthorized response (401)', {
270
+ status: response.status,
271
+ });
262
272
  await this.logout();
263
273
  return false;
264
274
  }
package/src/auth.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  import {AuthHeaderName} from './headers.js';
18
18
  import {type ParseJwtParams} from './jwt/jwt.js';
19
19
  import {type JwtUserData} from './jwt/user-jwt.js';
20
+ import {authLog} from './log.js';
20
21
 
21
22
  /**
22
23
  * All possible headers container types supported by {@link extractUserIdFromRequestHeaders}.
@@ -93,12 +94,28 @@ export async function extractUserIdFromRequestHeaders<UserId extends string | nu
93
94
  const cookie = readHeader(headers, 'cookie');
94
95
 
95
96
  if (!cookie || !csrfToken) {
97
+ authLog(
98
+ 'auth-vir: extractUserIdFromRequestHeaders failed - missing cookie or CSRF token',
99
+ {
100
+ hasCookie: !!cookie,
101
+ hasCsrfToken: !!csrfToken,
102
+ cookieName,
103
+ },
104
+ );
96
105
  return undefined;
97
106
  }
98
107
 
99
108
  const jwt = await extractCookieJwt(cookie, jwtParams, cookieName);
100
109
 
101
110
  if (!jwt || jwt.data.csrfToken !== csrfToken) {
111
+ authLog(
112
+ 'auth-vir: extractUserIdFromRequestHeaders failed - JWT invalid or CSRF mismatch',
113
+ {
114
+ hasJwt: !!jwt,
115
+ csrfMatch: jwt ? jwt.data.csrfToken === csrfToken : false,
116
+ cookieName,
117
+ },
118
+ );
102
119
  return undefined;
103
120
  }
104
121
 
@@ -108,7 +125,8 @@ export async function extractUserIdFromRequestHeaders<UserId extends string | nu
108
125
  cookieName,
109
126
  sessionStartedAt: jwt.data.sessionStartedAt,
110
127
  };
111
- } catch {
128
+ } catch (error) {
129
+ authLog('auth-vir: extractUserIdFromRequestHeaders error', {error, cookieName});
112
130
  return undefined;
113
131
  }
114
132
  }
@@ -130,12 +148,16 @@ export async function insecureExtractUserIdFromCookieAlone<UserId extends string
130
148
  const cookie = readHeader(headers, 'cookie');
131
149
 
132
150
  if (!cookie) {
151
+ authLog('auth-vir: insecureExtractUserIdFromCookieAlone failed - no cookie');
133
152
  return undefined;
134
153
  }
135
154
 
136
155
  const jwt = await extractCookieJwt(cookie, jwtParams, cookieName);
137
156
 
138
157
  if (!jwt) {
158
+ authLog(
159
+ 'auth-vir: insecureExtractUserIdFromCookieAlone failed - JWT extraction failed',
160
+ );
139
161
  return undefined;
140
162
  }
141
163
 
@@ -145,7 +167,8 @@ export async function insecureExtractUserIdFromCookieAlone<UserId extends string
145
167
  cookieName,
146
168
  sessionStartedAt: jwt.data.sessionStartedAt,
147
169
  };
148
- } catch {
170
+ } catch (error) {
171
+ authLog('auth-vir: insecureExtractUserIdFromCookieAlone error', {error});
149
172
  return undefined;
150
173
  }
151
174
  }
@@ -206,6 +229,13 @@ export function generateLogoutHeaders<CsrfHeaderName extends string = AuthHeader
206
229
  ): {
207
230
  'set-cookie': string;
208
231
  } & Record<CsrfHeaderName, string> {
232
+ authLog(
233
+ 'auth-vir: LOGOUT - generateLogoutHeaders called',
234
+ {
235
+ cookieName: cookieConfig.cookieName,
236
+ },
237
+ new Error().stack,
238
+ );
209
239
  const csrfHeaderName = (overrides.csrfHeaderName || AuthHeaderName.CsrfToken) as CsrfHeaderName;
210
240
 
211
241
  return {
@@ -239,6 +269,7 @@ export function handleAuthResponse(
239
269
  }> = {},
240
270
  ) {
241
271
  if (!response.ok) {
272
+ authLog('auth-vir: LOGOUT - handleAuthResponse: response not ok, wiping CSRF token');
242
273
  wipeCurrentCsrfToken(overrides);
243
274
  return;
244
275
  }
@@ -246,9 +277,11 @@ export function handleAuthResponse(
246
277
  const {csrfToken} = extractCsrfTokenHeader(response, overrides);
247
278
 
248
279
  if (!csrfToken) {
280
+ authLog('auth-vir: LOGOUT - handleAuthResponse: no CSRF token in response, wiping');
249
281
  wipeCurrentCsrfToken(overrides);
250
282
  throw new Error('Did not receive any CSRF token.');
251
283
  }
252
284
 
285
+ authLog('auth-vir: handleAuthResponse - successfully stored CSRF token');
253
286
  storeCsrfToken(csrfToken, overrides);
254
287
  }
package/src/csrf-token.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  import {defineShape, parseJsonWithShape} from 'object-shape-tester';
15
15
  import {type RequireExactlyOne} from 'type-fest';
16
16
  import {AuthHeaderName} from './headers.js';
17
+ import {authLog} from './log.js';
17
18
 
18
19
  /**
19
20
  * Shape definition for {@link CsrfToken}.
@@ -137,6 +138,7 @@ export function parseCsrfToken(value: string | undefined | null): Readonly<GetCs
137
138
  );
138
139
 
139
140
  if (!csrfToken) {
141
+ authLog('auth-vir: CSRF token parse failed - will cause logout if used');
140
142
  return {
141
143
  failure: CsrfTokenFailureReason.ParseFailed,
142
144
  };
@@ -148,6 +150,9 @@ export function parseCsrfToken(value: string | undefined | null): Readonly<GetCs
148
150
  relativeTo: csrfToken.expiration,
149
151
  })
150
152
  ) {
153
+ authLog('auth-vir: CSRF token expired - will cause logout', {
154
+ expiration: csrfToken.expiration,
155
+ });
151
156
  return {
152
157
  failure: CsrfTokenFailureReason.Expired,
153
158
  };
@@ -202,6 +207,7 @@ export function wipeCurrentCsrfToken(
202
207
  csrfHeaderName: string;
203
208
  }> = {},
204
209
  ) {
210
+ authLog('auth-vir: wipeCurrentCsrfToken called', new Error().stack);
205
211
  return (overrides.localStorage || globalThis.localStorage).removeItem(
206
212
  overrides.csrfHeaderName || AuthHeaderName.CsrfToken,
207
213
  );
package/src/index.ts CHANGED
@@ -8,4 +8,5 @@ export * from './headers.js';
8
8
  export * from './jwt/jwt-keys.js';
9
9
  export * from './jwt/jwt.js';
10
10
  export * from './jwt/user-jwt.js';
11
+ export * from './log.js';
11
12
  export * from './mock-local-storage.js';
package/src/log.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Send logs to the console for debugging.
3
+ *
4
+ * @category Internal
5
+ */
6
+ export function authLog(...params: any[]) {
7
+ if (!shouldLogAuth) {
8
+ return;
9
+ }
10
+ console.info(...params);
11
+ }
12
+
13
+ let shouldLogAuth = true;
14
+
15
+ /**
16
+ * Set to `false` to disable logging.
17
+ *
18
+ * @category Internal
19
+ */
20
+ export function setShouldLogAuth(value: boolean) {
21
+ shouldLogAuth = value;
22
+ }