@aura-stack/auth 0.4.0-rc.4 → 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-DkaLJFn8.d.ts → index-CSyIJmCM.d.ts} +373 -45
  74. package/dist/index.cjs +1128 -483
  75. package/dist/index.d.ts +6 -10
  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
package/dist/index.cjs CHANGED
@@ -30,23 +30,43 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- createAuth: () => createAuth,
34
- createClient: () => import_router7.createClient
33
+ createAuth: () => createAuth
35
34
  });
36
35
  module.exports = __toCommonJS(index_exports);
37
- var import_config2 = require("dotenv/config");
38
36
  var import_router7 = require("@aura-stack/router");
39
37
 
38
+ // src/env.ts
39
+ var import_meta = {};
40
+ var env = new Proxy({}, {
41
+ get(_, prop) {
42
+ if (typeof prop !== "string") return void 0;
43
+ const hasProperty = (process2) => {
44
+ return process2 && Object.prototype.hasOwnProperty.call(process2, prop);
45
+ };
46
+ try {
47
+ if (typeof process !== "undefined" && hasProperty(process.env)) {
48
+ return process.env[prop];
49
+ }
50
+ if (typeof import_meta !== "undefined" && hasProperty(import_meta.env)) {
51
+ return import_meta.env[prop];
52
+ }
53
+ if (typeof Deno !== "undefined" && Deno.env?.get) {
54
+ return Deno.env.get(prop);
55
+ }
56
+ if (typeof Bun !== "undefined" && hasProperty(Bun.env)) {
57
+ return Bun.env[prop];
58
+ }
59
+ const globalValue = globalThis[prop];
60
+ return typeof globalValue === "string" ? globalValue : void 0;
61
+ } catch {
62
+ return void 0;
63
+ }
64
+ }
65
+ });
66
+
40
67
  // src/jose.ts
41
- var import_config = require("dotenv/config");
42
68
  var import_jose = require("@aura-stack/jose");
43
69
 
44
- // src/secure.ts
45
- var import_crypto = __toESM(require("crypto"), 1);
46
-
47
- // src/utils.ts
48
- var import_router = require("@aura-stack/router");
49
-
50
70
  // src/errors.ts
51
71
  var OAuthProtocolError = class extends Error {
52
72
  type = "OAUTH_PROTOCOL_ERROR";
@@ -93,194 +113,8 @@ var isAuthSecurityError = (error) => {
93
113
  return error instanceof AuthSecurityError;
94
114
  };
95
115
 
96
- // src/utils.ts
97
- var toSnakeCase = (str) => {
98
- return str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase().replace(/^_+/, "");
99
- };
100
- var toUpperCase = (str) => {
101
- return str.toUpperCase();
102
- };
103
- var toCastCase = (obj, type = "snake") => {
104
- return Object.entries(obj).reduce((previous, [key, value]) => {
105
- const newKey = type === "snake" ? toSnakeCase(key) : toUpperCase(key);
106
- return { ...previous, [newKey]: value };
107
- }, {});
108
- };
109
- var equals = (a, b) => {
110
- if (a === null || b === null || a === void 0 || b === void 0) return false;
111
- return a === b;
112
- };
113
- var sanitizeURL = (url) => {
114
- try {
115
- let decodedURL = decodeURIComponent(url).trim();
116
- const protocolMatch = decodedURL.match(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)/);
117
- let protocol = "";
118
- let rest = decodedURL;
119
- if (protocolMatch) {
120
- protocol = protocolMatch[1];
121
- rest = decodedURL.slice(protocol.length);
122
- const slashIndex = rest.indexOf("/");
123
- if (slashIndex === -1) {
124
- return protocol + rest;
125
- }
126
- const domain = rest.slice(0, slashIndex);
127
- let path = rest.slice(slashIndex).replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
128
- if (path !== "/" && path.endsWith("/")) {
129
- path = path.replace(/\/+$/, "/");
130
- } else if (path !== "/") {
131
- path = path.replace(/\/+$/, "");
132
- }
133
- return protocol + domain + path;
134
- }
135
- let sanitized = decodedURL.replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
136
- if (sanitized !== "/" && sanitized.endsWith("/")) {
137
- sanitized = sanitized.replace(/\/+$/, "/");
138
- } else if (sanitized !== "/") {
139
- sanitized = sanitized.replace(/\/+$/, "");
140
- }
141
- return sanitized;
142
- } catch {
143
- return url.trim();
144
- }
145
- };
146
- var isValidRelativePath = (path) => {
147
- if (!path || typeof path !== "string") return false;
148
- if (!path.startsWith("/") || path.includes("://") || path.includes("\r") || path.includes("\n")) return false;
149
- if (/[\x00-\x1F\x7F]/.test(path) || path.includes("\0")) return false;
150
- const sanitized = sanitizeURL(path);
151
- if (sanitized.includes("..")) return false;
152
- return true;
153
- };
154
- var onErrorHandler = (error) => {
155
- if ((0, import_router.isRouterError)(error)) {
156
- const { message, status, statusText } = error;
157
- return Response.json({ type: "ROUTER_ERROR", code: "ROUTER_INTERNAL_ERROR", message }, { status, statusText });
158
- }
159
- if ((0, import_router.isInvalidZodSchemaError)(error)) {
160
- return Response.json({ type: "ROUTER_ERROR", code: "INVALID_REQUEST", message: error.errors }, { status: 422 });
161
- }
162
- if (isOAuthProtocolError(error)) {
163
- const { error: errorCode, message, type, errorURI } = error;
164
- return Response.json(
165
- {
166
- type,
167
- error: errorCode,
168
- error_description: message,
169
- error_uri: errorURI
170
- },
171
- { status: 400 }
172
- );
173
- }
174
- if (isAuthInternalError(error) || isAuthSecurityError(error)) {
175
- const { type, code, message } = error;
176
- return Response.json(
177
- {
178
- type,
179
- code,
180
- message
181
- },
182
- { status: 400 }
183
- );
184
- }
185
- return Response.json({ type: "SERVER_ERROR", code: "server_error", message: "An unexpected error occurred" }, { status: 500 });
186
- };
187
- var getNormalizedOriginPath = (path) => {
188
- try {
189
- const url = new URL(path);
190
- url.hash = "";
191
- url.search = "";
192
- return `${url.origin}${url.pathname}`;
193
- } catch {
194
- return sanitizeURL(path);
195
- }
196
- };
197
- var toISOString = (date) => {
198
- return new Date(date).toISOString();
199
- };
200
- var useSecureCookies = (request, trustedProxyHeaders) => {
201
- return trustedProxyHeaders ? request.url.startsWith("https://") || request.headers.get("X-Forwarded-Proto") === "https" || (request.headers.get("Forwarded")?.includes("proto=https") ?? false) : request.url.startsWith("https://");
202
- };
203
- var formatZodError = (error) => {
204
- if (!error.issues || error.issues.length === 0) {
205
- return {};
206
- }
207
- return error.issues.reduce((previous, issue) => {
208
- const key = issue.path.join(".");
209
- return {
210
- ...previous,
211
- [key]: {
212
- code: issue.code,
213
- message: issue.message
214
- }
215
- };
216
- }, {});
217
- };
218
-
219
- // src/assert.ts
220
- var isValidURL = (value) => {
221
- if (value.includes("\r\n") || value.includes("\n") || value.includes("\r")) return false;
222
- const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()*+,;=:@-]*)*\/?$/;
223
- return regex.test(value);
224
- };
225
- var isJWTPayloadWithToken = (payload) => {
226
- return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
227
- };
228
-
229
- // src/secure.ts
230
- var generateSecure = (length = 32) => {
231
- return import_crypto.default.randomBytes(length).toString("base64url");
232
- };
233
- var createHash = (data, base = "hex") => {
234
- return import_crypto.default.createHash("sha256").update(data).digest().toString(base);
235
- };
236
- var createPKCE = async (verifier) => {
237
- const codeVerifier = verifier ?? generateSecure(86);
238
- const codeChallenge = createHash(codeVerifier, "base64url");
239
- return { codeVerifier, codeChallenge, method: "S256" };
240
- };
241
- var createCSRF = async (jose, csrfCookie) => {
242
- try {
243
- const token = generateSecure(32);
244
- if (csrfCookie) {
245
- await jose.verifyJWS(csrfCookie);
246
- return csrfCookie;
247
- }
248
- return jose.signJWS({ token });
249
- } catch {
250
- const token = generateSecure(32);
251
- return jose.signJWS({ token });
252
- }
253
- };
254
- var verifyCSRF = async (jose, cookie, header) => {
255
- try {
256
- const cookiePayload = await jose.verifyJWS(cookie);
257
- const headerPayload = await jose.verifyJWS(header);
258
- if (!isJWTPayloadWithToken(cookiePayload)) {
259
- throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Cookie payload missing token field.");
260
- }
261
- if (!isJWTPayloadWithToken(headerPayload)) {
262
- throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Header payload missing token field.");
263
- }
264
- const cookieBuffer = Buffer.from(cookiePayload.token);
265
- const headerBuffer = Buffer.from(headerPayload.token);
266
- if (!equals(headerBuffer.length, cookieBuffer.length)) {
267
- throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
268
- }
269
- if (!import_crypto.default.timingSafeEqual(cookieBuffer, headerBuffer)) {
270
- throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
271
- }
272
- return true;
273
- } catch {
274
- throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
275
- }
276
- };
277
- var createDerivedSalt = (secret) => {
278
- return import_crypto.default.createHash("sha256").update(secret).update("aura-auth-salt").digest("hex");
279
- };
280
-
281
116
  // src/jose.ts
