@aura-stack/auth 0.4.0-rc.5 → 0.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.
Files changed (143) hide show
  1. package/dist/@types/index.d.ts +4 -3
  2. package/dist/@types/router.d.cjs +0 -17
  3. package/dist/@types/router.d.d.ts +3 -2
  4. package/dist/@types/router.d.js +0 -1
  5. package/dist/actions/callback/access-token.cjs +40 -25
  6. package/dist/actions/callback/access-token.d.ts +4 -3
  7. package/dist/actions/callback/access-token.js +3 -4
  8. package/dist/actions/callback/callback.cjs +287 -77
  9. package/dist/actions/callback/callback.d.ts +5 -26
  10. package/dist/actions/callback/callback.js +13 -10
  11. package/dist/actions/callback/userinfo.cjs +68 -7
  12. package/dist/actions/callback/userinfo.d.ts +4 -3
  13. package/dist/actions/callback/userinfo.js +8 -6
  14. package/dist/actions/csrfToken/csrfToken.cjs +63 -4
  15. package/dist/actions/csrfToken/csrfToken.d.ts +1 -3
  16. package/dist/actions/csrfToken/csrfToken.js +8 -6
  17. package/dist/actions/index.cjs +400 -175
  18. package/dist/actions/index.d.ts +3 -2
  19. package/dist/actions/index.js +21 -19
  20. package/dist/actions/session/session.cjs +40 -11
  21. package/dist/actions/session/session.d.ts +1 -3
  22. package/dist/actions/session/session.js +4 -4
  23. package/dist/actions/signIn/authorization.cjs +171 -132
  24. package/dist/actions/signIn/authorization.d.ts +21 -11
  25. package/dist/actions/signIn/authorization.js +8 -6
  26. package/dist/actions/signIn/signIn.cjs +220 -113
  27. package/dist/actions/signIn/signIn.d.ts +5 -25
  28. package/dist/actions/signIn/signIn.js +9 -7
  29. package/dist/actions/signOut/signOut.cjs +268 -119
  30. package/dist/actions/signOut/signOut.d.ts +1 -9
  31. package/dist/actions/signOut/signOut.js +10 -8
  32. package/dist/assert.cjs +117 -5
  33. package/dist/assert.d.ts +22 -3
  34. package/dist/assert.js +17 -3
  35. package/dist/chunk-4EKY7655.js +123 -0
  36. package/dist/chunk-4MYWAOLG.js +31 -0
  37. package/dist/chunk-4YHJ4IEQ.js +25 -0
  38. package/dist/chunk-54CZPKR4.js +25 -0
  39. package/dist/chunk-5LZ7TOM3.js +25 -0
  40. package/dist/{chunk-W6LG7BFW.js → chunk-5W4BRQYG.js} +24 -20
  41. package/dist/chunk-6MXFPFR3.js +143 -0
  42. package/dist/{chunk-3EUWD5BB.js → chunk-7QF22LHP.js} +13 -9
  43. package/dist/chunk-ALG3GIV4.js +95 -0
  44. package/dist/chunk-E6G5YCI6.js +25 -0
  45. package/dist/chunk-EBAMFRB7.js +34 -0
  46. package/dist/chunk-EEE7UM5T.js +25 -0
  47. package/dist/{chunk-TLE4PXY3.js → chunk-FRJFWTOY.js} +38 -7
  48. package/dist/chunk-FW4W3REU.js +25 -0
  49. package/dist/{chunk-HT4YLL7N.js → chunk-ICAZ4OVS.js} +10 -8
  50. package/dist/chunk-IPKO6UQN.js +25 -0
  51. package/dist/{chunk-YRCB5FLE.js → chunk-KJBAQZX2.js} +13 -0
  52. package/dist/chunk-KMMAZFSJ.js +25 -0
  53. package/dist/chunk-LDU7A2JE.js +25 -0
  54. package/dist/{chunk-N2APGLXA.js → chunk-NUDITUKX.js} +18 -16
  55. package/dist/chunk-OVHNRULD.js +33 -0
  56. package/dist/{chunk-JVFTCTTE.js → chunk-PHFH2MGS.js} +12 -9
  57. package/dist/chunk-QQVSRXGX.js +149 -0
  58. package/dist/chunk-TM5IPSNF.js +113 -0
  59. package/dist/{chunk-GA2SMTJO.js → chunk-TZB6MUXN.js} +33 -13
  60. package/dist/chunk-VNCNJKS2.js +267 -0
  61. package/dist/{chunk-IVET23KF.js → chunk-XGLBNXL4.js} +31 -14
  62. package/dist/chunk-XUP6KKNG.js +106 -0
  63. package/dist/cookie.cjs +24 -20
  64. package/dist/cookie.d.ts +4 -3
  65. package/dist/cookie.js +1 -1
  66. package/dist/env.cjs +56 -0
  67. package/dist/env.d.ts +7 -0
  68. package/dist/env.js +6 -0
  69. package/dist/errors.d.ts +4 -3
  70. package/dist/headers.cjs +28 -2
  71. package/dist/headers.d.ts +25 -1
  72. package/dist/headers.js +9 -3
  73. package/dist/{index-B8jeIElf.d.ts → index-CSyIJmCM.d.ts} +373 -45
  74. package/dist/index.cjs +1128 -483
  75. package/dist/index.d.ts +7 -67
  76. package/dist/index.js +83 -42
  77. package/dist/jose.cjs +62 -25
  78. package/dist/jose.d.ts +7 -5
  79. package/dist/jose.js +8 -6
  80. package/dist/logger.cjs +292 -0
  81. package/dist/logger.d.ts +8 -0
  82. package/dist/logger.js +8 -0
  83. package/dist/oauth/bitbucket.cjs +19 -15
  84. package/dist/oauth/bitbucket.d.ts +3 -2
  85. package/dist/oauth/bitbucket.js +1 -1
  86. package/dist/oauth/discord.cjs +27 -24
  87. package/dist/oauth/discord.d.ts +3 -2
  88. package/dist/oauth/discord.js +1 -1
  89. package/dist/oauth/figma.cjs +19 -16
  90. package/dist/oauth/figma.d.ts +3 -2
  91. package/dist/oauth/figma.js +1 -1
  92. package/dist/oauth/github.cjs +19 -8
  93. package/dist/oauth/github.d.ts +3 -2
  94. package/dist/oauth/github.js +1 -1
  95. package/dist/oauth/gitlab.cjs +19 -16
  96. package/dist/oauth/gitlab.d.ts +3 -2
  97. package/dist/oauth/gitlab.js +1 -1
  98. package/dist/oauth/index.cjs +266 -166
  99. package/dist/oauth/index.d.ts +3 -2
  100. package/dist/oauth/index.js +22 -21
  101. package/dist/oauth/mailchimp.cjs +19 -16
  102. package/dist/oauth/mailchimp.d.ts +3 -2
  103. package/dist/oauth/mailchimp.js +1 -1
  104. package/dist/oauth/pinterest.cjs +19 -16
  105. package/dist/oauth/pinterest.d.ts +3 -2
  106. package/dist/oauth/pinterest.js +1 -1
  107. package/dist/oauth/spotify.cjs +19 -16
  108. package/dist/oauth/spotify.d.ts +3 -2
  109. package/dist/oauth/spotify.js +1 -1
  110. package/dist/oauth/strava.cjs +19 -16
  111. package/dist/oauth/strava.d.ts +3 -2
  112. package/dist/oauth/strava.js +1 -1
  113. package/dist/oauth/x.cjs +19 -16
  114. package/dist/oauth/x.d.ts +3 -2
  115. package/dist/oauth/x.js +1 -1
  116. package/dist/schemas.cjs +16 -2
  117. package/dist/schemas.d.ts +17 -1
  118. package/dist/schemas.js +5 -3
  119. package/dist/secure.cjs +58 -16
  120. package/dist/secure.d.ts +4 -10
  121. package/dist/secure.js +5 -5
  122. package/dist/utils.cjs +94 -87
  123. package/dist/utils.d.ts +9 -39
  124. package/dist/utils.js +11 -9
  125. package/package.json +3 -4
  126. package/dist/chunk-42XB3YCW.js +0 -22
  127. package/dist/chunk-6R2YZ4AC.js +0 -22
  128. package/dist/chunk-A3N4PVAT.js +0 -70
  129. package/dist/chunk-B737EUJV.js +0 -22
  130. package/dist/chunk-CXLATHS5.js +0 -143
  131. package/dist/chunk-DIVDFNAP.js +0 -0
  132. package/dist/chunk-E3OXBRYF.js +0 -22
  133. package/dist/chunk-EIL2FPSS.js +0 -22
  134. package/dist/chunk-EMKJA2GJ.js +0 -89
  135. package/dist/chunk-FIPU4MLT.js +0 -21
  136. package/dist/chunk-FKRDCWBF.js +0 -22
  137. package/dist/chunk-HP34YGGJ.js +0 -22
  138. package/dist/chunk-IKHPGFCW.js +0 -14
  139. package/dist/chunk-IUYZQTJV.js +0 -30
  140. package/dist/chunk-KRNOMBXQ.js +0 -22
  141. package/dist/chunk-KSWLO5ZU.js +0 -102
  142. package/dist/chunk-N4SX7TZT.js +0 -96
  143. package/dist/chunk-STHEPPUZ.js +0 -11
