@aura-stack/auth 0.1.0 → 0.2.0-rc.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.
Files changed (111) hide show
  1. package/dist/@types/index.d.ts +5 -5
  2. package/dist/@types/router.d.d.ts +5 -5
  3. package/dist/@types/utility.d.ts +1 -5
  4. package/dist/actions/callback/access-token.cjs +95 -74
  5. package/dist/actions/callback/access-token.d.ts +7 -7
  6. package/dist/actions/callback/access-token.js +5 -3
  7. package/dist/actions/callback/callback.cjs +171 -249
  8. package/dist/actions/callback/callback.d.ts +6 -6
  9. package/dist/actions/callback/callback.js +10 -10
  10. package/dist/actions/callback/userinfo.cjs +81 -57
  11. package/dist/actions/callback/userinfo.d.ts +5 -5
  12. package/dist/actions/callback/userinfo.js +7 -5
  13. package/dist/actions/csrfToken/csrfToken.cjs +36 -105
  14. package/dist/actions/csrfToken/csrfToken.js +6 -6
  15. package/dist/actions/index.cjs +309 -444
  16. package/dist/actions/index.d.ts +5 -5
  17. package/dist/actions/index.js +19 -19
  18. package/dist/actions/session/session.cjs +25 -109
  19. package/dist/actions/session/session.js +4 -5
  20. package/dist/actions/signIn/authorization.cjs +96 -87
  21. package/dist/actions/signIn/authorization.d.ts +5 -5
  22. package/dist/actions/signIn/authorization.js +5 -5
  23. package/dist/actions/signIn/signIn.cjs +133 -242
  24. package/dist/actions/signIn/signIn.d.ts +6 -6
  25. package/dist/actions/signIn/signIn.js +8 -9
  26. package/dist/actions/signOut/signOut.cjs +136 -282
  27. package/dist/actions/signOut/signOut.js +8 -9
  28. package/dist/assert.cjs +5 -0
  29. package/dist/assert.d.ts +10 -1
  30. package/dist/assert.js +3 -1
  31. package/dist/chunk-3EUWD5BB.js +63 -0
  32. package/dist/chunk-6R2YZ4AC.js +22 -0
  33. package/dist/chunk-A3N4PVAT.js +70 -0
  34. package/dist/chunk-B737EUJV.js +22 -0
  35. package/dist/{chunk-256KIVJL.js → chunk-CXLATHS5.js} +53 -9
  36. package/dist/{chunk-6SM22VVJ.js → chunk-EIL2FPSS.js} +5 -1
  37. package/dist/{chunk-VFTYH33W.js → chunk-EMKJA2GJ.js} +36 -8
  38. package/dist/{chunk-UJJ7R56J.js → chunk-GA2SMTJO.js} +16 -10
  39. package/dist/chunk-HP34YGGJ.js +22 -0
  40. package/dist/chunk-HT4YLL7N.js +35 -0
  41. package/dist/{chunk-EBPE35JT.js → chunk-IUYZQTJV.js} +0 -1
  42. package/dist/{chunk-RLT4RFKV.js → chunk-IVET23KF.js} +21 -8
  43. package/dist/{chunk-XXJKNKGQ.js → chunk-JVFTCTTE.js} +9 -13
  44. package/dist/chunk-KSWLO5ZU.js +102 -0
  45. package/dist/{chunk-GZU3RBTB.js → chunk-N2APGLXA.js} +19 -10
  46. package/dist/{chunk-CAKJT3KS.js → chunk-N4SX7TZT.js} +21 -17
  47. package/dist/chunk-RRLIF4PQ.js +55 -0
  48. package/dist/chunk-TLE4PXY3.js +39 -0
  49. package/dist/chunk-W6LG7BFW.js +197 -0
  50. package/dist/{chunk-HMRKN75I.js → chunk-YRCB5FLE.js} +14 -9
  51. package/dist/chunk-ZNCZVF6U.js +14 -0
  52. package/dist/cookie.cjs +140 -99
  53. package/dist/cookie.d.ts +35 -44
  54. package/dist/cookie.js +10 -17
  55. package/dist/errors.cjs +85 -0
  56. package/dist/errors.d.ts +49 -0
  57. package/dist/errors.js +18 -0
  58. package/dist/{index-DpfbvTZ_.d.ts → index-DkaLJFn8.d.ts} +192 -61
  59. package/dist/index.cjs +543 -443
  60. package/dist/index.d.ts +6 -6
  61. package/dist/index.js +42 -28
  62. package/dist/jose.cjs +25 -14
  63. package/dist/jose.d.ts +4 -1
  64. package/dist/jose.js +5 -4
  65. package/dist/oauth/bitbucket.d.ts +5 -5
  66. package/dist/oauth/discord.cjs +0 -1
  67. package/dist/oauth/discord.d.ts +5 -5
  68. package/dist/oauth/discord.js +1 -1
  69. package/dist/oauth/figma.d.ts +5 -5
  70. package/dist/oauth/github.d.ts +5 -5
  71. package/dist/oauth/gitlab.d.ts +5 -5
  72. package/dist/oauth/index.cjs +176 -6
  73. package/dist/oauth/index.d.ts +5 -5
  74. package/dist/oauth/index.js +19 -4
  75. package/dist/oauth/mailchimp.cjs +46 -0
  76. package/dist/oauth/mailchimp.d.ts +7 -0
  77. package/dist/oauth/mailchimp.js +6 -0
  78. package/dist/oauth/pinterest.cjs +46 -0
  79. package/dist/oauth/pinterest.d.ts +7 -0
  80. package/dist/oauth/pinterest.js +6 -0
  81. package/dist/oauth/spotify.d.ts +5 -5
  82. package/dist/oauth/strava.cjs +46 -0
  83. package/dist/oauth/strava.d.ts +7 -0
  84. package/dist/oauth/strava.js +6 -0
  85. package/dist/oauth/x.d.ts +5 -5
  86. package/dist/{response.cjs → request.cjs} +14 -10
  87. package/dist/request.d.ts +13 -0
  88. package/dist/request.js +6 -0
  89. package/dist/schemas.cjs +43 -37
  90. package/dist/schemas.d.ts +67 -64
  91. package/dist/schemas.js +3 -1
  92. package/dist/secure.cjs +32 -24
  93. package/dist/secure.d.ts +5 -5
  94. package/dist/secure.js +4 -3
  95. package/dist/utils.cjs +90 -15
  96. package/dist/utils.d.ts +11 -2
  97. package/dist/utils.js +8 -4
  98. package/package.json +8 -7
  99. package/dist/chunk-FJUDBLCP.js +0 -59
  100. package/dist/chunk-HGJ4TXY4.js +0 -137
  101. package/dist/chunk-JAPMIE6S.js +0 -10
  102. package/dist/chunk-LLR722CL.js +0 -96
  103. package/dist/chunk-SJPDVKUS.js +0 -112
  104. package/dist/chunk-SMQO5WD7.js +0 -30
  105. package/dist/chunk-UTDLUEEG.js +0 -31
  106. package/dist/chunk-ZV4BH47P.js +0 -154
  107. package/dist/error.cjs +0 -88
  108. package/dist/error.d.ts +0 -62
  109. package/dist/error.js +0 -16
  110. package/dist/response.d.ts +0 -10
  111. package/dist/response.js +0 -6