282
117
  var createJoseInstance = (secret) => {
283
- const env = process.env;
284
118
  secret ??= env.AURA_AUTH_SECRET ?? env.AUTH_SECRET;
285
119
  if (!secret) {
286
120
  throw new AuthInternalError(
@@ -288,7 +122,22 @@ var createJoseInstance = (secret) => {
288
122
  "AURA_AUTH_SECRET environment variable is not set and no secret was provided."
289
123
  );
290
124
  }
291
- const salt = env.AURA_AUTH_SALT ?? env.AUTH_SALT ?? createDerivedSalt(secret);
125
+ const salt = env.AURA_AUTH_SALT ?? env.AUTH_SALT;
126
+ if (!salt) {
127
+ throw new AuthInternalError(
128
+ "JOSE_INITIALIZATION_FAILED",
129
+ "AURA_AUTH_SALT or AUTH_SALT environment variable is not set. A salt value is required for key derivation."
130
+ );
131
+ }
132
+ try {
133
+ (0, import_jose.createSecret)(salt);
134
+ } catch (error) {
135
+ throw new AuthInternalError(
136
+ "INVALID_SALT_SECRET_VALUE",
137
+ "AURA_AUTH_SALT/AUTH_SALT is invalid. It must be at least 32 bytes long and meet entropy requirements.",
138
+ { cause: error }
139
+ );
140
+ }
292
141
  const { derivedKey: derivedSigningKey } = (0, import_jose.createDeriveKey)(secret, salt, "signing");
293
142
  const { derivedKey: derivedEncryptionKey } = (0, import_jose.createDeriveKey)(secret, salt, "encryption");
294
143
  const { derivedKey: derivedCsrfTokenKey } = (0, import_jose.createDeriveKey)(secret, salt, "csrfToken");
@@ -304,6 +153,10 @@ var createJoseInstance = (secret) => {
304
153
  decryptJWE
305
154
  };
306
155
  };
156
+ var jwtVerificationOptions = {
157
+ algorithms: ["HS256"],
158
+ typ: "JWT"
159
+ };
307
160
 
308
161
  // src/cookie.ts
309
162
  var import_cookie = require("@aura-stack/router/cookie");
@@ -340,7 +193,8 @@ var setCookie = (cookieName, value, options2) => {
340
193
  var expiredCookieAttributes = {
341
194
  ...defaultCookieOptions,
342
195
  expires: /* @__PURE__ */ new Date(0),
343
- maxAge: 0
196
+ maxAge: 0,
197
+ secure: true
344
198
  };
345
199
  var getCookie = (request, cookieName) => {
346
200
  const cookies = request.headers.get("Cookie");
@@ -361,31 +215,27 @@ var createSessionCookie = async (jose, session) => {
361
215
  throw new AuthInternalError("INVALID_JWT_TOKEN", "Failed to create session cookie", { cause: error });
362
216
  }
363
217
  };
364
- var defineSecureCookieOptions = (useSecure, attributes, strategy) => {
218
+ var defineSecureCookieOptions = (useSecure, attributes, strategy, logger) => {
365
219
  if (!attributes.httpOnly) {
366
- console.warn(
367
- "[WARNING]: Cookie is configured without HttpOnly. This allows JavaScript access via document.cookie and increases XSS risk."
368
- );
220
+ logger?.log("COOKIE_HTTPONLY_DISABLED");
369
221
  }
370
222
  if (attributes.domain === "*") {
371
223
  attributes.domain = void 0;
372
- console.warn("[WARNING]: Cookie 'Domain' is set to '*', which is insecure. Avoid wildcard domains.");
224
+ logger?.log("COOKIE_WILDCARD_DOMAIN");
373
225
  }
374
226
  if (!useSecure) {
375
227
  if (attributes.secure) {
376
- console.warn(
377
- "[WARNING]: The 'Secure' attribute will be disabled for this cookie. Serve over HTTPS to enforce Secure cookies."
378
- );
228
+ logger?.log("COOKIE_SECURE_DISABLED");
379
229
  }
380
230
  if (attributes.sameSite == "none") {
381
231
  attributes.sameSite = "lax";
382
- console.warn("[WARNING]: SameSite=None requires Secure attribute. Changing SameSite to 'Lax'.");
232
+ logger?.log("COOKIE_SAMESITE_NONE_WITHOUT_SECURE");
383
233
  }
384
234
  if (process.env.NODE_ENV === "production") {
385
- console.warn("[WARNING]: In production, ensure cookies are served over HTTPS to maintain security.");
235
+ logger?.log("COOKIE_INSECURE_IN_PRODUCTION");
386
236
  }
387
237
  if (strategy === "host") {
388
- console.warn("[WARNING]: __Host- cookies require a secure context. Falling back to standard cookie settings.");
238
+ logger?.log("COOKIE_HOST_STRATEGY_INSECURE");
389
239
  }
390
240
  return {
391
241
  ...defaultCookieOptions,
@@ -399,7 +249,7 @@ var defineSecureCookieOptions = (useSecure, attributes, strategy) => {
399
249
  ...defaultHostCookieConfig
400
250
  } : { ...defaultCookieOptions, ...attributes, ...defaultSecureCookieConfig };
401
251
  };
402
- var createCookieStore = (useSecure, prefix, overrides) => {
252
+ var createCookieStore = (useSecure, prefix, overrides, logger) => {
403
253
  prefix ??= COOKIE_NAME;
404
254
  const securePrefix = useSecure ? "__Secure-" : "";
405
255
  const hostPrefix = useSecure ? "__Host-" : "";
@@ -412,7 +262,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
412
262
  ...defaultCookieOptions,
413
263
  ...overrides?.sessionToken?.attributes
414
264
  },
415
- overrides?.sessionToken?.attributes?.strategy ?? "secure"
265
+ overrides?.sessionToken?.attributes?.strategy ?? "secure",
266
+ logger
416
267
  )
417
268
  },
418
269
  state: {
@@ -423,7 +274,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
423
274
  ...oauthCookieOptions,
424
275
  ...overrides?.state?.attributes
425
276
  },
426
- overrides?.state?.attributes?.strategy ?? "secure"
277
+ overrides?.state?.attributes?.strategy ?? "secure",
278
+ logger
427
279
  )
428
280
  },
429
281
  csrfToken: {
@@ -432,9 +284,11 @@ var createCookieStore = (useSecure, prefix, overrides) => {
432
284
  useSecure,
433
285
  {
434
286
  ...overrides?.csrfToken?.attributes,
435
- ...defaultHostCookieConfig
287
+ ...defaultHostCookieConfig,
288
+ sameSite: "strict"
436
289
  },
437
- overrides?.csrfToken?.attributes?.strategy ?? "host"
290
+ overrides?.csrfToken?.attributes?.strategy ?? "host",
291
+ logger
438
292
  )
439
293
  },
440
294
  redirectTo: {
@@ -445,7 +299,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
445
299
  ...oauthCookieOptions,
446
300
  ...overrides?.redirectTo?.attributes
447
301
  },
448
- overrides?.redirectTo?.attributes?.strategy ?? "secure"
302
+ overrides?.redirectTo?.attributes?.strategy ?? "secure",
303
+ logger
449
304
  )
450
305
  },
451
306
  redirectURI: {
@@ -456,7 +311,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
456
311
  ...oauthCookieOptions,
457
312
  ...overrides?.redirectURI?.attributes
458
313
  },
459
- overrides?.redirectURI?.attributes?.strategy ?? "secure"
314
+ overrides?.redirectURI?.attributes?.strategy ?? "secure",
315
+ logger
460
316
  )
461
317
  },
462
318
  codeVerifier: {
@@ -467,203 +323,378 @@ var createCookieStore = (useSecure, prefix, overrides) => {
467
323
  ...oauthCookieOptions,
468
324
  ...overrides?.codeVerifier?.attributes
469
325
  },
470
- overrides?.codeVerifier?.attributes?.strategy ?? "secure"
326
+ overrides?.codeVerifier?.attributes?.strategy ?? "secure",
327
+ logger
471
328
  )
472
329
  }
473
330
  };
474
331
  };
475
332
 
476
- // src/oauth/github.ts
477
- var github = {
478
- id: "github",
479
- name: "GitHub",
480
- authorizeURL: "https://github.com/login/oauth/authorize",
481
- accessToken: "https://github.com/login/oauth/access_token",
482
- userInfo: "https://api.github.com/user",
483
- scope: "read:user user:email",
484
- responseType: "code"
333
+ // src/utils.ts
334
+ var import_router = require("@aura-stack/router");
335
+ var toSnakeCase = (str) => {
336
+ return str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase().replace(/^_+/, "");
485
337
  };
486
-
487
- // src/oauth/bitbucket.ts
488
- var bitbucket = {
489
- id: "bitbucket",
490
- name: "Bitbucket",
491
- authorizeURL: "https://bitbucket.org/site/oauth2/authorize",
492
- accessToken: "https://bitbucket.org/site/oauth2/access_token",
493
- userInfo: "https://api.bitbucket.org/2.0/user",
494
- scope: "account email",
495
- responseType: "code",
496
- profile(profile) {
338
+ var toUpperCase = (str) => {
339
+ return str.toUpperCase();
340
+ };
341
+ var toCastCase = (obj, type = "snake") => {
342
+ return Object.entries(obj).reduce((previous, [key, value]) => {
343
+ const newKey = type === "snake" ? toSnakeCase(key) : toUpperCase(key);
344
+ return { ...previous, [newKey]: value };
345
+ }, {});
346
+ };
347
+ var equals = (a, b) => {
348
+ if (a === null || b === null || a === void 0 || b === void 0) return false;
349
+ return a === b;
350
+ };
351
+ var createErrorHandler = (logger) => {
352
+ return (error) => {
353
+ if ((0, import_router.isRouterError)(error)) {
354
+ const { message, status, statusText } = error;
355
+ logger?.log("ROUTER_INTERNAL_ERROR");
356
+ return Response.json({ type: "ROUTER_ERROR", code: "ROUTER_INTERNAL_ERROR", message }, { status, statusText });
357
+ }
358
+ if ((0, import_router.isInvalidZodSchemaError)(error)) {
359
+ logger?.log("INVALID_REQUEST");
360
+ return Response.json({ type: "ROUTER_ERROR", code: "INVALID_REQUEST", message: error.errors }, { status: 422 });
361
+ }
362
+ if (isOAuthProtocolError(error)) {
363
+ const { error: errorCode, message, type, errorURI } = error;
364
+ logger?.log("OAUTH_PROTOCOL_ERROR", {
365
+ structuredData: {
366
+ error: errorCode,
367
+ error_description: message,
368
+ error_uri: errorURI ?? ""
369
+ }
370
+ });
371
+ return Response.json(
372
+ {
373
+ type,
374
+ message
375
+ },
376
+ { status: 400 }
377
+ );
378
+ }
379
+ if (isAuthInternalError(error)) {
380
+ const { type, code, message } = error;
381
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
382
+ structuredData: {
383
+ error: code,
384
+ error_description: message
385
+ }
386
+ });
387
+ return Response.json(
388
+ {
389
+ type,
390
+ message
391
+ },
392
+ { status: 400 }
393
+ );
394
+ }
395
+ if (isAuthSecurityError(error)) {
396
+ const { type, code, message } = error;
397
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
398
+ structuredData: {
399
+ error: code,
400
+ error_description: message
401
+ }
402
+ });
403
+ return Response.json(
404
+ {
405
+ type,
406
+ code,
407
+ message
408
+ },
409
+ { status: 400 }
410
+ );
411
+ }
412
+ logger?.log("SERVER_ERROR");
413
+ return Response.json(
414
+ { type: "SERVER_ERROR", code: "SERVER_ERROR", message: "An unexpected error occurred" },
415
+ { status: 500 }
416
+ );
417
+ };
418
+ };
419
+ var getBaseURL = (request) => {
420
+ const url = new URL(request.url);
421
+ return `${url.origin}${url.pathname}`;
422
+ };
423
+ var toISOString = (date) => {
424
+ return new Date(date).toISOString();
425
+ };
426
+ var useSecureCookies = (request, trustedProxyHeaders) => {
427
+ return trustedProxyHeaders ? request.url.startsWith("https://") || request.headers.get("X-Forwarded-Proto") === "https" || (request.headers.get("Forwarded")?.includes("proto=https") ?? false) : request.url.startsWith("https://");
428
+ };
429
+ var formatZodError = (error) => {
430
+ if (!error.issues || error.issues.length === 0) {
431
+ return {};
432
+ }
433
+ return error.issues.reduce((previous, issue) => {
434
+ const key = issue.path.join(".");
497
435
  return {
498
- sub: profile.uuid ?? profile.account_id,
499
- name: profile.display_name ?? profile.nickname,
500
- image: profile.links.avatar.href
436
+ ...previous,
437
+ [key]: {
438
+ code: issue.code,
439
+ message: issue.message
440
+ }
501
441
  };
442
+ }, {});
443
+ };
444
+ var extractPath = (url) => {
445
+ const pathRegex = /^https?:\/\/[a-zA-Z0-9_\-\.]+(:\d+)?(\/.*)$/;
446
+ const match = url.match(pathRegex);
447
+ return match && match[2] ? match[2] : "/";
448
+ };
449
+ var getErrorName = (error) => {
450
+ if (error instanceof Error) {
451
+ return error.name;
502
452
  }
453
+ return typeof error === "string" ? error : "UnknownError";
454
+ };
455
+
456
+ // src/oauth/github.ts
457
+ var github = (options2) => {
458
+ return {
459
+ id: "github",
460
+ name: "GitHub",
461
+ authorizeURL: "https://github.com/login/oauth/authorize",
462
+ accessToken: "https://github.com/login/oauth/access_token",
463
+ userInfo: "https://api.github.com/user",
464
+ scope: "read:user user:email",
465
+ responseType: "code",
466
+ profile: (profile) => {
467
+ return {
468
+ sub: profile.id.toString(),
469
+ name: profile.name ?? profile.login,
470
+ email: profile.email ?? void 0,
471
+ image: profile.avatar_url
472
+ };
473
+ },
474
+ ...options2
475
+ };
476
+ };
477
+
478
+ // src/oauth/bitbucket.ts
479
+ var bitbucket = (options2) => {
480
+ return {
481
+ id: "bitbucket",
482
+ name: "Bitbucket",
483
+ authorizeURL: "https://bitbucket.org/site/oauth2/authorize",
484
+ accessToken: "https://bitbucket.org/site/oauth2/access_token",
485
+ userInfo: "https://api.bitbucket.org/2.0/user",
486
+ scope: "account email",
487
+ responseType: "code",
488
+ profile(profile) {
489
+ return {
490
+ sub: profile.uuid ?? profile.account_id,
491
+ name: profile.display_name ?? profile.nickname,
492
+ image: profile.links.avatar?.href,
493
+ email: void 0
494
+ };
495
+ },
496
+ ...options2
497
+ };
503
498
  };
504
499
 
505
500
  // src/oauth/figma.ts
506
- var figma = {
507
- id: "figma",
508
- name: "Figma",
509
- authorizeURL: "https://www.figma.com/oauth",
510
- accessToken: "https://api.figma.com/v1/oauth/token",
511
- userInfo: "https://api.figma.com/v1/me",
512
- scope: "current_user:read",
513
- responseType: "code",
514
- profile(profile) {
515
- return {
516
- sub: profile.id,
517
- name: profile.handle,
518
- email: profile.email,
519
- image: profile.img_url
520
- };
521
- }
501
+ var figma = (options2) => {
502
+ return {
503
+ id: "figma",
504
+ name: "Figma",
505
+ authorizeURL: "https://www.figma.com/oauth",
506
+ accessToken: "https://api.figma.com/v1/oauth/token",
507
+ userInfo: "https://api.figma.com/v1/me",
508
+ scope: "current_user:read",
509
+ responseType: "code",
510
+ profile(profile) {
511
+ return {
512
+ sub: profile.id,
513
+ name: profile.handle,
514
+ email: profile.email,
515
+ image: profile.img_url
516
+ };
517
+ },
518
+ ...options2
519
+ };
522
520
  };
523
521
 
524
522
  // src/oauth/discord.ts
525
- var discord = {
526
- id: "discord",
527
- name: "Discord",
528
- authorizeURL: "https://discord.com/oauth2/authorize",
529
- accessToken: "https://discord.com/api/oauth2/token",
530
- userInfo: "https://discord.com/api/users/@me",
531
- scope: "identify email",
532
- responseType: "code",
533
- profile(profile) {
534
- let image = "";
535
- if (profile.avatar === null) {
536
- const index = profile.discriminator === "0" ? (BigInt(profile.id) >> 22n) % 6n : Number(profile.discriminator) % 5;
537
- image = `https://cdn.discordapp.com/embed/avatars/${index}.png`;
538
- } else {
539
- const format = profile.avatar.startsWith("a_") ? "gif" : "png";
540
- image = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;
541
- }
542
- return {
543
- sub: profile.id,
544
- name: profile.global_name ?? profile.username,
545
- email: profile.email ?? "",
546
- image
547
- };
548
- }
523
+ var discord = (options2) => {
524
+ return {
525
+ id: "discord",
526
+ name: "Discord",
527
+ authorizeURL: "https://discord.com/oauth2/authorize",
528
+ accessToken: "https://discord.com/api/oauth2/token",
529
+ userInfo: "https://discord.com/api/users/@me",
530
+ scope: "identify email",
531
+ responseType: "code",
532
+ profile(profile) {
533
+ let image = "";
534
+ if (profile.avatar === null) {
535
+ const index = profile.discriminator === "0" ? (BigInt(profile.id) >> 22n) % 6n : Number(profile.discriminator) % 5;
536
+ image = `https://cdn.discordapp.com/embed/avatars/${index}.png`;
537
+ } else {
538
+ const format = profile.avatar.startsWith("a_") ? "gif" : "png";
539
+ image = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;
540
+ }
541
+ return {
542
+ sub: profile.id,
543
+ name: profile.global_name ?? profile.username,
544
+ email: profile.email ?? "",
545
+ image
546
+ };
547
+ },
548
+ ...options2
549
+ };
549
550
  };
550
551
 
551
552
  // src/oauth/gitlab.ts
552
- var gitlab = {
553
- id: "gitlab",
554
- name: "GitLab",
555
- authorizeURL: "https://gitlab.com/oauth/authorize",
556
- accessToken: "https://gitlab.com/oauth/token",
557
- userInfo: "https://gitlab.com/api/v4/user",
558
- scope: "read_user",
559
- responseType: "code",
560
- profile(profile) {
561
- return {
562
- sub: profile.id.toString(),
563
- name: profile.name ?? profile.username,
564
- email: profile.email,
565
- avatar: profile.avatar_url
566
- };
567
- }
553
+ var gitlab = (options2) => {
554
+ return {
555
+ id: "gitlab",
556
+ name: "GitLab",
557
+ authorizeURL: "https://gitlab.com/oauth/authorize",
558
+ accessToken: "https://gitlab.com/oauth/token",
559
+ userInfo: "https://gitlab.com/api/v4/user",
560
+ scope: "read_user",
561
+ responseType: "code",
562
+ profile(profile) {
563
+ return {
564
+ sub: profile.id.toString(),
565
+ name: profile.name ?? profile.username,
566
+ email: profile.email,
567
+ image: profile.avatar_url
568
+ };
569
+ },
570
+ ...options2
571
+ };
568
572
  };
569
573
 
570
574
  // src/oauth/spotify.ts
571
- var spotify = {
572
- id: "spotify",
573
- name: "Spotify",
574
- authorizeURL: "https://accounts.spotify.com/authorize",
575
- accessToken: "https://accounts.spotify.com/api/token",
576
- userInfo: "https://api.spotify.com/v1/me",
577
- scope: "user-read-email user-read-private",
578
- responseType: "token",
579
- profile(profile) {
580
- return {
581
- sub: profile.id,
582
- name: profile.display_name,
583
- email: profile.email,
584
- image: profile.images?.[0]?.url
585
- };
586
- }
575
+ var spotify = (options2) => {
576
+ return {
577
+ id: "spotify",
578
+ name: "Spotify",
579
+ authorizeURL: "https://accounts.spotify.com/authorize",
580
+ accessToken: "https://accounts.spotify.com/api/token",
581
+ userInfo: "https://api.spotify.com/v1/me",
582
+ scope: "user-read-private user-read-email",
583
+ responseType: "code",
584
+ profile(profile) {
585
+ return {
586
+ sub: profile.id,
587
+ name: profile.display_name,
588
+ email: profile.email,
589
+ image: profile.images[0]?.url ?? void 0
590
+ };
591
+ },
592
+ ...options2
593
+ };
587
594
  };
588
595
 
589
596
  // src/oauth/x.ts
590
- var x = {
591
- id: "x",
592
- name: "X",
593
- authorizeURL: "https://x.com/i/oauth2/authorize",
594
- accessToken: "https://api.x.com/2/oauth2/token",
595
- userInfo: "https://api.x.com/2/users/me?user.fields=profile_image_url",
596
- scope: "users.read users.email tweet.read offline.access",
597
- responseType: "code",
598
- profile({ data }) {
599
- return {
600
- sub: data.id,
601
- name: data.name,
602
- image: data.profile_image_url,
603
- email: ""
604
- };
605
- }
597
+ var x = (options2) => {
598
+ return {
599
+ id: "x",
600
+ name: "X",
601
+ authorizeURL: "https://twitter.com/i/oauth2/authorize",
602
+ accessToken: "https://api.twitter.com/2/oauth2/token",
603
+ userInfo: "https://api.twitter.com/2/users/me?user.fields=profile_image_url",
604
+ scope: "tweet.read users.read offline.access",
605
+ responseType: "code",
606
+ profile(profile) {
607
+ return {
608
+ sub: profile.data.id,
609
+ name: profile.data.name,
610
+ image: profile.data.profile_image_url,
611
+ email: void 0
612
+ };
613
+ },
614
+ ...options2
615
+ };
606
616
  };
607
617
 
608
618
  // src/oauth/strava.ts
609
- var strava = {
610
- id: "strava",
611
- name: "Strava",
612
- authorizeURL: "https://www.strava.com/oauth/authorize",
613
- accessToken: "https://www.strava.com/oauth/token",
614
- userInfo: "https://www.strava.com/api/v3/athlete",
615
- scope: "read",
616
- responseType: "code",
617
- profile(profile) {
618
- return {
619
- sub: profile.id.toString(),
620
- name: `${profile.firstname} ${profile.lastname}`,
621
- image: profile.profile,
622
- email: ""
623
- };
624
- }
619
+ var strava = (options2) => {
620
+ return {
621
+ id: "strava",
622
+ name: "Strava",
623
+ authorizeURL: "https://www.strava.com/oauth/authorize",
624
+ accessToken: "https://www.strava.com/oauth/token",
625
+ userInfo: "https://www.strava.com/api/v3/athlete",
626
+ scope: "read",
627
+ responseType: "code",
628
+ profile(profile) {
629
+ return {
630
+ sub: profile.id.toString(),
631
+ name: `${profile.firstname} ${profile.lastname}`,
632
+ image: profile.profile,
633
+ email: void 0
634
+ };
635
+ },
636
+ ...options2
637
+ };
625
638
  };
626
639
 
627
640
  // src/oauth/mailchimp.ts
628
- var mailchimp = {
629
- id: "mailchimp",
630
- name: "Mailchimp",
631
- authorizeURL: "https://login.mailchimp.com/oauth2/authorize",
632
- accessToken: "https://login.mailchimp.com/oauth2/token",
633
- userInfo: "https://login.mailchimp.com/oauth2/metadata",
634
- scope: "",
635
- responseType: "code",
636
- profile(profile) {
637
- return {
638
- sub: profile.user_id,
639
- name: profile.accountname,
640
- email: profile.login.login_email,
641
- image: null
642
- };
643
- }
641
+ var mailchimp = (options2) => {
642
+ return {
643
+ id: "mailchimp",
644
+ name: "Mailchimp",
645
+ authorizeURL: "https://login.mailchimp.com/oauth2/authorize",
646
+ accessToken: "https://login.mailchimp.com/oauth2/token",
647
+ userInfo: "https://login.mailchimp.com/oauth2/metadata",
648
+ scope: "",
649
+ responseType: "code",
650
+ profile(profile) {
651
+ return {
652
+ sub: profile.user_id,
653
+ name: profile.accountname,
654
+ email: profile.login.email,
655
+ image: profile.login.avatar
656
+ };
657
+ },
658
+ ...options2
659
+ };
644
660
  };
645
661
 
646
662
  // src/oauth/pinterest.ts
647
- var pinterest = {
648
- id: "pinterest",
649
- name: "Pinterest",
650
- authorizeURL: "https://api.pinterest.com/oauth/",
651
- accessToken: "https://api.pinterest.com/v5/oauth/token",
652
- userInfo: "https://api.pinterest.com/v5/user_account",
653
- scope: "user_accounts:read",
654
- responseType: "code",
655
- profile(profile) {
656
- return {
657
- sub: profile.id,
658
- name: profile.username,
659
- email: null,
660
- image: profile.profile_image
661
- };
662
- }
663
+ var pinterest = (options2) => {
664
+ return {
665
+ id: "pinterest",
666
+ name: "Pinterest",
667
+ authorizeURL: "https://www.pinterest.com/oauth",
668
+ accessToken: "https://api.pinterest.com/v5/oauth/token",
669
+ userInfo: "https://api.pinterest.com/v5/user_account",
670
+ scope: "user_accounts:read",
671
+ responseType: "code",
672
+ profile(profile) {
673
+ return {
674
+ sub: profile.id,
675
+ name: profile.username,
676
+ image: profile.profile_image,
677
+ email: void 0
678
+ };
679
+ },
680
+ ...options2
681
+ };
663
682
  };
664
683
 
665
684
  // src/schemas.ts
666
685
  var import_zod = require("zod");
686
+ var OAuthProviderCredentialsSchema = (0, import_zod.object)({
687
+ id: (0, import_zod.string)(),
688
+ name: (0, import_zod.string)(),
689
+ authorizeURL: (0, import_zod.string)().url(),
690
+ accessToken: (0, import_zod.string)().url(),
691
+ scope: (0, import_zod.string)(),
692
+ userInfo: (0, import_zod.string)().url(),
693
+ responseType: (0, import_zod.enum)(["code", "token", "id_token"]),
694
+ clientId: (0, import_zod.string)(),
695
+ clientSecret: (0, import_zod.string)(),
696
+ profile: import_zod.z.function().optional()
697
+ });
667
698
  var OAuthProviderConfigSchema = (0, import_zod.object)({
668
699
  authorizeURL: (0, import_zod.string)().url(),
669
700
  accessToken: (0, import_zod.string)().url(),
@@ -744,7 +775,6 @@ var builtInOAuthProviders = {
744
775
  pinterest
745
776
  };
746
777
  var defineOAuthEnvironment = (oauth) => {
747
- const env = process.env;
748
778
  const clientIdSuffix = `${oauth.toUpperCase()}_CLIENT_ID`;
749
779
  const clientSecretSuffix = `${oauth.toUpperCase()}_CLIENT_SECRET`;
750
780
  const loadEnvs = OAuthEnvSchema.safeParse({
@@ -760,17 +790,38 @@ var defineOAuthEnvironment = (oauth) => {
760
790
  var defineOAuthProviderConfig = (config2) => {
761
791
  if (typeof config2 === "string") {
762
792
  const definition = defineOAuthEnvironment(config2);
763
- const oauthConfig = builtInOAuthProviders[config2];
764
- return {
765
- ...oauthConfig,
766
- ...definition
767
- };
793
+ const oauthConfig = builtInOAuthProviders[config2]();
794
+ const parsed2 = OAuthProviderCredentialsSchema.safeParse({ ...oauthConfig, ...definition });
795
+ if (!parsed2.success) {
796
+ const details = JSON.stringify(formatZodError(parsed2.error), null, 2);
797
+ throw new AuthInternalError(
798
+ "INVALID_OAUTH_PROVIDER_CONFIGURATION",
799
+ `Invalid configuration for OAuth provider "${config2}": ${details}`
800
+ );
801
+ }
802
+ return parsed2.data;
768
803
  }
769
- return config2;
804
+ const hasCredentials = config2.clientId && config2.clientSecret;
805
+ const envConfig = hasCredentials ? {} : defineOAuthEnvironment(config2.id);
806
+ const parsed = OAuthProviderCredentialsSchema.safeParse({ ...envConfig, ...config2 });
807
+ if (!parsed.success) {
808
+ const details = JSON.stringify(formatZodError(parsed.error), null, 2);
809
+ throw new AuthInternalError(
810
+ "INVALID_OAUTH_PROVIDER_CONFIGURATION",
811
+ `Invalid configuration for OAuth provider "${config2.id}": ${details}`
812
+ );
813
+ }
814
+ return parsed.data;
770
815
  };
771
816
  var createBuiltInOAuthProviders = (oauth = []) => {
772
817
  return oauth.reduce((previous, config2) => {
773
818
  const oauthConfig = defineOAuthProviderConfig(config2);
819
+ if (oauthConfig.id in previous) {
820
+ throw new AuthInternalError(
821
+ "DUPLICATED_OAUTH_PROVIDER_ID",
822
+ `Duplicate OAuth provider id "${oauthConfig.id}" found. Each provider must have a unique id.`
823
+ );
824
+ }
774
825
  return { ...previous, [oauthConfig.id]: oauthConfig };
775
826
  }, {});
776
827
  };
@@ -786,75 +837,259 @@ var cacheControl = {
786
837
  Expires: "0",
787
838
  Vary: "Cookie"
788
839
  };
840
+ var contentSecurityPolicy = {
841
+ "Content-Security-Policy": [
842
+ "default-src 'none'",
843
+ "script-src 'self'",
844
+ "frame-src 'none'",
845
+ "object-src 'none'",
846
+ "frame-ancestors 'none'",
847
+ "base-uri 'none'"
848
+ ].join("; ")
849
+ };
850
+ var secureHeaders = {
851
+ "X-Content-Type-Options": "nosniff",
852
+ "X-Frame-Options": "DENY",
853
+ "Referrer-Policy": "strict-origin-when-cross-origin"
854
+ };
855
+ var secureApiHeaders = {
856
+ ...cacheControl,
857
+ ...contentSecurityPolicy,
858
+ ...secureHeaders
859
+ };
860
+
861
+ // src/secure.ts
862
+ var import_crypto2 = __toESM(require("crypto"), 1);
863
+
864
+ // src/assert.ts
865
+ var import_crypto = require("crypto");
866
+ var unsafeChars = [
867
+ "<",
868
+ ">",
869
+ '"',
870
+ "`",
871
+ " ",
872
+ "\r",
873
+ "\n",
874
+ " ",
875
+ "\\",
876
+ "%2F",
877
+ "%5C",
878
+ "%2f",
879
+ "%5c",
880
+ "\r\n",
881
+ "%0A",
882
+ "%0D",
883
+ "%0a",
884
+ "%0d",
885
+ "..",
886
+ "//",
887
+ "///",
888
+ "...",
889
+ "%20",
890
+ "\0"
891
+ ];
892
+ var isValidURL = (value) => {
893
+ if (!new RegExp(/^https?:\/\/[^/]/).test(value)) {
894
+ return false;
895
+ }
896
+ const match = value.match(/^(https?:\/\/)(.*)$/);
897
+ if (!match) return false;
898
+ const rest = match[2];
899
+ for (const char of unsafeChars) {
900
+ if (rest.includes(char)) return false;
901
+ }
902
+ const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()?#*+,;=:@-]*)*\/?$/;
903
+ return regex.test(match[0]);
904
+ };
905
+ var isJWTPayloadWithToken = (payload) => {
906
+ return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
907
+ };
908
+ var isRelativeURL = (value) => {
909
+ if (value.length > 100) return false;
910
+ for (const char of unsafeChars) {
911
+ if (value.includes(char)) return false;
912
+ }
913
+ const regex = /^\/[a-zA-Z0-9\-_\/.?&=#]*\/?$/;
914
+ return regex.test(value);
915
+ };
916
+ var isSameOrigin = (origin, expected) => {
917
+ const originURL = new URL(origin);
918
+ const expectedURL = new URL(expected);
919
+ return equals(originURL.origin, expectedURL.origin);
920
+ };
921
+ var patternToRegex = (pattern) => {
922
+ try {
923
+ if (pattern.length > 2048) return null;
924
+ pattern = pattern.replace(/\\/g, "");
925
+ const match = pattern.match(/^(https?):\/\/([a-zA-Z0-9.*-]{1,253})(?::(\d{1,5}|\*))?(?:\/.*)?$/);
926
+ if (!match) return null;
927
+ const [, protocol, host, port] = match;
928
+ const hasWildcard = host.includes("*");
929
+ if (hasWildcard && !host.startsWith("*.")) return null;
930
+ if (hasWildcard && host.slice(2).includes("*")) return null;
931
+ const domain = hasWildcard ? host.slice(2) : host;
932
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
933
+ const hostRegex = hasWildcard ? `[^.]+\\.${escapedDomain}` : escapedDomain;
934
+ const portRegex = port === "*" ? ":\\d{1,5}" : port ? `:${port}` : "";
935
+ return new RegExp(`^${protocol}:\\/\\/${hostRegex}${portRegex}$`);
936
+ } catch {
937
+ return null;
938
+ }
939
+ };
940
+ var isTrustedOrigin = (url, trustedOrigins) => {
941
+ if (!isValidURL(url) || trustedOrigins.length === 0) return false;
942
+ try {
943
+ const urlOrigin = new URL(url).origin;
944
+ for (const pattern of trustedOrigins) {
945
+ const regex = patternToRegex(pattern);
946
+ if (regex?.test(urlOrigin)) return true;
947
+ try {
948
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return true;
949
+ } catch {
950
+ }
951
+ }
952
+ } catch {
953
+ }
954
+ return false;
955
+ };
956
+ var safeEquals = (a, b) => {
957
+ const bufferA = Buffer.from(a);
958
+ const bufferB = Buffer.from(b);
959
+ if (bufferA.length !== bufferB.length) {
960
+ return false;
961
+ }
962
+ return (0, import_crypto.timingSafeEqual)(bufferA, bufferB);
963
+ };
964
+
965
+ // src/secure.ts
966
+ var generateSecure = (length = 32) => {
967
+ return import_crypto2.default.randomBytes(length).toString("base64url");
968
+ };
969
+ var createHash = (data, base = "hex") => {
970
+ return import_crypto2.default.createHash("sha256").update(data).digest().toString(base);
971
+ };
972
+ var createPKCE = async (verifier) => {
973
+ const byteLength = verifier ? void 0 : Math.floor(Math.random() * (96 - 32 + 1) + 32);
974
+ const codeVerifier = verifier ?? generateSecure(byteLength ?? 64);
975
+ if (codeVerifier.length < 43 || codeVerifier.length > 128) {
976
+ throw new AuthSecurityError("PKCE_VERIFIER_INVALID", "The code verifier must be between 43 and 128 characters in length.");
977
+ }
978
+ const codeChallenge = createHash(codeVerifier, "base64url");
979
+ return { codeVerifier, codeChallenge, method: "S256" };
980
+ };
981
+ var createCSRF = async (jose, csrfCookie) => {
982
+ try {
983
+ const token = generateSecure(32);
984
+ if (csrfCookie) {
985
+ await jose.verifyJWS(csrfCookie, jwtVerificationOptions);
986
+ return csrfCookie;
987
+ }
988
+ return jose.signJWS({ token });
989
+ } catch {
990
+ const token = generateSecure(32);
991
+ return jose.signJWS({ token });
992
+ }
993
+ };
994
+ var verifyCSRF = async (jose, cookie, header) => {
995
+ try {
996
+ const cookiePayload = await jose.verifyJWS(cookie, jwtVerificationOptions);
997
+ const headerPayload = await jose.verifyJWS(header, jwtVerificationOptions);
998
+ if (!isJWTPayloadWithToken(cookiePayload)) {
999
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Cookie payload missing token field.");
1000
+ }
1001
+ if (!isJWTPayloadWithToken(headerPayload)) {
1002
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Header payload missing token field.");
1003
+ }
1004
+ if (!equals(cookiePayload.token.length, headerPayload.token.length)) {
1005
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1006
+ }
1007
+ if (!safeEquals(cookiePayload.token, headerPayload.token)) {
1008
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1009
+ }
1010
+ return true;
1011
+ } catch {
1012
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1013
+ }
1014
+ };
789
1015
 
790
1016
  // src/actions/signIn/authorization.ts
791
- var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod) => {
1017
+ var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod, logger) => {
792
1018
  const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
793
1019
  if (!parsed.success) {
794
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
795
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
1020
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
1021
+ structuredData: {
1022
+ scope: oauthConfig.scope,
1023
+ redirect_uri: redirectURI,
1024
+ has_state: Boolean(state),
1025
+ has_code_challenge: Boolean(codeChallenge),
1026
+ code_challenge_method: codeChallengeMethod
1027
+ }
1028
+ });
1029
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
796
1030
  }
797
1031
  const { authorizeURL, ...options2 } = parsed.data;
798
1032
  const { userInfo, accessToken, clientSecret, ...required } = options2;
799
1033
  const searchParams = new URLSearchParams(toCastCase(required));
800
1034
  return `${authorizeURL}?${searchParams}`;
801
1035
  };
802
- var getOriginURL = (request, trustedProxyHeaders) => {
1036
+ var getTrustedOrigins = async (request, trustedOrigins) => {
1037
+ if (!trustedOrigins) return [];
1038
+ const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins;
1039
+ return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
1040
+ };
1041
+ var getOriginURL = async (request, context) => {
803
1042
  const headers = request.headers;
804
- if (trustedProxyHeaders) {
805
- const protocol = headers.get("X-Forwarded-Proto") ?? headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? "http";
806
- const host = headers.get("X-Forwarded-Host") ?? headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? null;
807
- return new URL(`${protocol}://${host}${getNormalizedOriginPath(new URL(request.url).pathname)}`);
808
- } else {
809
- return new URL(getNormalizedOriginPath(request.url));
1043
+ let origin = new URL(request.url).origin;
1044
+ const trustedOrigins = await getTrustedOrigins(request, context?.trustedOrigins);
1045
+ trustedOrigins.push(origin);
1046
+ if (context?.trustedProxyHeaders) {
1047
+ const protocol = headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Proto") ?? "http";
1048
+ const host = headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Host") ?? null;
1049
+ origin = `${protocol}://${host}`;
1050
+ }
1051
+ if (!isTrustedOrigin(origin, trustedOrigins)) {
1052
+ context?.logger?.log("UNTRUSTED_ORIGIN", { structuredData: { origin } });
1053
+ throw new AuthInternalError("UNTRUSTED_ORIGIN", "The constructed origin URL is not trusted.");
810
1054
  }
1055
+ return origin;
811
1056
  };
812
- var createRedirectURI = (request, oauth, basePath, trustedProxyHeaders) => {
813
- const url = getOriginURL(request, trustedProxyHeaders);
814
- return `${url.origin}${basePath}/callback/${oauth}`;
1057
+ var createRedirectURI = async (request, oauth, context) => {
1058
+ const origin = await getOriginURL(request, context);
1059
+ return `${origin}${context.basePath}/callback/${oauth}`;
815
1060
  };
816
- var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
1061
+ var createRedirectTo = async (request, redirectTo, context) => {
817
1062
  try {
818
1063
  const headers = request.headers;
819
- const origin = headers.get("Origin");
820
- const referer = headers.get("Referer");
821
- let hostedURL = getOriginURL(request, trustedProxyHeaders);
822
- if (redirectTo) {
823
- if (redirectTo.startsWith("/")) {
824
- return sanitizeURL(redirectTo);
825
- }
826
- const redirectToURL = new URL(sanitizeURL(getNormalizedOriginPath(redirectTo)));
827
- if (!isValidURL(redirectTo) || !equals(redirectToURL.origin, hostedURL.origin)) {
828
- throw new AuthSecurityError(
829
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
830
- "The redirectTo parameter does not match the hosted origin."
831
- );
832
- }
833
- return sanitizeURL(redirectToURL.pathname);
834
- }
835
- if (referer) {
836
- const refererURL = new URL(sanitizeURL(referer));
837
- if (!isValidURL(referer) || !equals(refererURL.origin, hostedURL.origin)) {
838
- throw new AuthSecurityError(
839
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
840
- "The referer of the request does not match the hosted origin."
841
- );
1064
+ const requestOrigin = await getOriginURL(request, context);
1065
+ const origins = await getTrustedOrigins(request, context?.trustedOrigins);
1066
+ const validateURL = (url) => {
1067
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
1068
+ if (isRelativeURL(url)) return url;
1069
+ if (origins.length > 0) {
1070
+ if (isTrustedOrigin(url, origins)) {
1071
+ const urlOrigin = new URL(url).origin;
1072
+ for (const pattern of origins) {
1073
+ const regex = patternToRegex(pattern);
1074
+ if (regex?.test(urlOrigin)) {
1075
+ return isSameOrigin(url, request.url) ? extractPath(url) : url;
1076
+ }
1077
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return url;
1078
+ }
1079
+ }
1080
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
1081
+ return "/";
842
1082
  }
843
- return sanitizeURL(refererURL.pathname);
844
- }
845
- if (origin) {
846
- const originURL = new URL(sanitizeURL(getNormalizedOriginPath(origin)));
847
- if (!isValidURL(origin) || !equals(originURL.origin, hostedURL.origin)) {
848
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
1083
+ if (isSameOrigin(url, requestOrigin)) {
1084
+ return extractPath(url);
849
1085
  }
850
- return sanitizeURL(originURL.pathname);
851
- }
852
- return "/";
1086
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
1087
+ return "/";
1088
+ };
1089
+ return validateURL(redirectTo ?? headers.get("Referer") ?? headers.get("Origin") ?? "/");
853
1090
  } catch (error) {
854
- if (isAuthSecurityError(error)) {
855
- throw error;
856
- }
857
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
1091
+ context?.logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED");
1092
+ return "/";
858
1093
  }
859
1094
  };
860
1095
 
@@ -883,13 +1118,17 @@ var signInAction = (oauth) => {
883
1118
  request,
884
1119
  params: { oauth: oauth2 },
885
1120
  searchParams: { redirectTo },
886
- context: { oauth: providers, cookies, trustedProxyHeaders, basePath }
1121
+ context
887
1122
  } = ctx;
1123
+ const { oauth: providers, cookies, logger } = context;
888
1124
  const state = generateSecure();
889
- const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
890
- const redirectToValue = createRedirectTo(request, redirectTo, trustedProxyHeaders);
1125
+ const redirectURI = await createRedirectURI(request, oauth2, context);
1126
+ const redirectToValue = await createRedirectTo(request, redirectTo, context);
891
1127
  const { codeVerifier, codeChallenge, method } = await createPKCE();
892
- const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
1128
+ const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method, logger);
1129
+ logger?.log("SIGN_IN_INITIATED", {
1130
+ structuredData: { oauth_provider: oauth2, code_challenge_method: method }
1131
+ });
893
1132
  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();
894
1133
  return Response.json(
895
1134
  { oauth: oauth2 },
@@ -928,9 +1167,14 @@ var getDefaultUserInfo = (profile) => {
928
1167
  image: profile?.image ?? profile?.picture
929
1168
  };
930
1169
  };
931
- var getUserInfo = async (oauthConfig, accessToken) => {
1170
+ var getUserInfo = async (oauthConfig, accessToken, logger) => {
932
1171
  const userinfoEndpoint = oauthConfig.userInfo;
933
1172
  try {
1173
+ logger?.log("OAUTH_USERINFO_REQUEST_INITIATED", {
1174
+ structuredData: {
1175
+ endpoint: userinfoEndpoint
1176
+ }
1177
+ });
934
1178
  const response = await fetchAsync(userinfoEndpoint, {
935
1179
  method: "GET",
936
1180
  headers: {
@@ -938,35 +1182,54 @@ var getUserInfo = async (oauthConfig, accessToken) => {
938
1182
  Authorization: `Bearer ${accessToken}`
939
1183
  }
940
1184
  });
1185
+ if (!response.ok) {
1186
+ logger?.log("OAUTH_USERINFO_INVALID_RESPONSE");
1187
+ throw new OAuthProtocolError("INVALID_REQUEST", "Invalid userinfo response format");
1188
+ }
941
1189
  const json = await response.json();
942
1190
  const { success, data } = OAuthErrorResponse.safeParse(json);
943
1191
  if (success) {
944
- throw new OAuthProtocolError(
945
- data.error,
946
- data?.error_description ?? "An error occurred while fetching user information."
947
- );
1192
+ logger?.log("OAUTH_USERINFO_ERROR", {
1193
+ message: "Error response received from OAuth userinfo endpoint",
1194
+ structuredData: {
1195
+ error: data.error,
1196
+ error_description: data.error_description ?? ""
1197
+ }
1198
+ });
1199
+ throw new OAuthProtocolError("INVALID_REQUEST", "An error was received from the OAuth userinfo endpoint.");
948
1200
  }
1201
+ logger?.log("OAUTH_USERINFO_SUCCESS");
949
1202
  return oauthConfig?.profile ? oauthConfig.profile(json) : getDefaultUserInfo(json);
950
1203
  } catch (error) {
951
1204
  if (isOAuthProtocolError(error)) {
952
1205
  throw error;
953
1206
  }
1207
+ logger?.log("OAUTH_USERINFO_REQUEST_FAILED");
954
1208
  if (isNativeError(error)) {
955
- throw new OAuthProtocolError("invalid_request", error.message, "", { cause: error });
1209
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information from OAuth provider", "", {
1210
+ cause: error
1211
+ });
956
1212
  }
957
- throw new OAuthProtocolError("invalid_request", "Failed to fetch user information.", "", { cause: error });
1213
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information", "", { cause: error });
958
1214
  }
959
1215
  };
960
1216
 
961
1217
  // src/actions/callback/access-token.ts
962
- var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) => {
1218
+ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier, logger) => {
963
1219
  const parsed = OAuthAccessToken.safeParse({ ...oauthConfig, redirectURI, code, codeVerifier });
964
1220
  if (!parsed.success) {
965
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
966
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
1221
+ logger?.log("INVALID_OAUTH_CONFIGURATION");
1222
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
967
1223
  }
968
1224
  const { accessToken, clientId, clientSecret, code: codeParsed, redirectURI: redirectParsed } = parsed.data;
969
1225
  try {
1226
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_INITIATED", {
1227
+ structuredData: {
1228
+ has_client_id: Boolean(clientId),
1229
+ redirect_uri: redirectParsed,
1230
+ grant_type: "authorization_code"
1231
+ }
1232
+ });
970
1233
  const response = await fetchAsync(accessToken, {
971
1234
  method: "POST",
972
1235
  headers: {
@@ -982,17 +1245,33 @@ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) =>
982
1245
  code_verifier: codeVerifier
983
1246
  }).toString()
984
1247
  });
1248
+ if (!response.ok) {
1249
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
1250
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response");
1251
+ }
985
1252
  const json = await response.json();
986
1253
  const token = OAuthAccessTokenResponse.safeParse(json);
987
1254
  if (!token.success) {
988
1255
  const { success, data } = OAuthAccessTokenErrorResponse.safeParse(json);
989
1256
  if (!success) {
990
- throw new OAuthProtocolError("INVALID_REQUEST", "Invalid access token response format");
1257
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
1258
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response format");
991
1259
  }
992
- throw new OAuthProtocolError(data.error, data?.error_description ?? "Failed to retrieve access token");
1260
+ logger?.log("OAUTH_ACCESS_TOKEN_ERROR", {
1261
+ structuredData: {
1262
+ error: data.error,
1263
+ error_description: data.error_description ?? ""
1264
+ }
1265
+ });
1266
+ throw new OAuthProtocolError("INVALID_ACCESS_TOKEN", "Failed to retrieve access token");
993
1267
  }
1268
+ logger?.log("OAUTH_ACCESS_TOKEN_SUCCESS");
994
1269
  return token.data;
995
1270
  } catch (error) {
1271
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_FAILED");
1272
+ if (error instanceof Error) {
1273
+ throw new OAuthProtocolError("server_error", "Failed to communicate with OAuth provider", "", { cause: error });
1274
+ }
996
1275
  throw error;
997
1276
  }
998
1277
  };
@@ -1014,10 +1293,23 @@ var callbackConfig = (oauth) => {
1014
1293
  },
1015
1294
  middlewares: [
1016
1295
  (ctx) => {
1017
- const response = OAuthAuthorizationErrorResponse.safeParse(ctx.searchParams);
1296
+ const {
1297
+ searchParams,
1298
+ context: { logger }
1299
+ } = ctx;
1300
+ const response = OAuthAuthorizationErrorResponse.safeParse(searchParams);
1018
1301
  if (response.success) {
1019
1302
  const { error, error_description } = response.data;
1020
- throw new OAuthProtocolError(error, error_description ?? "OAuth Authorization Error");
1303
+ const criticalAuthErrors = ["access_denied", "server_error"];
1304
+ const severity = criticalAuthErrors.includes(error.toLowerCase()) ? "critical" : "warning";
1305
+ logger?.log("OAUTH_AUTHORIZATION_ERROR", {
1306
+ severity,
1307
+ structuredData: {
1308
+ error,
1309
+ error_description: error_description ?? ""
1310
+ }
1311
+ });
1312
+ throw new OAuthProtocolError(error, error_description || "OAuth Authorization Error");
1021
1313
  }
1022
1314
  return ctx;
1023
1315
  }
@@ -1033,31 +1325,54 @@ var callbackAction = (oauth) => {
1033
1325
  request,
1034
1326
  params: { oauth: oauth2 },
1035
1327
  searchParams: { code, state },
1036
- context: { oauth: providers, cookies, jose }
1328
+ context
1037
1329
  } = ctx;
1330
+ const { oauth: providers, cookies, jose, logger, trustedOrigins } = context;
1038
1331
  const oauthConfig = providers[oauth2];
1039
1332
  const cookieState = getCookie(request, cookies.state.name);
1333
+ const codeVerifier = getCookie(request, cookies.codeVerifier.name);
1040
1334
  const cookieRedirectTo = getCookie(request, cookies.redirectTo.name);
1041
1335
  const cookieRedirectURI = getCookie(request, cookies.redirectURI.name);
1042
- const codeVerifier = getCookie(request, cookies.codeVerifier.name);
1043
- if (!equals(cookieState, state)) {
1336
+ if (!safeEquals(cookieState, state)) {
1337
+ logger?.log("MISMATCHING_STATE", {
1338
+ structuredData: {
1339
+ oauth_provider: oauth2
1340
+ }
1341
+ });
1044
1342
  throw new AuthSecurityError(
1045
1343
  "MISMATCHING_STATE",
1046
1344
  "The provided state passed in the OAuth response does not match the stored state."
1047
1345
  );
1048
1346
  }
1049
- const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier);
1050
- const sanitized = sanitizeURL(cookieRedirectTo);
1051
- if (!isValidRelativePath(sanitized)) {
1052
- throw new AuthSecurityError(
1053
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
1054
- "Invalid redirect path. Potential open redirect attack detected."
1055
- );
1347
+ const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier, logger);
1348
+ const origins = await getTrustedOrigins(request, trustedOrigins);
1349
+ const requestOrigin = await getOriginURL(request, context);
1350
+ if (!isRelativeURL(cookieRedirectTo)) {
1351
+ const isValid = origins.length > 0 ? isTrustedOrigin(cookieRedirectTo, origins) : isSameOrigin(cookieRedirectTo, requestOrigin);
1352
+ if (!isValid) {
1353
+ logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", {
1354
+ structuredData: {
1355
+ redirect_path: cookieRedirectTo,
1356
+ provider: oauth2,
1357
+ has_trusted_origins: origins.length > 0,
1358
+ request_origin: requestOrigin
1359
+ }
1360
+ });
1361
+ throw new AuthSecurityError(
1362
+ "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
1363
+ "Invalid redirect path. Potential open redirect attack detected."
1364
+ );
1365
+ }
1056
1366
  }
1057
- const userInfo = await getUserInfo(oauthConfig, accessToken.access_token);
1367
+ const userInfo = await getUserInfo(oauthConfig, accessToken.access_token, logger);
1058
1368
  const sessionCookie = await createSessionCookie(jose, userInfo);
1059
1369
  const csrfToken = await createCSRF(jose);
1060
- 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();
1370
+ logger?.log("OAUTH_CALLBACK_SUCCESS", {
1371
+ structuredData: {
1372
+ provider: oauth2
1373
+ }
1374
+ });
1375
+ 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();
1061
1376
  return Response.json({ oauth: oauth2 }, { status: 302, headers });
1062
1377
  },
1063
1378
  callbackConfig(oauth)
@@ -1069,16 +1384,18 @@ var import_router4 = require("@aura-stack/router");
1069
1384
  var sessionAction = (0, import_router4.createEndpoint)("GET", "/session", async (ctx) => {
1070
1385
  const {
1071
1386
  request,
1072
- context: { jose, cookies }
1387
+ context: { jose, cookies, logger }
1073
1388
  } = ctx;
1074
1389
  try {
1075
1390
  const session = getCookie(request, cookies.sessionToken.name);
1076
1391
  const decoded = await jose.decodeJWT(session);
1392
+ logger?.log("AUTH_SESSION_VALID");
1077
1393
  const { exp, iat, jti, nbf, ...user } = decoded;
1078
- const headers = new Headers(cacheControl);
1394
+ const headers = new Headers(secureApiHeaders);
1079
1395
  return Response.json({ user, expires: toISOString(exp * 1e3) }, { headers });
1080
1396
  } catch (error) {
1081
- const headers = new import_router4.HeadersBuilder(cacheControl).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1397
+ logger?.log("AUTH_SESSION_INVALID", { structuredData: { error_type: getErrorName(error) } });
1398
+ const headers = new import_router4.HeadersBuilder(secureApiHeaders).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1082
1399
  return Response.json({ authenticated: false, message: "Unauthorized" }, { status: 401, headers });
1083
1400
  }
1084
1401
  });
@@ -1102,30 +1419,54 @@ var signOutAction = (0, import_router5.createEndpoint)(
1102
1419
  request,
1103
1420
  headers,
1104
1421
  searchParams: { redirectTo },
1105
- context: { jose, cookies }
1422
+ context
1106
1423
  } = ctx;
1424
+ const { jose, cookies, logger } = context;
1107
1425
  const session = headers.getCookie(cookies.sessionToken.name);
1108
1426
  const csrfToken = headers.getCookie(cookies.csrfToken.name);
1109
1427
  const header = headers.getHeader("X-CSRF-Token");
1428
+ logger?.log("SIGN_OUT_ATTEMPT", {
1429
+ structuredData: {
1430
+ has_session: Boolean(session),
1431
+ has_csrf_token: Boolean(csrfToken),
1432
+ has_csrf_header: Boolean(header)
1433
+ }
1434
+ });
1110
1435
  if (!session) {
1436
+ logger?.log("SESSION_TOKEN_MISSING");
1111
1437
  throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
1112
1438
  }
1113
1439
  if (!csrfToken) {
1440
+ logger?.log("CSRF_TOKEN_MISSING");
1114
1441
  throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
1115
1442
  }
1116
1443
  if (!header) {
1117
- throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF header is missing.");
1444
+ logger?.log("CSRF_HEADER_MISSING");
1445
+ throw new AuthSecurityError("CSRF_HEADER_MISSING", "The CSRF header is missing.");
1446
+ }
1447
+ try {
1448
+ await verifyCSRF(jose, csrfToken, header);
1449
+ } catch (error) {
1450
+ logger?.log("CSRF_TOKEN_INVALID", { structuredData: { error_type: getErrorName(error) } });
1451
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "CSRF token verification failed");
1118
1452
  }
1119
- await verifyCSRF(jose, csrfToken, header);
1120
- await jose.decodeJWT(session);
1121
- const normalizedOriginPath = getNormalizedOriginPath(request.url);
1122
- const location = createRedirectTo(
1123
- new Request(normalizedOriginPath, {
1453
+ logger?.log("SIGN_OUT_CSRF_VERIFIED");
1454
+ try {
1455
+ await jose.decodeJWT(session);
1456
+ logger?.log("SIGN_OUT_SUCCESS");
1457
+ } catch (error) {
1458
+ logger?.log("INVALID_JWT_TOKEN", { structuredData: { error_type: getErrorName(error) } });
1459
+ }
1460
+ const baseURL = getBaseURL(request);
1461
+ const location = await createRedirectTo(
1462
+ new Request(baseURL, {
1124
1463
  headers: headers.toHeaders()
1125
1464
  }),
1126
- redirectTo
1465
+ redirectTo,
1466
+ context
1127
1467
  );
1128
- const headersList = new import_router5.HeadersBuilder(cacheControl).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1468
+ logger?.log("SIGN_OUT_REDIRECT", { structuredData: { location } });
1469
+ const headersList = new import_router5.HeadersBuilder(secureApiHeaders).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1129
1470
  return Response.json({ message: "Signed out successfully" }, { status: import_router5.statusCode.ACCEPTED, headers: headersList });
1130
1471
  },
1131
1472
  config
@@ -1143,33 +1484,338 @@ var getCSRFToken = (request, cookieName) => {
1143
1484
  var csrfTokenAction = (0, import_router6.createEndpoint)("GET", "/csrfToken", async (ctx) => {
1144
1485
  const {
1145
1486
  request,
1146
- context: { jose, cookies }
1487
+ context: { jose, cookies, logger }
1147
1488
  } = ctx;
1148
1489
  const token = getCSRFToken(request, cookies.csrfToken.name);
1490
+ logger?.log("CSRF_TOKEN_REQUESTED", { structuredData: { has_token: Boolean(token) } });
1149
1491
  const csrfToken = await createCSRF(jose, token);
1150
- const headers = new Headers(cacheControl);
1492
+ logger?.log("CSRF_TOKEN_ISSUED", { structuredData: { issued: Boolean(csrfToken) } });
1493
+ const headers = new Headers(secureApiHeaders);
1151
1494
  headers.append("Set-Cookie", setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes));
1152
1495
  return Response.json({ csrfToken }, { headers });
1153
1496
  });
1154
1497
 
1498
+ // src/logger.ts
1499
+ var logMessages = {
1500
+ ROUTER_INTERNAL_ERROR: {
1501
+ facility: 10,
1502
+ severity: "error",
1503
+ msgId: "ROUTER_INTERNAL_ERROR",
1504
+ message: "Unhandled router error while processing the request"
1505
+ },
1506
+ INVALID_REQUEST: {
1507
+ facility: 10,
1508
+ severity: "warning",
1509
+ msgId: "INVALID_REQUEST",
1510
+ message: "Request validation failed against the expected schema"
1511
+ },
1512
+ SERVER_ERROR: {
1513
+ facility: 10,
1514
+ severity: "error",
1515
+ msgId: "SERVER_ERROR",
1516
+ message: "Unexpected internal server error during authentication"
1517
+ },
1518
+ OAUTH_PROTOCOL_ERROR: {
1519
+ facility: 10,
1520
+ severity: "warning",
1521
+ msgId: "OAUTH_PROTOCOL_ERROR",
1522
+ message: "OAuth provider returned an invalid or unexpected protocol response"
1523
+ },
1524
+ OAUTH_AUTHORIZATION_ERROR: {
1525
+ facility: 10,
1526
+ severity: "error",
1527
+ msgId: "OAUTH_AUTHORIZATION_ERROR",
1528
+ message: "OAuth authorization request was rejected or failed"
1529
+ },
1530
+ INVALID_OAUTH_CONFIGURATION: {
1531
+ facility: 10,
1532
+ severity: "error",
1533
+ msgId: "INVALID_OAUTH_CONFIGURATION",
1534
+ message: "The OAuth provider configuration is invalid or incomplete"
1535
+ },
1536
+ OAUTH_ACCESS_TOKEN_REQUEST_INITIATED: {
1537
+ facility: 10,
1538
+ severity: "debug",
1539
+ msgId: "OAUTH_ACCESS_TOKEN_REQUEST_INITIATED",
1540
+ message: "Starting OAuth access token request to the provider"
1541
+ },
1542
+ INVALID_OAUTH_ACCESS_TOKEN_RESPONSE: {
1543
+ facility: 10,
1544
+ severity: "error",
1545
+ msgId: "INVALID_OAUTH_ACCESS_TOKEN_RESPONSE",
1546
+ message: "OAuth access token endpoint returned an invalid or malformed response"
1547
+ },
1548
+ OAUTH_ACCESS_TOKEN_ERROR: {
1549
+ facility: 10,
1550
+ severity: "error",
1551
+ msgId: "OAUTH_ACCESS_TOKEN_ERROR",
1552
+ message: "OAuth access token endpoint returned an error response"
1553
+ },
1554
+ OAUTH_ACCESS_TOKEN_SUCCESS: {
1555
+ facility: 10,
1556
+ severity: "info",
1557
+ msgId: "OAUTH_ACCESS_TOKEN_SUCCESS",
1558
+ message: "Successfully retrieved OAuth access token from the provider"
1559
+ },
1560
+ OAUTH_ACCESS_TOKEN_REQUEST_FAILED: {
1561
+ facility: 10,
1562
+ severity: "error",
1563
+ msgId: "OAUTH_ACCESS_TOKEN_REQUEST_FAILED",
1564
+ message: "Network or server error while requesting OAuth access token"
1565
+ },
1566
+ OAUTH_USERINFO_REQUEST_INITIATED: {
1567
+ facility: 10,
1568
+ severity: "debug",
1569
+ msgId: "OAUTH_USERINFO_REQUEST_INITIATED",
1570
+ message: "Starting OAuth userinfo request to the provider"
1571
+ },
1572
+ OAUTH_USERINFO_INVALID_RESPONSE: {
1573
+ facility: 10,
1574
+ severity: "error",
1575
+ msgId: "OAUTH_USERINFO_INVALID_RESPONSE",
1576
+ message: "OAuth userinfo endpoint returned an invalid or malformed response"
1577
+ },
1578
+ OAUTH_USERINFO_ERROR: {
1579
+ facility: 10,
1580
+ severity: "error",
1581
+ msgId: "OAUTH_USERINFO_ERROR",
1582
+ message: "OAuth userinfo endpoint returned an error response"
1583
+ },
1584
+ OAUTH_USERINFO_SUCCESS: {
1585
+ facility: 10,
1586
+ severity: "info",
1587
+ msgId: "OAUTH_USERINFO_SUCCESS",
1588
+ message: "Successfully retrieved user information from the OAuth provider"
1589
+ },
1590
+ OAUTH_USERINFO_REQUEST_FAILED: {
1591
+ facility: 10,
1592
+ severity: "error",
1593
+ msgId: "OAUTH_USERINFO_REQUEST_FAILED",
1594
+ message: "Network or server error while requesting user information from the OAuth provider"
1595
+ },
1596
+ OAUTH_CALLBACK_SUCCESS: {
1597
+ facility: 4,
1598
+ severity: "info",
1599
+ msgId: "OAUTH_CALLBACK_SUCCESS",
1600
+ message: "OAuth callback completed successfully and session was created"
1601
+ },
1602
+ MISMATCHING_STATE: {
1603
+ facility: 4,
1604
+ severity: "critical",
1605
+ msgId: "MISMATCHING_STATE",
1606
+ message: "OAuth response state parameter does not match the stored state value"
1607
+ },
1608
+ POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED: {
1609
+ facility: 4,
1610
+ severity: "critical",
1611
+ msgId: "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
1612
+ message: "Blocked redirect to untrusted or external URL (potential open redirect attack)"
1613
+ },
1614
+ OPEN_REDIRECT_ATTACK: {
1615
+ facility: 4,
1616
+ severity: "warning",
1617
+ msgId: "OPEN_REDIRECT_ATTACK",
1618
+ message: "Detected redirect target that does not match the trusted origin"
1619
+ },
1620
+ SESSION_TOKEN_MISSING: {
1621
+ facility: 4,
1622
+ severity: "warning",
1623
+ msgId: "SESSION_TOKEN_MISSING",
1624
+ message: "Session cookie is missing from the request"
1625
+ },
1626
+ CSRF_TOKEN_MISSING: {
1627
+ facility: 4,
1628
+ severity: "warning",
1629
+ msgId: "CSRF_TOKEN_MISSING",
1630
+ message: "CSRF token cookie is missing from the request"
1631
+ },
1632
+ CSRF_HEADER_MISSING: {
1633
+ facility: 4,
1634
+ severity: "warning",
1635
+ msgId: "CSRF_HEADER_MISSING",
1636
+ message: "CSRF header is missing from the request"
1637
+ },
1638
+ CSRF_TOKEN_INVALID: {
1639
+ facility: 4,
1640
+ severity: "error",
1641
+ msgId: "CSRF_TOKEN_INVALID",
1642
+ message: "CSRF token verification failed or token is invalid"
1643
+ },
1644
+ SIGN_IN_INITIATED: {
1645
+ facility: 4,
1646
+ severity: "info",
1647
+ msgId: "SIGN_IN_INITIATED",
1648
+ message: "Starting OAuth sign-in flow for the selected provider"
1649
+ },
1650
+ SIGN_OUT_ATTEMPT: {
1651
+ facility: 4,
1652
+ severity: "debug",
1653
+ msgId: "SIGN_OUT_ATTEMPT",
1654
+ message: "Received sign-out request from client"
1655
+ },
1656
+ SIGN_OUT_CSRF_VERIFIED: {
1657
+ facility: 4,
1658
+ severity: "info",
1659
+ msgId: "SIGN_OUT_CSRF_VERIFIED",
1660
+ message: "CSRF token was successfully verified during sign-out"
1661
+ },
1662
+ SIGN_OUT_SUCCESS: {
1663
+ facility: 4,
1664
+ severity: "info",
1665
+ msgId: "SIGN_OUT_SUCCESS",
1666
+ message: "User session was cleared and sign-out completed successfully"
1667
+ },
1668
+ SIGN_OUT_REDIRECT: {
1669
+ facility: 4,
1670
+ severity: "debug",
1671
+ msgId: "SIGN_OUT_REDIRECT",
1672
+ message: "Redirecting client after successful sign-out"
1673
+ },
1674
+ AUTH_SESSION_VALID: {
1675
+ facility: 4,
1676
+ severity: "info",
1677
+ msgId: "AUTH_SESSION_VALID",
1678
+ message: "Session token is valid and user session was returned"
1679
+ },
1680
+ AUTH_SESSION_INVALID: {
1681
+ facility: 4,
1682
+ severity: "notice",
1683
+ msgId: "AUTH_SESSION_INVALID",
1684
+ message: "Session token is missing, expired, or invalid"
1685
+ },
1686
+ INVALID_JWT_TOKEN: {
1687
+ facility: 4,
1688
+ severity: "warning",
1689
+ msgId: "INVALID_JWT_TOKEN",
1690
+ message: "JWT session token failed validation during sign-out"
1691
+ },
1692
+ CSRF_TOKEN_REQUESTED: {
1693
+ facility: 4,
1694
+ severity: "debug",
1695
+ msgId: "CSRF_TOKEN_REQUESTED",
1696
+ message: "Client requested a CSRF token"
1697
+ },
1698
+ CSRF_TOKEN_ISSUED: {
1699
+ facility: 4,
1700
+ severity: "debug",
1701
+ msgId: "CSRF_TOKEN_ISSUED",
1702
+ message: "Issued a new CSRF token to the client"
1703
+ },
1704
+ INVALID_URL: {
1705
+ facility: 10,
1706
+ severity: "error",
1707
+ msgId: "INVALID_URL",
1708
+ message: "Derived origin URL is invalid or malformed"
1709
+ },
1710
+ COOKIE_HTTPONLY_DISABLED: {
1711
+ facility: 10,
1712
+ severity: "critical",
1713
+ msgId: "COOKIE_HTTPONLY_DISABLED",
1714
+ message: "Cookie is configured without HttpOnly. This allows JavaScript access via document.cookie and increases XSS exposure."
1715
+ },
1716
+ COOKIE_WILDCARD_DOMAIN: {
1717
+ facility: 10,
1718
+ severity: "critical",
1719
+ msgId: "COOKIE_WILDCARD_DOMAIN",
1720
+ message: "Cookie 'Domain' is set to a wildcard, which is insecure and should be avoided."
1721
+ },
1722
+ COOKIE_SECURE_DISABLED: {
1723
+ facility: 10,
1724
+ severity: "warning",
1725
+ msgId: "COOKIE_SECURE_DISABLED",
1726
+ message: "Cookie is configured with 'Secure' but the request is not HTTPS. The 'Secure' attribute will be ignored by the browser."
1727
+ },
1728
+ COOKIE_SAMESITE_NONE_WITHOUT_SECURE: {
1729
+ facility: 10,
1730
+ severity: "warning",
1731
+ msgId: "COOKIE_SAMESITE_NONE_WITHOUT_SECURE",
1732
+ message: "Cookie uses SameSite=None without Secure. Falling back to SameSite=Lax for safer defaults."
1733
+ },
1734
+ COOKIE_INSECURE_IN_PRODUCTION: {
1735
+ facility: 10,
1736
+ severity: "critical",
1737
+ msgId: "COOKIE_INSECURE_IN_PRODUCTION",
1738
+ message: "Cookies are being served over an insecure connection in production, which is a serious security risk."
1739
+ },
1740
+ COOKIE_HOST_STRATEGY_INSECURE: {
1741
+ facility: 10,
1742
+ severity: "critical",
1743
+ msgId: "COOKIE_HOST_STRATEGY_INSECURE",
1744
+ message: "__Host- cookies require a secure HTTPS context. Falling back to standard cookie settings."
1745
+ },
1746
+ UNTRUSTED_ORIGIN: {
1747
+ facility: 10,
1748
+ severity: "error",
1749
+ msgId: "UNTRUSTED_ORIGIN",
1750
+ message: "The constructed origin URL is not trusted."
1751
+ }
1752
+ };
1753
+ var createLogEntry = (key, overrides) => {
1754
+ const message = logMessages[key];
1755
+ return {
1756
+ ...message,
1757
+ ...overrides
1758
+ };
1759
+ };
1760
+
1155
1761
  // src/index.ts
1762
+ var logLevelToSeverity = {
1763
+ debug: ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"],
1764
+ info: ["info", "notice", "warning", "error", "critical", "alert", "emergency"],
1765
+ warn: ["warning", "error", "critical", "alert", "emergency"],
1766
+ error: ["error", "critical", "alert", "emergency"]
1767
+ };
1768
+ var createLoggerProxy = (logger) => {
1769
+ if (!logger) return void 0;
1770
+ const level = logger.level;
1771
+ const allowedSeverities = logLevelToSeverity[level] ?? [];
1772
+ const internalLogger = {
1773
+ level,
1774
+ log(key, overrides) {
1775
+ const entry = createLogEntry(key, overrides);
1776
+ if (!allowedSeverities.includes(entry.severity)) return entry;
1777
+ logger.log({
1778
+ timestamp: entry.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
1779
+ appName: entry.appName ?? "aura-auth",
1780
+ hostname: entry.hostname ?? "aura-auth",
1781
+ ...entry
1782
+ });
1783
+ return entry;
1784
+ }
1785
+ };
1786
+ return internalLogger;
1787
+ };
1156
1788
  var createInternalConfig = (authConfig) => {
1157
1789
  const useSecure = authConfig?.trustedProxyHeaders ?? false;
1790
+ const logger = authConfig?.logger;
1791
+ const internalLogger = createLoggerProxy(logger);
1158
1792
  return {
1159
1793
  basePath: authConfig?.basePath ?? "/auth",
1160
- onError: onErrorHandler,
1794
+ onError: createErrorHandler(internalLogger),
1161
1795
  context: {
1162
1796
  oauth: createBuiltInOAuthProviders(authConfig?.oauth),
1163
- cookies: createCookieStore(useSecure, authConfig?.cookies?.prefix, authConfig?.cookies?.overrides ?? {}),
1797
+ cookies: createCookieStore(
1798
+ useSecure,
1799
+ authConfig?.cookies?.prefix,
1800
+ authConfig?.cookies?.overrides ?? {},
1801
+ internalLogger
1802
+ ),
1164
1803
  jose: createJoseInstance(authConfig?.secret),
1165
1804
  secret: authConfig?.secret,
1166
1805
  basePath: authConfig?.basePath ?? "/auth",
1167
- trustedProxyHeaders: useSecure
1806
+ trustedProxyHeaders: useSecure,
1807
+ trustedOrigins: authConfig?.trustedOrigins,
1808
+ logger: internalLogger
1168
1809
  },
1169
1810
  middlewares: [
1170
1811
  (ctx) => {
1171
1812
  const useSecure2 = useSecureCookies(ctx.request, ctx.context.trustedProxyHeaders);
1172
- const cookies = createCookieStore(useSecure2, authConfig?.cookies?.prefix, authConfig?.cookies?.overrides ?? {});
1813
+ const cookies = createCookieStore(
1814
+ useSecure2,
1815
+ authConfig?.cookies?.prefix,
1816
+ authConfig?.cookies?.overrides ?? {},
1817
+ internalLogger
1818
+ );
1173
1819
  ctx.context.cookies = cookies;
1174
1820
  return ctx;
1175
1821
  }
@@ -1189,6 +1835,5 @@ var createAuth = (authConfig) => {
1189
1835
  };
1190
1836
  // Annotate the CommonJS export names for ESM import in node:
1191
1837
  0 && (module.exports = {
1192
- createAuth,
1193
- createClient
1838
+ createAuth
1194
1839
  });