@@ -49,9 +49,29 @@ var cacheControl = {
49
49
  Expires: "0",
50
50
  Vary: "Cookie"
51
51
  };
52
+ var contentSecurityPolicy = {
53
+ "Content-Security-Policy": [
54
+ "default-src 'none'",
55
+ "script-src 'self'",
56
+ "frame-src 'none'",
57
+ "object-src 'none'",
58
+ "frame-ancestors 'none'",
59
+ "base-uri 'none'"
60
+ ].join("; ")
61
+ };
62
+ var secureHeaders = {
63
+ "X-Content-Type-Options": "nosniff",
64
+ "X-Frame-Options": "DENY",
65
+ "Referrer-Policy": "strict-origin-when-cross-origin"
66
+ };
67
+ var secureApiHeaders = {
68
+ ...cacheControl,
69
+ ...contentSecurityPolicy,
70
+ ...secureHeaders
71
+ };
52
72
 
53
73
  // src/secure.ts
54
- var import_crypto = __toESM(require("crypto"), 1);
74
+ var import_crypto2 = __toESM(require("crypto"), 1);
55
75
 
56
76
  // src/utils.ts
57
77
  var import_router = require("@aura-stack/router");
@@ -95,9 +115,6 @@ var isNativeError = (error) => {
95
115
  var isOAuthProtocolError = (error) => {
96
116
  return error instanceof OAuthProtocolError;
97
117
  };
98
- var isAuthSecurityError = (error) => {
99
- return error instanceof AuthSecurityError;
100
- };
101
118
 
102
119
  // src/utils.ts
103
120
  var toSnakeCase = (str) => {
@@ -116,95 +133,175 @@ var equals = (a, b) => {
116
133
  if (a === null || b === null || a === void 0 || b === void 0) return false;
117
134
  return a === b;
118
135
  };
119
- var sanitizeURL = (url) => {
120
- try {
121
- let decodedURL = decodeURIComponent(url).trim();
122
- const protocolMatch = decodedURL.match(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)/);
123
- let protocol = "";
124
- let rest = decodedURL;
125
- if (protocolMatch) {
126
- protocol = protocolMatch[1];
127
- rest = decodedURL.slice(protocol.length);
128
- const slashIndex = rest.indexOf("/");
129
- if (slashIndex === -1) {
130
- return protocol + rest;
131
- }
132
- const domain = rest.slice(0, slashIndex);
133
- let path = rest.slice(slashIndex).replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
134
- if (path !== "/" && path.endsWith("/")) {
135
- path = path.replace(/\/+$/, "/");
136
- } else if (path !== "/") {
137
- path = path.replace(/\/+$/, "");
138
- }
139
- return protocol + domain + path;
140
- }
141
- let sanitized = decodedURL.replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
142
- if (sanitized !== "/" && sanitized.endsWith("/")) {
143
- sanitized = sanitized.replace(/\/+$/, "/");
144
- } else if (sanitized !== "/") {
145
- sanitized = sanitized.replace(/\/+$/, "");
146
- }
147
- return sanitized;
148
- } catch {
149
- return url.trim();
150
- }
151
- };
152
- var isValidRelativePath = (path) => {
153
- if (!path || typeof path !== "string") return false;
154
- if (!path.startsWith("/") || path.includes("://") || path.includes("\r") || path.includes("\n")) return false;
155
- if (/[\x00-\x1F\x7F]/.test(path) || path.includes("\0")) return false;
156
- const sanitized = sanitizeURL(path);
157
- if (sanitized.includes("..")) return false;
158
- return true;
159
- };
160
- var getNormalizedOriginPath = (path) => {
161
- try {
162
- const url = new URL(path);
163
- url.hash = "";
164
- url.search = "";
165
- return `${url.origin}${url.pathname}`;
166
- } catch {
167
- return sanitizeURL(path);
168
- }
136
+ var getBaseURL = (request) => {
137
+ const url = new URL(request.url);
138
+ return `${url.origin}${url.pathname}`;
169
139
  };
170
140
  var toISOString = (date) => {
171
141
  return new Date(date).toISOString();
172
142
  };
173
- var formatZodError = (error) => {
174
- if (!error.issues || error.issues.length === 0) {
175
- return {};
143
+ var extractPath = (url) => {
144
+ const pathRegex = /^https?:\/\/[a-zA-Z0-9_\-\.]+(:\d+)?(\/.*)$/;
145
+ const match = url.match(pathRegex);
146
+ return match && match[2] ? match[2] : "/";
147
+ };
148
+ var getErrorName = (error) => {
149
+ if (error instanceof Error) {
150
+ return error.name;
176
151
  }
177
- return error.issues.reduce((previous, issue) => {
178
- const key = issue.path.join(".");
179
- return {
180
- ...previous,
181
- [key]: {
182
- code: issue.code,
183
- message: issue.message
184
- }
185
- };
186
- }, {});
152
+ return typeof error === "string" ? error : "UnknownError";
187
153
  };
188
154
 
189
155
  // src/assert.ts
156
+ var import_crypto = require("crypto");
157
+ var unsafeChars = [
158
+ "<",
159
+ ">",
160
+ '"',
161
+ "`",
162
+ " ",
163
+ "\r",
164
+ "\n",
165
+ " ",
166
+ "\\",
167
+ "%2F",
168
+ "%5C",
169
+ "%2f",
170
+ "%5c",
171
+ "\r\n",
172
+ "%0A",
173
+ "%0D",
174
+ "%0a",
175
+ "%0d",
176
+ "..",
177
+ "//",
178
+ "///",
179
+ "...",
180
+ "%20",
181
+ "\0"
182
+ ];
190
183
  var isValidURL = (value) => {
191
- if (value.includes("\r\n") || value.includes("\n") || value.includes("\r")) return false;
192
- const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()*+,;=:@-]*)*\/?$/;
193
- return regex.test(value);
184
+ if (!new RegExp(/^https?:\/\/[^/]/).test(value)) {
185
+ return false;
186
+ }
187
+ const match = value.match(/^(https?:\/\/)(.*)$/);
188
+ if (!match) return false;
189
+ const rest = match[2];
190
+ for (const char of unsafeChars) {
191
+ if (rest.includes(char)) return false;
192
+ }
193
+ const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()?#*+,;=:@-]*)*\/?$/;
194
+ return regex.test(match[0]);
194
195
  };
195
196
  var isJWTPayloadWithToken = (payload) => {
196
197
  return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
197
198
  };
199
+ var isRelativeURL = (value) => {
200
+ if (value.length > 100) return false;
201
+ for (const char of unsafeChars) {
202
+ if (value.includes(char)) return false;
203
+ }
204
+ const regex = /^\/[a-zA-Z0-9\-_\/.?&=#]*\/?$/;
205
+ return regex.test(value);
206
+ };
207
+ var isSameOrigin = (origin, expected) => {
208
+ const originURL = new URL(origin);
209
+ const expectedURL = new URL(expected);
210
+ return equals(originURL.origin, expectedURL.origin);
211
+ };
212
+ var patternToRegex = (pattern) => {
213
+ try {
214
+ if (pattern.length > 2048) return null;
215
+ pattern = pattern.replace(/\\/g, "");
216
+ const match = pattern.match(/^(https?):\/\/([a-zA-Z0-9.*-]{1,253})(?::(\d{1,5}|\*))?(?:\/.*)?$/);
217
+ if (!match) return null;
218
+ const [, protocol, host, port] = match;
219
+ const hasWildcard = host.includes("*");
220
+ if (hasWildcard && !host.startsWith("*.")) return null;
221
+ if (hasWildcard && host.slice(2).includes("*")) return null;
222
+ const domain = hasWildcard ? host.slice(2) : host;
223
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
224
+ const hostRegex = hasWildcard ? `[^.]+\\.${escapedDomain}` : escapedDomain;
225
+ const portRegex = port === "*" ? ":\\d{1,5}" : port ? `:${port}` : "";
226
+ return new RegExp(`^${protocol}:\\/\\/${hostRegex}${portRegex}$`);
227
+ } catch {
228
+ return null;
229
+ }
230
+ };
231
+ var isTrustedOrigin = (url, trustedOrigins) => {
232
+ if (!isValidURL(url) || trustedOrigins.length === 0) return false;
233
+ try {
234
+ const urlOrigin = new URL(url).origin;
235
+ for (const pattern of trustedOrigins) {
236
+ const regex = patternToRegex(pattern);
237
+ if (regex?.test(urlOrigin)) return true;
238
+ try {
239
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return true;
240
+ } catch {
241
+ }
242
+ }
243
+ } catch {
244
+ }
245
+ return false;
246
+ };
247
+ var safeEquals = (a, b) => {
248
+ const bufferA = Buffer.from(a);
249
+ const bufferB = Buffer.from(b);
250
+ if (bufferA.length !== bufferB.length) {
251
+ return false;
252
+ }
253
+ return (0, import_crypto.timingSafeEqual)(bufferA, bufferB);
254
+ };
255
+
256
+ // src/env.ts
257
+ var import_meta = {};
258
+ var env = new Proxy({}, {
259
+ get(_, prop) {
260
+ if (typeof prop !== "string") return void 0;
261
+ const hasProperty = (process2) => {
262
+ return process2 && Object.prototype.hasOwnProperty.call(process2, prop);
263
+ };
264
+ try {
265
+ if (typeof process !== "undefined" && hasProperty(process.env)) {
266
+ return process.env[prop];
267
+ }
268
+ if (typeof import_meta !== "undefined" && hasProperty(import_meta.env)) {
269
+ return import_meta.env[prop];
270
+ }
271
+ if (typeof Deno !== "undefined" && Deno.env?.get) {
272
+ return Deno.env.get(prop);
273
+ }
274
+ if (typeof Bun !== "undefined" && hasProperty(Bun.env)) {
275
+ return Bun.env[prop];
276
+ }
277
+ const globalValue = globalThis[prop];
278
+ return typeof globalValue === "string" ? globalValue : void 0;
279
+ } catch {
280
+ return void 0;
281
+ }
282
+ }
283
+ });
284
+
285
+ // src/jose.ts
286
+ var import_jose = require("@aura-stack/jose");
287
+ var jwtVerificationOptions = {
288
+ algorithms: ["HS256"],
289
+ typ: "JWT"
290
+ };
198
291
 
199
292
  // src/secure.ts
200
293
  var generateSecure = (length = 32) => {
201
- return import_crypto.default.randomBytes(length).toString("base64url");
294
+ return import_crypto2.default.randomBytes(length).toString("base64url");
202
295
  };
203
296
  var createHash = (data, base = "hex") => {
204
- return import_crypto.default.createHash("sha256").update(data).digest().toString(base);
297
+ return import_crypto2.default.createHash("sha256").update(data).digest().toString(base);
205
298
  };
206
299
  var createPKCE = async (verifier) => {
207
- const codeVerifier = verifier ?? generateSecure(86);
300
+ const byteLength = verifier ? void 0 : Math.floor(Math.random() * (96 - 32 + 1) + 32);
301
+ const codeVerifier = verifier ?? generateSecure(byteLength ?? 64);
302
+ if (codeVerifier.length < 43 || codeVerifier.length > 128) {
303
+ throw new AuthSecurityError("PKCE_VERIFIER_INVALID", "The code verifier must be between 43 and 128 characters in length.");
304
+ }
208
305
  const codeChallenge = createHash(codeVerifier, "base64url");
209
306
  return { codeVerifier, codeChallenge, method: "S256" };
210
307
  };
@@ -212,7 +309,7 @@ var createCSRF = async (jose, csrfCookie) => {
212
309
  try {
213
310
  const token = generateSecure(32);
214
311
  if (csrfCookie) {
215
- await jose.verifyJWS(csrfCookie);
312
+ await jose.verifyJWS(csrfCookie, jwtVerificationOptions);
216
313
  return csrfCookie;
217
314
  }
218
315
  return jose.signJWS({ token });
@@ -223,20 +320,18 @@ var createCSRF = async (jose, csrfCookie) => {
223
320
  };
224
321
  var verifyCSRF = async (jose, cookie, header) => {
225
322
  try {
226
- const cookiePayload = await jose.verifyJWS(cookie);
227
- const headerPayload = await jose.verifyJWS(header);
323
+ const cookiePayload = await jose.verifyJWS(cookie, jwtVerificationOptions);
324
+ const headerPayload = await jose.verifyJWS(header, jwtVerificationOptions);
228
325
  if (!isJWTPayloadWithToken(cookiePayload)) {
229
326
  throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Cookie payload missing token field.");
230
327
  }
231
328
  if (!isJWTPayloadWithToken(headerPayload)) {
232
329
  throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Header payload missing token field.");
233
330
  }
234
- const cookieBuffer = Buffer.from(cookiePayload.token);
235
- const headerBuffer = Buffer.from(headerPayload.token);
236
- if (!equals(headerBuffer.length, cookieBuffer.length)) {
331
+ if (!equals(cookiePayload.token.length, headerPayload.token.length)) {
237
332
  throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
238
333
  }
239
- if (!import_crypto.default.timingSafeEqual(cookieBuffer, headerBuffer)) {
334
+ if (!safeEquals(cookiePayload.token, headerPayload.token)) {
240
335
  throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
241
336
  }
242
337
  return true;
@@ -247,6 +342,18 @@ var verifyCSRF = async (jose, cookie, header) => {
247
342
 
248
343
  // src/schemas.ts
249
344
  var import_zod = require("zod");
345
+ var OAuthProviderCredentialsSchema = (0, import_zod.object)({
346
+ id: (0, import_zod.string)(),
347
+ name: (0, import_zod.string)(),
348
+ authorizeURL: (0, import_zod.string)().url(),
349
+ accessToken: (0, import_zod.string)().url(),
350
+ scope: (0, import_zod.string)(),
351
+ userInfo: (0, import_zod.string)().url(),
352
+ responseType: (0, import_zod.enum)(["code", "token", "id_token"]),
353
+ clientId: (0, import_zod.string)(),
354
+ clientSecret: (0, import_zod.string)(),
355
+ profile: import_zod.z.function().optional()
356
+ });
250
357
  var OAuthProviderConfigSchema = (0, import_zod.object)({
251
358
  authorizeURL: (0, import_zod.string)().url(),
252
359
  accessToken: (0, import_zod.string)().url(),
@@ -314,73 +421,82 @@ var OAuthEnvSchema = (0, import_zod.object)({
314
421
  });
315
422
 
316
423
  // src/actions/signIn/authorization.ts
317
- var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod) => {
424
+ var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod, logger) => {
318
425
  const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
319
426
  if (!parsed.success) {
320
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
321
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
427
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
428
+ structuredData: {
429
+ scope: oauthConfig.scope,
430
+ redirect_uri: redirectURI,
431
+ has_state: Boolean(state),
432
+ has_code_challenge: Boolean(codeChallenge),
433
+ code_challenge_method: codeChallengeMethod
434
+ }
435
+ });
436
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
322
437
  }
323
438
  const { authorizeURL, ...options2 } = parsed.data;
324
439
  const { userInfo, accessToken, clientSecret, ...required } = options2;
325
440
  const searchParams = new URLSearchParams(toCastCase(required));
326
441
  return `${authorizeURL}?${searchParams}`;
327
442
  };
328
- var getOriginURL = (request, trustedProxyHeaders) => {
443
+ var getTrustedOrigins = async (request, trustedOrigins) => {
444
+ if (!trustedOrigins) return [];
445
+ const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins;
446
+ return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
447
+ };
448
+ var getOriginURL = async (request, context) => {
329
449
  const headers = request.headers;
330
- if (trustedProxyHeaders) {
331
- const protocol = headers.get("X-Forwarded-Proto") ?? headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? "http";
332
- const host = headers.get("X-Forwarded-Host") ?? headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? null;
333
- return new URL(`${protocol}://${host}${getNormalizedOriginPath(new URL(request.url).pathname)}`);
334
- } else {
335
- return new URL(getNormalizedOriginPath(request.url));
450
+ let origin = new URL(request.url).origin;
451
+ const trustedOrigins = await getTrustedOrigins(request, context?.trustedOrigins);
452
+ trustedOrigins.push(origin);
453
+ if (context?.trustedProxyHeaders) {
454
+ const protocol = headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Proto") ?? "http";
455
+ const host = headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Host") ?? null;
456
+ origin = `${protocol}://${host}`;
457
+ }
458
+ if (!isTrustedOrigin(origin, trustedOrigins)) {
459
+ context?.logger?.log("UNTRUSTED_ORIGIN", { structuredData: { origin } });
460
+ throw new AuthInternalError("UNTRUSTED_ORIGIN", "The constructed origin URL is not trusted.");
336
461
  }
462
+ return origin;
337
463
  };
338
- var createRedirectURI = (request, oauth, basePath, trustedProxyHeaders) => {
339
- const url = getOriginURL(request, trustedProxyHeaders);
340
- return `${url.origin}${basePath}/callback/${oauth}`;
464
+ var createRedirectURI = async (request, oauth, context) => {
465
+ const origin = await getOriginURL(request, context);
466
+ return `${origin}${context.basePath}/callback/${oauth}`;
341
467
  };
342
- var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
468
+ var createRedirectTo = async (request, redirectTo, context) => {
343
469
  try {
344
470
  const headers = request.headers;
345
- const origin = headers.get("Origin");
346
- const referer = headers.get("Referer");
347
- let hostedURL = getOriginURL(request, trustedProxyHeaders);
348
- if (redirectTo) {
349
- if (redirectTo.startsWith("/")) {
350
- return sanitizeURL(redirectTo);
351
- }
352
- const redirectToURL = new URL(sanitizeURL(getNormalizedOriginPath(redirectTo)));
353
- if (!isValidURL(redirectTo) || !equals(redirectToURL.origin, hostedURL.origin)) {
354
- throw new AuthSecurityError(
355
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
356
- "The redirectTo parameter does not match the hosted origin."
357
- );
358
- }
359
- return sanitizeURL(redirectToURL.pathname);
360
- }
361
- if (referer) {
362
- const refererURL = new URL(sanitizeURL(referer));
363
- if (!isValidURL(referer) || !equals(refererURL.origin, hostedURL.origin)) {
364
- throw new AuthSecurityError(
365
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
366
- "The referer of the request does not match the hosted origin."
367
- );
471
+ const requestOrigin = await getOriginURL(request, context);
472
+ const origins = await getTrustedOrigins(request, context?.trustedOrigins);
473
+ const validateURL = (url) => {
474
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
475
+ if (isRelativeURL(url)) return url;
476
+ if (origins.length > 0) {
477
+ if (isTrustedOrigin(url, origins)) {
478
+ const urlOrigin = new URL(url).origin;
479
+ for (const pattern of origins) {
480
+ const regex = patternToRegex(pattern);
481
+ if (regex?.test(urlOrigin)) {
482
+ return isSameOrigin(url, request.url) ? extractPath(url) : url;
483
+ }
484
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return url;
485
+ }
486
+ }
487
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
488
+ return "/";
368
489
  }
369
- return sanitizeURL(refererURL.pathname);
370
- }
371
- if (origin) {
372
- const originURL = new URL(sanitizeURL(getNormalizedOriginPath(origin)));
373
- if (!isValidURL(origin) || !equals(originURL.origin, hostedURL.origin)) {
374
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
490
+ if (isSameOrigin(url, requestOrigin)) {
491
+ return extractPath(url);
375
492
  }
376
- return sanitizeURL(originURL.pathname);
377
- }
378
- return "/";
493
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
494
+ return "/";
495
+ };
496
+ return validateURL(redirectTo ?? headers.get("Referer") ?? headers.get("Origin") ?? "/");
379
497
  } catch (error) {
380
- if (isAuthSecurityError(error)) {
381
- throw error;
382
- }
383
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
498
+ context?.logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED");
499
+ return "/";
384
500
  }
385
501
  };
386
502
 
@@ -409,13 +525,17 @@ var signInAction = (oauth) => {
409
525
  request,
410
526
  params: { oauth: oauth2 },
411
527
  searchParams: { redirectTo },
412
- context: { oauth: providers, cookies, trustedProxyHeaders, basePath }
528
+ context
413
529
  } = ctx;
530
+ const { oauth: providers, cookies, logger } = context;
414
531
  const state = generateSecure();
415
- const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
416
- const redirectToValue = createRedirectTo(request, redirectTo, trustedProxyHeaders);
532
+ const redirectURI = await createRedirectURI(request, oauth2, context);
533
+ const redirectToValue = await createRedirectTo(request, redirectTo, context);
417
534
  const { codeVerifier, codeChallenge, method } = await createPKCE();
418
- const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
535
+ const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method, logger);
536
+ logger?.log("SIGN_IN_INITIATED", {
537
+ structuredData: { oauth_provider: oauth2, code_challenge_method: method }
538
+ });
419
539
  const headers = new import_router2.HeadersBuilder(cacheControl).setHeader("Location", authorization).setCookie(cookies.state.name, state, cookies.state.attributes).setCookie(cookies.redirectURI.name, redirectURI, cookies.redirectURI.attributes).setCookie(cookies.redirectTo.name, redirectToValue, cookies.redirectTo.attributes).setCookie(cookies.codeVerifier.name, codeVerifier, cookies.codeVerifier.attributes).toHeaders();
420
540
  return Response.json(
421
541
  { oauth: oauth2 },
@@ -454,9 +574,14 @@ var getDefaultUserInfo = (profile) => {
454
574
  image: profile?.image ?? profile?.picture
455
575
  };
456
576
  };
457
- var getUserInfo = async (oauthConfig, accessToken) => {
577
+ var getUserInfo = async (oauthConfig, accessToken, logger) => {
458
578
  const userinfoEndpoint = oauthConfig.userInfo;
459
579
  try {
580
+ logger?.log("OAUTH_USERINFO_REQUEST_INITIATED", {
581
+ structuredData: {
582
+ endpoint: userinfoEndpoint
583
+ }
584
+ });
460
585
  const response = await fetchAsync(userinfoEndpoint, {
461
586
  method: "GET",
462
587
  headers: {
@@ -464,35 +589,54 @@ var getUserInfo = async (oauthConfig, accessToken) => {
464
589
  Authorization: `Bearer ${accessToken}`
465
590
  }
466
591
  });
592
+ if (!response.ok) {
593
+ logger?.log("OAUTH_USERINFO_INVALID_RESPONSE");
594
+ throw new OAuthProtocolError("INVALID_REQUEST", "Invalid userinfo response format");
595
+ }
467
596
  const json = await response.json();
468
597
  const { success, data } = OAuthErrorResponse.safeParse(json);
469
598
  if (success) {
470
- throw new OAuthProtocolError(
471
- data.error,
472
- data?.error_description ?? "An error occurred while fetching user information."
473
- );
599
+ logger?.log("OAUTH_USERINFO_ERROR", {
600
+ message: "Error response received from OAuth userinfo endpoint",
601
+ structuredData: {
602
+ error: data.error,
603
+ error_description: data.error_description ?? ""
604
+ }
605
+ });
606
+ throw new OAuthProtocolError("INVALID_REQUEST", "An error was received from the OAuth userinfo endpoint.");
474
607
  }
608
+ logger?.log("OAUTH_USERINFO_SUCCESS");
475
609
  return oauthConfig?.profile ? oauthConfig.profile(json) : getDefaultUserInfo(json);
476
610
  } catch (error) {
477
611
  if (isOAuthProtocolError(error)) {
478
612
  throw error;
479
613
  }
614
+ logger?.log("OAUTH_USERINFO_REQUEST_FAILED");
480
615
  if (isNativeError(error)) {
481
- throw new OAuthProtocolError("invalid_request", error.message, "", { cause: error });
616
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information from OAuth provider", "", {
617
+ cause: error
618
+ });
482
619
  }
483
- throw new OAuthProtocolError("invalid_request", "Failed to fetch user information.", "", { cause: error });
620
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information", "", { cause: error });
484
621
  }
485
622
  };
486
623
 
487
624
  // src/actions/callback/access-token.ts
488
- var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) => {
625
+ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier, logger) => {
489
626
  const parsed = OAuthAccessToken.safeParse({ ...oauthConfig, redirectURI, code, codeVerifier });
490
627
  if (!parsed.success) {
491
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
492
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
628
+ logger?.log("INVALID_OAUTH_CONFIGURATION");
629
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
493
630
  }
494
631
  const { accessToken, clientId, clientSecret, code: codeParsed, redirectURI: redirectParsed } = parsed.data;
495
632
  try {
633
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_INITIATED", {
634
+ structuredData: {
635
+ has_client_id: Boolean(clientId),
636
+ redirect_uri: redirectParsed,
637
+ grant_type: "authorization_code"
638
+ }
639
+ });
496
640
  const response = await fetchAsync(accessToken, {
497
641
  method: "POST",
498
642
  headers: {
@@ -508,17 +652,33 @@ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) =>
508
652
  code_verifier: codeVerifier
509
653
  }).toString()
510
654
  });
655
+ if (!response.ok) {
656
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
657
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response");
658
+ }
511
659
  const json = await response.json();
512
660
  const token = OAuthAccessTokenResponse.safeParse(json);
513
661
  if (!token.success) {
514
662
  const { success, data } = OAuthAccessTokenErrorResponse.safeParse(json);
515
663
  if (!success) {
516
- throw new OAuthProtocolError("INVALID_REQUEST", "Invalid access token response format");
664
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
665
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response format");
517
666
  }
518
- throw new OAuthProtocolError(data.error, data?.error_description ?? "Failed to retrieve access token");
667
+ logger?.log("OAUTH_ACCESS_TOKEN_ERROR", {
668
+ structuredData: {
669
+ error: data.error,
670
+ error_description: data.error_description ?? ""
671
+ }
672
+ });
673
+ throw new OAuthProtocolError("INVALID_ACCESS_TOKEN", "Failed to retrieve access token");
519
674
  }
675
+ logger?.log("OAUTH_ACCESS_TOKEN_SUCCESS");
520
676
  return token.data;
521
677
  } catch (error) {
678
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_FAILED");
679
+ if (error instanceof Error) {
680
+ throw new OAuthProtocolError("server_error", "Failed to communicate with OAuth provider", "", { cause: error });
681
+ }
522
682
  throw error;
523
683
  }
524
684
  };
@@ -543,7 +703,8 @@ var setCookie = (cookieName, value, options2) => {
543
703
  var expiredCookieAttributes = {
544
704
  ...defaultCookieOptions,
545
705
  expires: /* @__PURE__ */ new Date(0),
546
- maxAge: 0
706
+ maxAge: 0,
707
+ secure: true
547
708
  };
548
709
  var getCookie = (request, cookieName) => {
549
710
  const cookies = request.headers.get("Cookie");
@@ -582,10 +743,23 @@ var callbackConfig = (oauth) => {
582
743
  },
583
744
  middlewares: [
584
745
  (ctx) => {
585
- const response = OAuthAuthorizationErrorResponse.safeParse(ctx.searchParams);
746
+ const {
747
+ searchParams,
748
+ context: { logger }
749
+ } = ctx;
750
+ const response = OAuthAuthorizationErrorResponse.safeParse(searchParams);
586
751
  if (response.success) {
587
752
  const { error, error_description } = response.data;
588
- throw new OAuthProtocolError(error, error_description ?? "OAuth Authorization Error");
753
+ const criticalAuthErrors = ["access_denied", "server_error"];
754
+ const severity = criticalAuthErrors.includes(error.toLowerCase()) ? "critical" : "warning";
755
+ logger?.log("OAUTH_AUTHORIZATION_ERROR", {
756
+ severity,
757
+ structuredData: {
758
+ error,
759
+ error_description: error_description ?? ""
760
+ }
761
+ });
762
+ throw new OAuthProtocolError(error, error_description || "OAuth Authorization Error");
589
763
  }
590
764
  return ctx;
591
765
  }
@@ -601,31 +775,54 @@ var callbackAction = (oauth) => {
601
775
  request,
602
776
  params: { oauth: oauth2 },
603
777
  searchParams: { code, state },
604
- context: { oauth: providers, cookies, jose }
778
+ context
605
779
  } = ctx;
780
+ const { oauth: providers, cookies, jose, logger, trustedOrigins } = context;
606
781
  const oauthConfig = providers[oauth2];
607
782
  const cookieState = getCookie(request, cookies.state.name);
783
+ const codeVerifier = getCookie(request, cookies.codeVerifier.name);
608
784
  const cookieRedirectTo = getCookie(request, cookies.redirectTo.name);
609
785
  const cookieRedirectURI = getCookie(request, cookies.redirectURI.name);
610
- const codeVerifier = getCookie(request, cookies.codeVerifier.name);
611
- if (!equals(cookieState, state)) {
786
+ if (!safeEquals(cookieState, state)) {
787
+ logger?.log("MISMATCHING_STATE", {
788
+ structuredData: {
789
+ oauth_provider: oauth2
790
+ }
791
+ });
612
792
  throw new AuthSecurityError(
613
793
  "MISMATCHING_STATE",
614
794
  "The provided state passed in the OAuth response does not match the stored state."
615
795
  );
616
796
  }
617
- const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier);
618
- const sanitized = sanitizeURL(cookieRedirectTo);
619
- if (!isValidRelativePath(sanitized)) {
620
- throw new AuthSecurityError(
621
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
622
- "Invalid redirect path. Potential open redirect attack detected."
623
- );
797
+ const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier, logger);
798
+ const origins = await getTrustedOrigins(request, trustedOrigins);
799
+ const requestOrigin = await getOriginURL(request, context);
800
+ if (!isRelativeURL(cookieRedirectTo)) {
801
+ const isValid = origins.length > 0 ? isTrustedOrigin(cookieRedirectTo, origins) : isSameOrigin(cookieRedirectTo, requestOrigin);
802
+ if (!isValid) {
803
+ logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", {
804
+ structuredData: {
805
+ redirect_path: cookieRedirectTo,
806
+ provider: oauth2,
807
+ has_trusted_origins: origins.length > 0,
808
+ request_origin: requestOrigin
809
+ }
810
+ });
811
+ throw new AuthSecurityError(
812
+ "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
813
+ "Invalid redirect path. Potential open redirect attack detected."
814
+ );
815
+ }
624
816
  }
625
- const userInfo = await getUserInfo(oauthConfig, accessToken.access_token);
817
+ const userInfo = await getUserInfo(oauthConfig, accessToken.access_token, logger);
626
818
  const sessionCookie = await createSessionCookie(jose, userInfo);
627
819
  const csrfToken = await createCSRF(jose);
628
- const headers = new import_router3.HeadersBuilder(cacheControl).setHeader("Location", sanitized).setCookie(cookies.sessionToken.name, sessionCookie, cookies.sessionToken.attributes).setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes).setCookie(cookies.state.name, "", expiredCookieAttributes).setCookie(cookies.redirectURI.name, "", expiredCookieAttributes).setCookie(cookies.redirectTo.name, "", expiredCookieAttributes).setCookie(cookies.codeVerifier.name, "", expiredCookieAttributes).toHeaders();
820
+ logger?.log("OAUTH_CALLBACK_SUCCESS", {
821
+ structuredData: {
822
+ provider: oauth2
823
+ }
824
+ });
825
+ const headers = new import_router3.HeadersBuilder(cacheControl).setHeader("Location", cookieRedirectTo).setCookie(cookies.sessionToken.name, sessionCookie, cookies.sessionToken.attributes).setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes).setCookie(cookies.state.name, "", expiredCookieAttributes).setCookie(cookies.redirectURI.name, "", expiredCookieAttributes).setCookie(cookies.redirectTo.name, "", expiredCookieAttributes).setCookie(cookies.codeVerifier.name, "", expiredCookieAttributes).toHeaders();
629
826
  return Response.json({ oauth: oauth2 }, { status: 302, headers });
630
827
  },
631
828
  callbackConfig(oauth)
@@ -637,16 +834,18 @@ var import_router4 = require("@aura-stack/router");
637
834
  var sessionAction = (0, import_router4.createEndpoint)("GET", "/session", async (ctx) => {
638
835
  const {
639
836
  request,
640
- context: { jose, cookies }
837
+ context: { jose, cookies, logger }
641
838
  } = ctx;
642
839
  try {
643
840
  const session = getCookie(request, cookies.sessionToken.name);
644
841
  const decoded = await jose.decodeJWT(session);
842
+ logger?.log("AUTH_SESSION_VALID");
645
843
  const { exp, iat, jti, nbf, ...user } = decoded;
646
- const headers = new Headers(cacheControl);
844
+ const headers = new Headers(secureApiHeaders);
647
845
  return Response.json({ user, expires: toISOString(exp * 1e3) }, { headers });
648
846
  } catch (error) {
649
- const headers = new import_router4.HeadersBuilder(cacheControl).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
847
+ logger?.log("AUTH_SESSION_INVALID", { structuredData: { error_type: getErrorName(error) } });
848
+ const headers = new import_router4.HeadersBuilder(secureApiHeaders).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
650
849
  return Response.json({ authenticated: false, message: "Unauthorized" }, { status: 401, headers });
651
850
  }
652
851
  });
@@ -670,30 +869,54 @@ var signOutAction = (0, import_router5.createEndpoint)(
670
869
  request,
671
870
  headers,
672
871
  searchParams: { redirectTo },
673
- context: { jose, cookies }
872
+ context
674
873
  } = ctx;
874
+ const { jose, cookies, logger } = context;
675
875
  const session = headers.getCookie(cookies.sessionToken.name);
676
876
  const csrfToken = headers.getCookie(cookies.csrfToken.name);
677
877
  const header = headers.getHeader("X-CSRF-Token");
878
+ logger?.log("SIGN_OUT_ATTEMPT", {
879
+ structuredData: {
880
+ has_session: Boolean(session),
881
+ has_csrf_token: Boolean(csrfToken),
882
+ has_csrf_header: Boolean(header)
883
+ }
884
+ });
678
885
  if (!session) {
886
+ logger?.log("SESSION_TOKEN_MISSING");
679
887
  throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
680
888
  }
681
889
  if (!csrfToken) {
890
+ logger?.log("CSRF_TOKEN_MISSING");
682
891
  throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
683
892
  }
684
893
  if (!header) {
685
- throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF header is missing.");
894
+ logger?.log("CSRF_HEADER_MISSING");
895
+ throw new AuthSecurityError("CSRF_HEADER_MISSING", "The CSRF header is missing.");
896
+ }
897
+ try {
898
+ await verifyCSRF(jose, csrfToken, header);
899
+ } catch (error) {
900
+ logger?.log("CSRF_TOKEN_INVALID", { structuredData: { error_type: getErrorName(error) } });
901
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "CSRF token verification failed");
902
+ }
903
+ logger?.log("SIGN_OUT_CSRF_VERIFIED");
904
+ try {
905
+ await jose.decodeJWT(session);
906
+ logger?.log("SIGN_OUT_SUCCESS");
907
+ } catch (error) {
908
+ logger?.log("INVALID_JWT_TOKEN", { structuredData: { error_type: getErrorName(error) } });
686
909
  }
687
- await verifyCSRF(jose, csrfToken, header);
688
- await jose.decodeJWT(session);
689
- const normalizedOriginPath = getNormalizedOriginPath(request.url);
690
- const location = createRedirectTo(
691
- new Request(normalizedOriginPath, {
910
+ const baseURL = getBaseURL(request);
911
+ const location = await createRedirectTo(
912
+ new Request(baseURL, {
692
913
  headers: headers.toHeaders()
693
914
  }),
694
- redirectTo
915
+ redirectTo,
916
+ context
695
917
  );
696
- const headersList = new import_router5.HeadersBuilder(cacheControl).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
918
+ logger?.log("SIGN_OUT_REDIRECT", { structuredData: { location } });
919
+ const headersList = new import_router5.HeadersBuilder(secureApiHeaders).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
697
920
  return Response.json({ message: "Signed out successfully" }, { status: import_router5.statusCode.ACCEPTED, headers: headersList });
698
921
  },
699
922
  config
@@ -711,11 +934,13 @@ var getCSRFToken = (request, cookieName) => {
711
934
  var csrfTokenAction = (0, import_router6.createEndpoint)("GET", "/csrfToken", async (ctx) => {
712
935
  const {
713
936
  request,
714
- context: { jose, cookies }
937
+ context: { jose, cookies, logger }
715
938
  } = ctx;
716
939
  const token = getCSRFToken(request, cookies.csrfToken.name);
940
+ logger?.log("CSRF_TOKEN_REQUESTED", { structuredData: { has_token: Boolean(token) } });
717
941
  const csrfToken = await createCSRF(jose, token);
718
- const headers = new Headers(cacheControl);
942
+ logger?.log("CSRF_TOKEN_ISSUED", { structuredData: { issued: Boolean(csrfToken) } });
943
+ const headers = new Headers(secureApiHeaders);
719
944
  headers.append("Set-Cookie", setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes));
720
945
  return Response.json({ csrfToken }, { headers });
721
946
  });