@@ -39,71 +39,64 @@ __export(actions_exports, {
39
39
  module.exports = __toCommonJS(actions_exports);
40
40
 
41
41
  // src/actions/signIn/signIn.ts
42
- var import_zod = __toESM(require("zod"), 1);
42
+ var import_zod2 = require("zod");
43
43
  var import_router2 = require("@aura-stack/router");
44
44
 
45
- // src/response.ts
46
- var AuraResponse = class extends Response {
47
- static json(body, init) {
48
- return Response.json(body, init);
49
- }
45
+ // src/headers.ts
46
+ var cacheControl = {
47
+ "Cache-Control": "no-store",
48
+ Pragma: "no-cache",
49
+ Expires: "0",
50
+ Vary: "Cookie"
50
51
  };
51
52
 
52
53
  // src/secure.ts
53
- var import_node_crypto = __toESM(require("crypto"), 1);
54
+ var import_crypto = __toESM(require("crypto"), 1);
54
55
 
55
56
  // src/utils.ts
56
57
  var import_router = require("@aura-stack/router");
57
58
 
58
- // src/error.ts
59
- var AuthError = class extends Error {
60
- constructor(type, message) {
61
- super(message);
62
- this.type = type;
63
- this.name = "AuthError";
59
+ // src/errors.ts
60
+ var OAuthProtocolError = class extends Error {
61
+ type = "OAUTH_PROTOCOL_ERROR";
62
+ error;
63
+ errorURI;
64
+ constructor(error, description, errorURI, options2) {
65
+ super(description, options2);
66
+ this.error = error;
67
+ this.errorURI = errorURI;
68
+ this.name = new.target.name;
69
+ Error.captureStackTrace(this, new.target);
64
70
  }
65
71
  };
66
- var InvalidCsrfTokenError = class extends AuthError {
67
- constructor(message = "The provided CSRF token is invalid or has expired") {
68
- super("invalid_csrf_token", message);
69
- this.name = "InvalidCsrfTokenError";
72
+ var AuthInternalError = class extends Error {
73
+ type = "AUTH_INTERNAL_ERROR";
74
+ code;
75
+ constructor(code, message, options2) {
76
+ super(message, options2);
77
+ this.code = code;
78
+ this.name = new.target.name;
79
+ Error.captureStackTrace(this, new.target);
70
80
  }
71
81
  };
72
- var InvalidRedirectToError = class extends AuthError {
73
- constructor(message = "The redirectTo parameter does not match the hosted origin.") {
74
- super("invalid_redirect_to", message);
75
- this.name = "InvalidRedirectToError";
82
+ var AuthSecurityError = class extends Error {
83
+ type = "AUTH_SECURITY_ERROR";
84
+ code;
85
+ constructor(code, message, options2) {
86
+ super(message, options2);
87
+ this.code = code;
88
+ this.name = new.target.name;
89
+ Error.captureStackTrace(this, new.target);
76
90
  }
77
91
  };
78
- var isAuthError = (error) => {
79
- return error instanceof AuthError;
92
+ var isNativeError = (error) => {
93
+ return error instanceof Error;
80
94
  };
81
- var throwAuthError = (error, message) => {
82
- if (error instanceof Error) {
83
- if (isAuthError(error)) {
84
- throw error;
85
- }
86
- throw new AuthError("invalid_request", error.message ?? message);
87
- }
95
+ var isOAuthProtocolError = (error) => {
96
+ return error instanceof OAuthProtocolError;
88
97
  };
89
- var ERROR_RESPONSE = {
90
- AUTHORIZATION: {
91
- INVALID_REQUEST: "invalid_request",
92
- UNAUTHORIZED_CLIENT: "unauthorized_client",
93
- ACCESS_DENIED: "access_denied",
94
- UNSUPPORTED_RESPONSE_TYPE: "unsupported_response_type",
95
- INVALID_SCOPE: "invalid_scope",
96
- SERVER_ERROR: "server_error",
97
- TEMPORARILY_UNAVAILABLE: "temporarily_unavailable"
98
- },
99
- ACCESS_TOKEN: {
100
- INVALID_REQUEST: "invalid_request",
101
- INVALID_CLIENT: "invalid_client",
102
- INVALID_GRANT: "invalid_grant",
103
- UNAUTHORIZED_CLIENT: "unauthorized_client",
104
- UNSUPPORTED_GRANT_TYPE: "unsupported_grant_type",
105
- INVALID_SCOPE: "invalid_scope"
106
- }
98
+ var isAuthSecurityError = (error) => {
99
+ return error instanceof AuthSecurityError;
107
100
  };
108
101
 
109
102
  // src/utils.ts
@@ -123,9 +116,9 @@ var equals = (a, b) => {
123
116
  if (a === null || b === null || a === void 0 || b === void 0) return false;
124
117
  return a === b;
125
118
  };
126
- var sanitizeURL = (url2) => {
119
+ var sanitizeURL = (url) => {
127
120
  try {
128
- let decodedURL = decodeURIComponent(url2).trim();
121
+ let decodedURL = decodeURIComponent(url).trim();
129
122
  const protocolMatch = decodedURL.match(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)/);
130
123
  let protocol = "";
131
124
  let rest = decodedURL;
@@ -153,7 +146,7 @@ var sanitizeURL = (url2) => {
153
146
  }
154
147
  return sanitized;
155
148
  } catch {
156
- return url2.trim();
149
+ return url.trim();
157
150
  }
158
151
  };
159
152
  var isValidRelativePath = (path) => {
@@ -166,10 +159,10 @@ var isValidRelativePath = (path) => {
166
159
  };
167
160
  var getNormalizedOriginPath = (path) => {
168
161
  try {
169
- const url2 = new URL(path);
170
- url2.hash = "";
171
- url2.search = "";
172
- return `${url2.origin}${url2.pathname}`;
162
+ const url = new URL(path);
163
+ url.hash = "";
164
+ url.search = "";
165
+ return `${url.origin}${url.pathname}`;
173
166
  } catch {
174
167
  return sanitizeURL(path);
175
168
  }
@@ -177,13 +170,38 @@ var getNormalizedOriginPath = (path) => {
177
170
  var toISOString = (date) => {
178
171
  return new Date(date).toISOString();
179
172
  };
173
+ var formatZodError = (error) => {
174
+ if (!error.issues || error.issues.length === 0) {
175
+ return {};
176
+ }
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
+ }, {});
187
+ };
188
+
189
+ // src/assert.ts
190
+ 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);
194
+ };
195
+ var isJWTPayloadWithToken = (payload) => {
196
+ return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
197
+ };
180
198
 
181
199
  // src/secure.ts
182
200
  var generateSecure = (length = 32) => {
183
- return import_node_crypto.default.randomBytes(length).toString("base64url");
201
+ return import_crypto.default.randomBytes(length).toString("base64url");
184
202
  };
185
203
  var createHash = (data, base = "hex") => {
186
- return import_node_crypto.default.createHash("sha256").update(data).digest().toString(base);
204
+ return import_crypto.default.createHash("sha256").update(data).digest().toString(base);
187
205
  };
188
206
  var createPKCE = async (verifier) => {
189
207
  const codeVerifier = verifier ?? generateSecure(86);
@@ -205,182 +223,51 @@ var createCSRF = async (jose, csrfCookie) => {
205
223
  };
206
224
  var verifyCSRF = async (jose, cookie, header) => {
207
225
  try {
208
- const { token: cookieToken } = await jose.verifyJWS(cookie);
209
- const { token: headerToken } = await jose.verifyJWS(header);
210
- const cookieBuffer = Buffer.from(cookieToken);
211
- const headerBuffer = Buffer.from(headerToken);
226
+ const cookiePayload = await jose.verifyJWS(cookie);
227
+ const headerPayload = await jose.verifyJWS(header);
228
+ if (!isJWTPayloadWithToken(cookiePayload)) {
229
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Cookie payload missing token field.");
230
+ }
231
+ if (!isJWTPayloadWithToken(headerPayload)) {
232
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Header payload missing token field.");
233
+ }
234
+ const cookieBuffer = Buffer.from(cookiePayload.token);
235
+ const headerBuffer = Buffer.from(headerPayload.token);
212
236
  if (!equals(headerBuffer.length, cookieBuffer.length)) {
213
- throw new InvalidCsrfTokenError();
237
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
214
238
  }
215
- if (!import_node_crypto.default.timingSafeEqual(cookieBuffer, headerBuffer)) {
216
- throw new InvalidCsrfTokenError();
239
+ if (!import_crypto.default.timingSafeEqual(cookieBuffer, headerBuffer)) {
240
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
217
241
  }
218
242
  return true;
219
243
  } catch {
220
- throw new InvalidCsrfTokenError();
221
- }
222
- };
223
-
224
- // src/cookie.ts
225
- var import_cookie = require("cookie");
226
-
227
- // src/assert.ts
228
- var isRequest = (value) => {
229
- return typeof Request !== "undefined" && value instanceof Request;
230
- };
231
- var isValidURL = (value) => {
232
- if (value.includes("\r\n") || value.includes("\n") || value.includes("\r")) return false;
233
- const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()*+,;=:@-]*)*\/?$/;
234
- return regex.test(value);
235
- };
236
-
237
- // src/cookie.ts
238
- var import_cookie2 = require("cookie");
239
- var COOKIE_NAME = "aura-auth";
240
- var defaultCookieOptions = {
241
- httpOnly: true,
242
- sameSite: "lax",
243
- path: "/",
244
- maxAge: 60 * 60 * 24 * 15
245
- };
246
- var defaultStandardCookieConfig = {
247
- secure: false,
248
- httpOnly: true,
249
- prefix: ""
250
- };
251
- var defaultSecureCookieConfig = {
252
- secure: true,
253
- prefix: "__Secure-"
254
- };
255
- var defaultHostCookieConfig = {
256
- secure: true,
257
- prefix: "__Host-",
258
- path: "/",
259
- domain: void 0
260
- };
261
- var expiredCookieOptions = {
262
- ...defaultCookieOptions,
263
- expires: /* @__PURE__ */ new Date(0),
264
- maxAge: 0
265
- };
266
- var defineDefaultCookieOptions = (options2) => {
267
- return {
268
- name: options2?.name ?? COOKIE_NAME,
269
- prefix: options2?.prefix ?? (options2?.secure ? "__Secure-" : ""),
270
- ...defaultCookieOptions,
271
- ...options2
272
- };
273
- };
274
- var setCookie = (cookieName, value, options2) => {
275
- const { prefix, name } = defineDefaultCookieOptions(options2);
276
- const cookieNameWithPrefix = `${prefix}${name}.${cookieName}`;
277
- return (0, import_cookie.serialize)(cookieNameWithPrefix, value, {
278
- ...defaultCookieOptions,
279
- ...options2
280
- });
281
- };
282
- var getCookie = (petition, cookie, options2, optional = false) => {
283
- const cookies = isRequest(petition) ? petition.headers.get("Cookie") : petition.headers.getSetCookie().join("; ");
284
- if (!cookies) {
285
- if (optional) {
286
- return "";
287
- }
288
- throw new AuthError("invalid_request", "No cookies found. There is no active session");
289
- }
290
- const { name, prefix } = defineDefaultCookieOptions(options2);
291
- const parsedCookies = (0, import_cookie.parse)(cookies);
292
- const value = parsedCookies[`${prefix}${name}.${cookie}`];
293
- if (value === void 0) {
294
- if (optional) {
295
- return "";
296
- }
297
- throw new AuthError("invalid_request", `Cookie "${cookie}" not found. There is no active session`);
298
- }
299
- return value;
300
- };
301
- var createSessionCookie = async (session, cookieOptions, jose) => {
302
- try {
303
- const encoded = await jose.encodeJWT(session);
304
- return setCookie("sessionToken", encoded, cookieOptions);
305
- } catch (error) {
306
- throw new AuthError("server_error", "Failed to create session cookie", { cause: error });
307
- }
308
- };
309
- var secureCookieOptions = (request, cookieOptions, trustedProxyHeaders) => {
310
- const name = cookieOptions.name ?? COOKIE_NAME;
311
- const isSecure = trustedProxyHeaders ? request.url.startsWith("https://") || request.headers.get("X-Forwarded-Proto") === "https" || request.headers.get("Forwarded")?.includes("proto=https") : request.url.startsWith("https://");
312
- if (!cookieOptions.options?.httpOnly) {
313
- console.warn(
314
- "[WARNING]: Cookie is configured without HttpOnly. This allows JavaScript access via document.cookie and increases XSS risk."
315
- );
316
- }
317
- if (cookieOptions.options?.domain === "*") {
318
- console.warn("[WARNING]: Cookie 'Domain' is set to '*', which is insecure. Avoid wildcard domains.");
319
- }
320
- if (!isSecure) {
321
- const options2 = cookieOptions.options;
322
- if (options2?.secure) {
323
- console.warn(
324
- "[WARNING]: The 'Secure' attribute will be disabled for this cookie. Serve over HTTPS to enforce Secure cookies."
325
- );
326
- }
327
- if (options2?.sameSite == "none") {
328
- console.warn("[WARNING]: SameSite=None without a secure connection can be blocked by browsers.");
329
- }
330
- if (process.env.NODE_ENV === "production") {
331
- console.warn("[WARNING]: In production, ensure cookies are served over HTTPS to maintain security.");
332
- }
333
- return {
334
- ...defaultCookieOptions,
335
- ...cookieOptions.options,
336
- sameSite: options2?.sameSite === "none" ? "lax" : options2?.sameSite ?? "lax",
337
- ...defaultStandardCookieConfig,
338
- name
339
- };
244
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
340
245
  }
341
- return cookieOptions.strategy === "host" ? {
342
- ...defaultCookieOptions,
343
- ...cookieOptions.options,
344
- ...defaultHostCookieConfig,
345
- name
346
- } : { ...defaultCookieOptions, ...cookieOptions.options, ...defaultSecureCookieConfig, name };
347
- };
348
- var expireCookie = (name, options2) => {
349
- return setCookie(name, "", { ...options2, ...expiredCookieOptions });
350
- };
351
- var oauthCookie = (options2) => {
352
- return {
353
- ...options2,
354
- secure: options2.secure,
355
- httpOnly: options2.httpOnly,
356
- maxAge: 5 * 60,
357
- expires: new Date(Date.now() + 5 * 60 * 1e3)
358
- };
359
246
  };
360
247
 
361
248
  // src/schemas.ts
362
- var import_v4 = require("zod/v4");
363
- var OAuthProviderConfigSchema = (0, import_v4.object)({
364
- authorizeURL: (0, import_v4.url)(),
365
- accessToken: (0, import_v4.url)(),
366
- scope: (0, import_v4.string)().optional(),
367
- userInfo: (0, import_v4.url)(),
368
- responseType: (0, import_v4.enum)(["code", "token", "id_token"]),
369
- clientId: (0, import_v4.string)(),
370
- clientSecret: (0, import_v4.string)()
249
+ var import_zod = require("zod");
250
+ var OAuthProviderConfigSchema = (0, import_zod.object)({
251
+ authorizeURL: (0, import_zod.string)().url(),
252
+ accessToken: (0, import_zod.string)().url(),
253
+ scope: (0, import_zod.string)().optional(),
254
+ userInfo: (0, import_zod.string)().url(),
255
+ responseType: (0, import_zod.enum)(["code", "token", "id_token"]),
256
+ clientId: (0, import_zod.string)(),
257
+ clientSecret: (0, import_zod.string)()
371
258
  });
372
259
  var OAuthAuthorization = OAuthProviderConfigSchema.extend({
373
- redirectURI: (0, import_v4.string)(),
374
- state: (0, import_v4.string)(),
375
- codeChallenge: (0, import_v4.string)(),
376
- codeChallengeMethod: (0, import_v4.enum)(["plain", "S256"])
260
+ redirectURI: (0, import_zod.string)(),
261
+ state: (0, import_zod.string)(),
262
+ codeChallenge: (0, import_zod.string)(),
263
+ codeChallengeMethod: (0, import_zod.enum)(["plain", "S256"])
377
264
  });
378
- var OAuthAuthorizationResponse = (0, import_v4.object)({
379
- state: (0, import_v4.string)(),
380
- code: (0, import_v4.string)()
265
+ var OAuthAuthorizationResponse = (0, import_zod.object)({
266
+ state: (0, import_zod.string)({ message: "Missing state parameter in the OAuth authorization response." }),
267
+ code: (0, import_zod.string)({ message: "Missing code parameter in the OAuth authorization response." })
381
268
  });
382
- var OAuthAuthorizationErrorResponse = (0, import_v4.object)({
383
- error: (0, import_v4.enum)([
269
+ var OAuthAuthorizationErrorResponse = (0, import_zod.object)({
270
+ error: (0, import_zod.enum)([
384
271
  "invalid_request",
385
272
  "unauthorized_client",
386
273
  "access_denied",
@@ -389,24 +276,24 @@ var OAuthAuthorizationErrorResponse = (0, import_v4.object)({
389
276
  "server_error",
390
277
  "temporarily_unavailable"
391
278
  ]),
392
- error_description: (0, import_v4.string)().optional(),
393
- error_uri: (0, import_v4.string)().optional(),
394
- state: (0, import_v4.string)()
279
+ error_description: (0, import_zod.string)().optional(),
280
+ error_uri: (0, import_zod.string)().optional(),
281
+ state: (0, import_zod.string)()
395
282
  });
396
283
  var OAuthAccessToken = OAuthProviderConfigSchema.extend({
397
- redirectURI: (0, import_v4.string)(),
398
- code: (0, import_v4.string)(),
399
- codeVerifier: (0, import_v4.string)().min(43).max(128)
284
+ redirectURI: (0, import_zod.string)(),
285
+ code: (0, import_zod.string)(),
286
+ codeVerifier: (0, import_zod.string)().min(43).max(128)
400
287
  });
401
- var OAuthAccessTokenResponse = (0, import_v4.object)({
402
- access_token: (0, import_v4.string)(),
403
- token_type: (0, import_v4.string)(),
404
- expires_in: (0, import_v4.number)().optional(),
405
- refresh_token: (0, import_v4.string)().optional(),
406
- scope: (0, import_v4.string)().optional()
288
+ var OAuthAccessTokenResponse = (0, import_zod.object)({
289
+ access_token: (0, import_zod.string)(),
290
+ token_type: (0, import_zod.string)().optional(),
291
+ expires_in: (0, import_zod.number)().optional(),
292
+ refresh_token: (0, import_zod.string)().optional(),
293
+ scope: (0, import_zod.string)().optional().or((0, import_zod.null)())
407
294
  });
408
- var OAuthAccessTokenErrorResponse = (0, import_v4.object)({
409
- error: (0, import_v4.enum)([
295
+ var OAuthAccessTokenErrorResponse = (0, import_zod.object)({
296
+ error: (0, import_zod.enum)([
410
297
  "invalid_request",
411
298
  "invalid_client",
412
299
  "invalid_grant",
@@ -414,19 +301,24 @@ var OAuthAccessTokenErrorResponse = (0, import_v4.object)({
414
301
  "unsupported_grant_type",
415
302
  "invalid_scope"
416
303
  ]),
417
- error_description: (0, import_v4.string)().optional(),
418
- error_uri: (0, import_v4.string)().optional()
304
+ error_description: (0, import_zod.string)().optional(),
305
+ error_uri: (0, import_zod.string)().optional()
306
+ });
307
+ var OAuthErrorResponse = (0, import_zod.object)({
308
+ error: (0, import_zod.string)(),
309
+ error_description: (0, import_zod.string)().optional()
419
310
  });
420
- var OAuthErrorResponse = (0, import_v4.object)({
421
- error: (0, import_v4.string)(),
422
- error_description: (0, import_v4.string)().optional()
311
+ var OAuthEnvSchema = (0, import_zod.object)({
312
+ clientId: import_zod.z.string().min(1, "OAuth Client ID is required in the environment variables."),
313
+ clientSecret: import_zod.z.string().min(1, "OAuth Client Secret is required in the environment variables.")
423
314
  });
424
315
 
425
316
  // src/actions/signIn/authorization.ts
426
317
  var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod) => {
427
318
  const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
428
319
  if (!parsed.success) {
429
- throw new AuthError(ERROR_RESPONSE.AUTHORIZATION.SERVER_ERROR, "Invalid OAuth configuration");
320
+ const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
321
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
430
322
  }
431
323
  const { authorizeURL, ...options2 } = parsed.data;
432
324
  const { userInfo, accessToken, clientSecret, ...required } = options2;
@@ -444,8 +336,8 @@ var getOriginURL = (request, trustedProxyHeaders) => {
444
336
  }
445
337
  };
446
338
  var createRedirectURI = (request, oauth, basePath, trustedProxyHeaders) => {
447
- const url2 = getOriginURL(request, trustedProxyHeaders);
448
- return `${url2.origin}${basePath}/callback/${oauth}`;
339
+ const url = getOriginURL(request, trustedProxyHeaders);
340
+ return `${url.origin}${basePath}/callback/${oauth}`;
449
341
  };
450
342
  var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
451
343
  try {
@@ -459,15 +351,18 @@ var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
459
351
  }
460
352
  const redirectToURL = new URL(sanitizeURL(getNormalizedOriginPath(redirectTo)));
461
353
  if (!isValidURL(redirectTo) || !equals(redirectToURL.origin, hostedURL.origin)) {
462
- throw new InvalidRedirectToError();
354
+ throw new AuthSecurityError(
355
+ "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
356
+ "The redirectTo parameter does not match the hosted origin."
357
+ );
463
358
  }
464
359
  return sanitizeURL(redirectToURL.pathname);
465
360
  }
466
361
  if (referer) {
467
362
  const refererURL = new URL(sanitizeURL(referer));
468
363
  if (!isValidURL(referer) || !equals(refererURL.origin, hostedURL.origin)) {
469
- throw new AuthError(
470
- ERROR_RESPONSE.AUTHORIZATION.INVALID_REQUEST,
364
+ throw new AuthSecurityError(
365
+ "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
471
366
  "The referer of the request does not match the hosted origin."
472
367
  );
473
368
  }
@@ -476,16 +371,16 @@ var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
476
371
  if (origin) {
477
372
  const originURL = new URL(sanitizeURL(getNormalizedOriginPath(origin)));
478
373
  if (!isValidURL(origin) || !equals(originURL.origin, hostedURL.origin)) {
479
- throw new AuthError(ERROR_RESPONSE.AUTHORIZATION.INVALID_REQUEST, "Invalid origin (potential CSRF).");
374
+ throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
480
375
  }
481
376
  return sanitizeURL(originURL.pathname);
482
377
  }
483
378
  return "/";
484
379
  } catch (error) {
485
- if (isAuthError(error)) {
380
+ if (isAuthSecurityError(error)) {
486
381
  throw error;
487
382
  }
488
- throw new AuthError(ERROR_RESPONSE.AUTHORIZATION.INVALID_REQUEST, "Invalid origin (potential CSRF).");
383
+ throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
489
384
  }
490
385
  };
491
386
 
@@ -493,9 +388,14 @@ var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
493
388
  var signInConfig = (oauth) => {
494
389
  return (0, import_router2.createEndpointConfig)("/signIn/:oauth", {
495
390
  schemas: {
496
- params: import_zod.default.object({
497
- oauth: import_zod.default.enum(Object.keys(oauth)),
498
- redirectTo: import_zod.default.string().optional()
391
+ params: import_zod2.z.object({
392
+ oauth: import_zod2.z.enum(
393
+ Object.keys(oauth),
394
+ "The OAuth provider is not supported or invalid."
395
+ )
396
+ }),
397
+ searchParams: import_zod2.z.object({
398
+ redirectTo: import_zod2.z.string().optional()
499
399
  })
500
400
  }
501
401
  });
@@ -507,67 +407,41 @@ var signInAction = (oauth) => {
507
407
  async (ctx) => {
508
408
  const {
509
409
  request,
510
- params: { oauth: oauth2, redirectTo },
410
+ params: { oauth: oauth2 },
411
+ searchParams: { redirectTo },
511
412
  context: { oauth: providers, cookies, trustedProxyHeaders, basePath }
512
413
  } = ctx;
513
- try {
514
- const cookieOptions = secureCookieOptions(request, cookies, trustedProxyHeaders);
515
- const state = generateSecure();
516
- const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
517
- const stateCookie = setCookie("state", state, oauthCookie(cookieOptions));
518
- const redirectURICookie = setCookie("redirect_uri", redirectURI, oauthCookie(cookieOptions));
519
- const redirectToCookie = setCookie(
520
- "redirect_to",
521
- createRedirectTo(request, redirectTo, trustedProxyHeaders),
522
- oauthCookie(cookieOptions)
523
- );
524
- const { codeVerifier, codeChallenge, method } = await createPKCE();
525
- const codeVerifierCookie = setCookie("code_verifier", codeVerifier, oauthCookie(cookieOptions));
526
- const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
527
- const headers = new Headers();
528
- headers.set("Location", authorization);
529
- headers.append("Set-Cookie", stateCookie);
530
- headers.append("Set-Cookie", redirectURICookie);
531
- headers.append("Set-Cookie", redirectToCookie);
532
- headers.append("Set-Cookie", codeVerifierCookie);
533
- return Response.json(
534
- { oauth: oauth2 },
535
- {
536
- status: 302,
537
- headers
538
- }
539
- );
540
- } catch (error) {
541
- if (isAuthError(error)) {
542
- const { type, message } = error;
543
- return AuraResponse.json(
544
- { error: type, error_description: message },
545
- { status: import_router2.statusCode.BAD_REQUEST }
546
- );
414
+ const state = generateSecure();
415
+ const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
416
+ const redirectToValue = createRedirectTo(request, redirectTo, trustedProxyHeaders);
417
+ const { codeVerifier, codeChallenge, method } = await createPKCE();
418
+ const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
419
+ 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
+ return Response.json(
421
+ { oauth: oauth2 },
422
+ {
423
+ status: 302,
424
+ headers
547
425
  }
548
- return AuraResponse.json(
549
- {
550
- error: ERROR_RESPONSE.AUTHORIZATION.SERVER_ERROR,
551
- error_description: "An unexpected error occurred"
552
- },
553
- { status: import_router2.statusCode.INTERNAL_SERVER_ERROR }
554
- );
555
- }
426
+ );
556
427
  },
557
428
  signInConfig(oauth)
558
429
  );
559
430
  };
560
431
 
561
432
  // src/actions/callback/callback.ts
562
- var import_zod2 = __toESM(require("zod"), 1);
433
+ var import_zod3 = require("zod");
563
434
  var import_router3 = require("@aura-stack/router");
564
435
 
565
- // src/headers.ts
566
- var cacheControl = {
567
- "Cache-Control": "no-store",
568
- Pragma: "no-cache",
569
- Expires: "0",
570
- Vary: "Cookie"
436
+ // src/request.ts
437
+ var fetchAsync = async (url, options2 = {}, timeout = 5e3) => {
438
+ const controller = new AbortController();
439
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
440
+ const response = await fetch(url, {
441
+ ...options2,
442
+ signal: controller.signal
443
+ }).finally(() => clearTimeout(timeoutId));
444
+ return response;
571
445
  };
572
446
 
573
447
  // src/actions/callback/userinfo.ts
@@ -583,7 +457,7 @@ var getDefaultUserInfo = (profile) => {
583
457
  var getUserInfo = async (oauthConfig, accessToken) => {
584
458
  const userinfoEndpoint = oauthConfig.userInfo;
585
459
  try {
586
- const response = await fetch(userinfoEndpoint, {
460
+ const response = await fetchAsync(userinfoEndpoint, {
587
461
  method: "GET",
588
462
  headers: {
589
463
  Accept: "application/json",
@@ -593,11 +467,20 @@ var getUserInfo = async (oauthConfig, accessToken) => {
593
467
  const json = await response.json();
594
468
  const { success, data } = OAuthErrorResponse.safeParse(json);
595
469
  if (success) {
596
- throw new AuthError(data.error, data?.error_description ?? "An error occurred while fetching user information.");
470
+ throw new OAuthProtocolError(
471
+ data.error,
472
+ data?.error_description ?? "An error occurred while fetching user information."
473
+ );
597
474
  }
598
475
  return oauthConfig?.profile ? oauthConfig.profile(json) : getDefaultUserInfo(json);
599
476
  } catch (error) {
600
- throw throwAuthError(error, "Failed to retrieve userinfo");
477
+ if (isOAuthProtocolError(error)) {
478
+ throw error;
479
+ }
480
+ if (isNativeError(error)) {
481
+ throw new OAuthProtocolError("invalid_request", error.message, "", { cause: error });
482
+ }
483
+ throw new OAuthProtocolError("invalid_request", "Failed to fetch user information.", "", { cause: error });
601
484
  }
602
485
  };
603
486
 
@@ -605,11 +488,12 @@ var getUserInfo = async (oauthConfig, accessToken) => {
605
488
  var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) => {
606
489
  const parsed = OAuthAccessToken.safeParse({ ...oauthConfig, redirectURI, code, codeVerifier });
607
490
  if (!parsed.success) {
608
- throw new AuthError(ERROR_RESPONSE.ACCESS_TOKEN.INVALID_REQUEST, "Invalid OAuth configuration");
491
+ const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
492
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
609
493
  }
610
494
  const { accessToken, clientId, clientSecret, code: codeParsed, redirectURI: redirectParsed } = parsed.data;
611
495
  try {
612
- const response = await fetch(accessToken, {
496
+ const response = await fetchAsync(accessToken, {
613
497
  method: "POST",
614
498
  headers: {
615
499
  Accept: "application/json",
@@ -629,13 +513,55 @@ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) =>
629
513
  if (!token.success) {
630
514
  const { success, data } = OAuthAccessTokenErrorResponse.safeParse(json);
631
515
  if (!success) {
632
- throw new AuthError(ERROR_RESPONSE.ACCESS_TOKEN.INVALID_GRANT, "Invalid access token response format");
516
+ throw new OAuthProtocolError("INVALID_REQUEST", "Invalid access token response format");
633
517
  }
634
- throw new AuthError(data.error, data?.error_description ?? "Failed to retrieve access token");
518
+ throw new OAuthProtocolError(data.error, data?.error_description ?? "Failed to retrieve access token");
635
519
  }
636
520
  return token.data;
637
521
  } catch (error) {
638
- throw throwAuthError(error, "Failed to create access token");
522
+ throw error;
523
+ }
524
+ };
525
+
526
+ // src/cookie.ts
527
+ var import_cookie = require("@aura-stack/router/cookie");
528
+ var defaultCookieOptions = {
529
+ httpOnly: true,
530
+ sameSite: "lax",
531
+ path: "/",
532
+ maxAge: 60 * 60 * 24 * 15
533
+ };
534
+ var oauthCookieOptions = {
535
+ httpOnly: true,
536
+ maxAge: 5 * 60,
537
+ sameSite: "lax",
538
+ expires: new Date(Date.now() + 5 * 60 * 1e3)
539
+ };
540
+ var setCookie = (cookieName, value, options2) => {
541
+ return (0, import_cookie.serialize)(cookieName, value, options2);
542
+ };
543
+ var expiredCookieAttributes = {
544
+ ...defaultCookieOptions,
545
+ expires: /* @__PURE__ */ new Date(0),
546
+ maxAge: 0
547
+ };
548
+ var getCookie = (request, cookieName) => {
549
+ const cookies = request.headers.get("Cookie");
550
+ if (!cookies) {
551
+ throw new AuthInternalError("COOKIE_NOT_FOUND", "No cookies found. There is no active session");
552
+ }
553
+ const value = (0, import_cookie.parse)(cookies)[cookieName];
554
+ if (!value) {
555
+ throw new AuthInternalError("COOKIE_NOT_FOUND", `Cookie "${cookieName}" not found. There is no active session`);
556
+ }
557
+ return value;
558
+ };
559
+ var createSessionCookie = async (jose, session) => {
560
+ try {
561
+ const encoded = await jose.encodeJWT(session);
562
+ return encoded;
563
+ } catch (error) {
564
+ throw new AuthInternalError("INVALID_JWT_TOKEN", "Failed to create session cookie", { cause: error });
639
565
  }
640
566
  };
641
567
 
@@ -643,9 +569,15 @@ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) =>
643
569
  var callbackConfig = (oauth) => {
644
570
  return (0, import_router3.createEndpointConfig)("/callback/:oauth", {
645
571
  schemas: {
646
- searchParams: OAuthAuthorizationResponse,
647
- params: import_zod2.default.object({
648
- oauth: import_zod2.default.enum(Object.keys(oauth))
572
+ params: import_zod3.z.object({
573
+ oauth: import_zod3.z.enum(
574
+ Object.keys(oauth),
575
+ "The OAuth provider is not supported or invalid."
576
+ )
577
+ }),
578
+ searchParams: import_zod3.z.object({
579
+ code: import_zod3.z.string("Missing code parameter in the OAuth authorization response."),
580
+ state: import_zod3.z.string("Missing state parameter in the OAuth authorization response.")
649
581
  })
650
582
  },
651
583
  middlewares: [
@@ -653,7 +585,7 @@ var callbackConfig = (oauth) => {
653
585
  const response = OAuthAuthorizationErrorResponse.safeParse(ctx.searchParams);
654
586
  if (response.success) {
655
587
  const { error, error_description } = response.data;
656
- throw new AuthError(error, error_description ?? "OAuth Authorization Error");
588
+ throw new OAuthProtocolError(error, error_description ?? "OAuth Authorization Error");
657
589
  }
658
590
  return ctx;
659
591
  }
@@ -669,66 +601,32 @@ var callbackAction = (oauth) => {
669
601
  request,
670
602
  params: { oauth: oauth2 },
671
603
  searchParams: { code, state },
672
- context: { oauth: providers, cookies, jose, trustedProxyHeaders }
604
+ context: { oauth: providers, cookies, jose }
673
605
  } = ctx;
674
- try {
675
- const oauthConfig = providers[oauth2];
676
- const cookieOptions = secureCookieOptions(request, cookies, trustedProxyHeaders);
677
- const cookieState = getCookie(request, "state", cookieOptions);
678
- const cookieRedirectTo = getCookie(request, "redirect_to", cookieOptions);
679
- const cookieRedirectURI = getCookie(request, "redirect_uri", cookieOptions);
680
- const codeVerifier = getCookie(request, "code_verifier", cookieOptions);
681
- if (!equals(cookieState, state)) {
682
- throw new AuthError(ERROR_RESPONSE.ACCESS_TOKEN.INVALID_REQUEST, "Mismatching state");
683
- }
684
- const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier);
685
- const sanitized = sanitizeURL(cookieRedirectTo);
686
- if (!isValidRelativePath(sanitized)) {
687
- throw new AuthError(
688
- ERROR_RESPONSE.ACCESS_TOKEN.INVALID_REQUEST,
689
- "Invalid redirect path. Potential open redirect attack detected."
690
- );
691
- }
692
- const headers = new Headers(cacheControl);
693
- headers.set("Location", sanitized);
694
- const userInfo = await getUserInfo(oauthConfig, accessToken.access_token);
695
- const sessionCookie = await createSessionCookie(userInfo, cookieOptions, jose);
696
- const csrfToken = await createCSRF(jose);
697
- const csrfCookie = setCookie(
698
- "csrfToken",
699
- csrfToken,
700
- secureCookieOptions(
701
- request,
702
- {
703
- ...cookies,
704
- strategy: "host"
705
- },
706
- trustedProxyHeaders
707
- )
606
+ const oauthConfig = providers[oauth2];
607
+ const cookieState = getCookie(request, cookies.state.name);
608
+ const cookieRedirectTo = getCookie(request, cookies.redirectTo.name);
609
+ const cookieRedirectURI = getCookie(request, cookies.redirectURI.name);
610
+ const codeVerifier = getCookie(request, cookies.codeVerifier.name);
611
+ if (!equals(cookieState, state)) {
612
+ throw new AuthSecurityError(
613
+ "MISMATCHING_STATE",
614
+ "The provided state passed in the OAuth response does not match the stored state."
708
615
  );
709
- headers.set("Set-Cookie", sessionCookie);
710
- headers.append("Set-Cookie", expireCookie("state", cookieOptions));
711
- headers.append("Set-Cookie", expireCookie("redirect_uri", cookieOptions));
712
- headers.append("Set-Cookie", expireCookie("redirect_to", cookieOptions));
713
- headers.append("Set-Cookie", expireCookie("code_verifier", cookieOptions));
714
- headers.append("Set-Cookie", csrfCookie);
715
- return Response.json({ oauth: oauth2 }, { status: 302, headers });
716
- } catch (error) {
717
- if (isAuthError(error)) {
718
- const { type, message } = error;
719
- return AuraResponse.json(
720
- { error: type, error_description: message },
721
- { status: import_router3.statusCode.BAD_REQUEST }
722
- );
723
- }
724
- return AuraResponse.json(
725
- {
726
- error: ERROR_RESPONSE.ACCESS_TOKEN.INVALID_CLIENT,
727
- error_description: "An unexpected error occurred"
728
- },
729
- { status: import_router3.statusCode.INTERNAL_SERVER_ERROR }
616
+ }
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."
730
623
  );
731
624
  }
625
+ const userInfo = await getUserInfo(oauthConfig, accessToken.access_token);
626
+ const sessionCookie = await createSessionCookie(jose, userInfo);
627
+ 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();
629
+ return Response.json({ oauth: oauth2 }, { status: 302, headers });
732
630
  },
733
631
  callbackConfig(oauth)
734
632
  );
@@ -739,31 +637,28 @@ var import_router4 = require("@aura-stack/router");
739
637
  var sessionAction = (0, import_router4.createEndpoint)("GET", "/session", async (ctx) => {
740
638
  const {
741
639
  request,
742
- context: { cookies, jose, trustedProxyHeaders }
640
+ context: { jose, cookies }
743
641
  } = ctx;
744
- const cookieOptions = secureCookieOptions(request, cookies, trustedProxyHeaders);
745
642
  try {
746
- const session = getCookie(request, "sessionToken", cookieOptions);
643
+ const session = getCookie(request, cookies.sessionToken.name);
747
644
  const decoded = await jose.decodeJWT(session);
748
645
  const { exp, iat, jti, nbf, ...user } = decoded;
749
646
  const headers = new Headers(cacheControl);
750
647
  return Response.json({ user, expires: toISOString(exp * 1e3) }, { headers });
751
- } catch {
752
- const headers = new Headers(cacheControl);
753
- const sessionCookie = expireCookie("sessionToken", cookieOptions);
754
- headers.set("Set-Cookie", sessionCookie);
648
+ } catch (error) {
649
+ const headers = new import_router4.HeadersBuilder(cacheControl).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
755
650
  return Response.json({ authenticated: false, message: "Unauthorized" }, { status: 401, headers });
756
651
  }
757
652
  });
758
653
 
759
654
  // src/actions/signOut/signOut.ts
760
- var import_zod3 = __toESM(require("zod"), 1);
655
+ var import_zod4 = require("zod");
761
656
  var import_router5 = require("@aura-stack/router");
762
657
  var config = (0, import_router5.createEndpointConfig)({
763
658
  schemas: {
764
- searchParams: import_zod3.default.object({
765
- token_type_hint: import_zod3.default.literal("session_token"),
766
- redirectTo: import_zod3.default.string().optional()
659
+ searchParams: import_zod4.z.object({
660
+ token_type_hint: import_zod4.z.literal("session_token"),
661
+ redirectTo: import_zod4.z.string().optional()
767
662
  })
768
663
  }
769
664
  });
@@ -775,83 +670,53 @@ var signOutAction = (0, import_router5.createEndpoint)(
775
670
  request,
776
671
  headers,
777
672
  searchParams: { redirectTo },
778
- context: { cookies, jose, trustedProxyHeaders }
673
+ context: { jose, cookies }
779
674
  } = ctx;
780
- try {
781
- const cookiesOptions = secureCookieOptions(request, cookies, trustedProxyHeaders);
782
- const session = getCookie(request, "sessionToken", cookiesOptions);
783
- const csrfToken = getCookie(request, "csrfToken", {
784
- ...cookiesOptions,
785
- prefix: cookiesOptions.secure ? "__Host-" : ""
786
- });
787
- const header = headers.get("X-CSRF-Token");
788
- if (!header || !session || !csrfToken) {
789
- throw new Error("Missing CSRF token or session token");
790
- }
791
- await verifyCSRF(jose, csrfToken, header);
792
- await jose.decodeJWT(session);
793
- const normalizedOriginPath = getNormalizedOriginPath(request.url);
794
- const location = createRedirectTo(
795
- new Request(normalizedOriginPath, {
796
- headers
797
- }),
798
- redirectTo
799
- );
800
- const responseHeaders = new Headers(cacheControl);
801
- responseHeaders.append("Set-Cookie", expireCookie("sessionToken", cookiesOptions));
802
- responseHeaders.append(
803
- "Set-Cookie",
804
- expireCookie("csrfToken", { ...cookiesOptions, prefix: cookiesOptions.secure ? "__Host-" : "" })
805
- );
806
- responseHeaders.append("Location", location);
807
- return Response.json(
808
- { message: "Signed out successfully" },
809
- { status: import_router5.statusCode.ACCEPTED, headers: responseHeaders }
810
- );
811
- } catch (error) {
812
- if (error instanceof InvalidCsrfTokenError) {
813
- return AuraResponse.json(
814
- {
815
- error: "invalid_csrf_token",
816
- error_description: "The provided CSRF token is invalid or has expired"
817
- },
818
- { status: import_router5.statusCode.UNAUTHORIZED }
819
- );
820
- }
821
- if (error instanceof InvalidRedirectToError) {
822
- const { type, message } = error;
823
- return AuraResponse.json(
824
- {
825
- error: type,
826
- error_description: message
827
- },
828
- { status: import_router5.statusCode.BAD_REQUEST }
829
- );
830
- }
831
- return AuraResponse.json(
832
- {
833
- error: "invalid_session_token",
834
- error_description: "The provided sessionToken is invalid or has already expired"
835
- },
836
- { status: import_router5.statusCode.UNAUTHORIZED }
837
- );
675
+ const session = headers.getCookie(cookies.sessionToken.name);
676
+ const csrfToken = headers.getCookie(cookies.csrfToken.name);
677
+ const header = headers.getHeader("X-CSRF-Token");
678
+ if (!session) {
679
+ throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
680
+ }
681
+ if (!csrfToken) {
682
+ throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
683
+ }
684
+ if (!header) {
685
+ throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF header is missing.");
838
686
  }
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, {
692
+ headers: headers.toHeaders()
693
+ }),
694
+ redirectTo
695
+ );
696
+ const headersList = new import_router5.HeadersBuilder(cacheControl).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
697
+ return Response.json({ message: "Signed out successfully" }, { status: import_router5.statusCode.ACCEPTED, headers: headersList });
839
698
  },
840
699
  config
841
700
  );
842
701
 
843
702
  // src/actions/csrfToken/csrfToken.ts
844
703
  var import_router6 = require("@aura-stack/router");
704
+ var getCSRFToken = (request, cookieName) => {
705
+ try {
706
+ return getCookie(request, cookieName);
707
+ } catch {
708
+ return void 0;
709
+ }
710
+ };
845
711
  var csrfTokenAction = (0, import_router6.createEndpoint)("GET", "/csrfToken", async (ctx) => {
846
712
  const {
847
713
  request,
848
- context: { cookies, jose, trustedProxyHeaders }
714
+ context: { jose, cookies }
849
715
  } = ctx;
850
- const cookieOptions = secureCookieOptions(request, { ...cookies, strategy: "host" }, trustedProxyHeaders);
851
- const existingCSRFToken = getCookie(request, "csrfToken", cookieOptions, true);
852
- const csrfToken = await createCSRF(jose, existingCSRFToken);
716
+ const token = getCSRFToken(request, cookies.csrfToken.name);
717
+ const csrfToken = await createCSRF(jose, token);
853
718
  const headers = new Headers(cacheControl);
854
- headers.set("Set-Cookie", setCookie("csrfToken", csrfToken, cookieOptions));
719
+ headers.append("Set-Cookie", setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes));
855
720
  return Response.json({ csrfToken }, { headers });
856
721
  });
857
722
  // Annotate the CommonJS export names for ESM import in node: