@aura-stack/auth 0.4.0-rc.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/@types/index.d.ts +4 -3
  2. package/dist/@types/router.d.cjs +0 -17
  3. package/dist/@types/router.d.d.ts +3 -2
  4. package/dist/@types/router.d.js +0 -1
  5. package/dist/actions/callback/access-token.cjs +40 -25
  6. package/dist/actions/callback/access-token.d.ts +4 -3
  7. package/dist/actions/callback/access-token.js +3 -4
  8. package/dist/actions/callback/callback.cjs +287 -77
  9. package/dist/actions/callback/callback.d.ts +5 -26
  10. package/dist/actions/callback/callback.js +13 -10
  11. package/dist/actions/callback/userinfo.cjs +68 -7
  12. package/dist/actions/callback/userinfo.d.ts +4 -3
  13. package/dist/actions/callback/userinfo.js +8 -6
  14. package/dist/actions/csrfToken/csrfToken.cjs +63 -4
  15. package/dist/actions/csrfToken/csrfToken.d.ts +1 -3
  16. package/dist/actions/csrfToken/csrfToken.js +8 -6
  17. package/dist/actions/index.cjs +400 -175
  18. package/dist/actions/index.d.ts +3 -2
  19. package/dist/actions/index.js +21 -19
  20. package/dist/actions/session/session.cjs +40 -11
  21. package/dist/actions/session/session.d.ts +1 -3
  22. package/dist/actions/session/session.js +4 -4
  23. package/dist/actions/signIn/authorization.cjs +171 -132
  24. package/dist/actions/signIn/authorization.d.ts +21 -11
  25. package/dist/actions/signIn/authorization.js +8 -6
  26. package/dist/actions/signIn/signIn.cjs +220 -113
  27. package/dist/actions/signIn/signIn.d.ts +5 -25
  28. package/dist/actions/signIn/signIn.js +9 -7
  29. package/dist/actions/signOut/signOut.cjs +268 -119
  30. package/dist/actions/signOut/signOut.d.ts +1 -9
  31. package/dist/actions/signOut/signOut.js +10 -8
  32. package/dist/assert.cjs +117 -5
  33. package/dist/assert.d.ts +22 -3
  34. package/dist/assert.js +17 -3
  35. package/dist/chunk-4EKY7655.js +123 -0
  36. package/dist/chunk-4MYWAOLG.js +31 -0
  37. package/dist/chunk-4YHJ4IEQ.js +25 -0
  38. package/dist/chunk-54CZPKR4.js +25 -0
  39. package/dist/chunk-5LZ7TOM3.js +25 -0
  40. package/dist/{chunk-W6LG7BFW.js → chunk-5W4BRQYG.js} +24 -20
  41. package/dist/chunk-6MXFPFR3.js +143 -0
  42. package/dist/{chunk-3EUWD5BB.js → chunk-7QF22LHP.js} +13 -9
  43. package/dist/chunk-ALG3GIV4.js +95 -0
  44. package/dist/chunk-E6G5YCI6.js +25 -0
  45. package/dist/chunk-EBAMFRB7.js +34 -0
  46. package/dist/chunk-EEE7UM5T.js +25 -0
  47. package/dist/{chunk-TLE4PXY3.js → chunk-FRJFWTOY.js} +38 -7
  48. package/dist/chunk-FW4W3REU.js +25 -0
  49. package/dist/{chunk-HT4YLL7N.js → chunk-ICAZ4OVS.js} +10 -8
  50. package/dist/chunk-IPKO6UQN.js +25 -0
  51. package/dist/{chunk-YRCB5FLE.js → chunk-KJBAQZX2.js} +13 -0
  52. package/dist/chunk-KMMAZFSJ.js +25 -0
  53. package/dist/chunk-LDU7A2JE.js +25 -0
  54. package/dist/{chunk-N2APGLXA.js → chunk-NUDITUKX.js} +18 -16
  55. package/dist/chunk-OVHNRULD.js +33 -0
  56. package/dist/{chunk-JVFTCTTE.js → chunk-PHFH2MGS.js} +12 -9
  57. package/dist/chunk-QQVSRXGX.js +149 -0
  58. package/dist/chunk-TM5IPSNF.js +113 -0
  59. package/dist/{chunk-GA2SMTJO.js → chunk-TZB6MUXN.js} +33 -13
  60. package/dist/chunk-VNCNJKS2.js +267 -0
  61. package/dist/{chunk-IVET23KF.js → chunk-XGLBNXL4.js} +31 -14
  62. package/dist/chunk-XUP6KKNG.js +106 -0
  63. package/dist/cookie.cjs +24 -20
  64. package/dist/cookie.d.ts +4 -3
  65. package/dist/cookie.js +1 -1
  66. package/dist/env.cjs +56 -0
  67. package/dist/env.d.ts +7 -0
  68. package/dist/env.js +6 -0
  69. package/dist/errors.d.ts +4 -3
  70. package/dist/headers.cjs +28 -2
  71. package/dist/headers.d.ts +25 -1
  72. package/dist/headers.js +9 -3
  73. package/dist/{index-B8jeIElf.d.ts → index-CSyIJmCM.d.ts} +373 -45
  74. package/dist/index.cjs +1128 -483
  75. package/dist/index.d.ts +7 -67
  76. package/dist/index.js +83 -42
  77. package/dist/jose.cjs +62 -25
  78. package/dist/jose.d.ts +7 -5
  79. package/dist/jose.js +8 -6
  80. package/dist/logger.cjs +292 -0
  81. package/dist/logger.d.ts +8 -0
  82. package/dist/logger.js +8 -0
  83. package/dist/oauth/bitbucket.cjs +19 -15
  84. package/dist/oauth/bitbucket.d.ts +3 -2
  85. package/dist/oauth/bitbucket.js +1 -1
  86. package/dist/oauth/discord.cjs +27 -24
  87. package/dist/oauth/discord.d.ts +3 -2
  88. package/dist/oauth/discord.js +1 -1
  89. package/dist/oauth/figma.cjs +19 -16
  90. package/dist/oauth/figma.d.ts +3 -2
  91. package/dist/oauth/figma.js +1 -1
  92. package/dist/oauth/github.cjs +19 -8
  93. package/dist/oauth/github.d.ts +3 -2
  94. package/dist/oauth/github.js +1 -1
  95. package/dist/oauth/gitlab.cjs +19 -16
  96. package/dist/oauth/gitlab.d.ts +3 -2
  97. package/dist/oauth/gitlab.js +1 -1
  98. package/dist/oauth/index.cjs +266 -166
  99. package/dist/oauth/index.d.ts +3 -2
  100. package/dist/oauth/index.js +22 -21
  101. package/dist/oauth/mailchimp.cjs +19 -16
  102. package/dist/oauth/mailchimp.d.ts +3 -2
  103. package/dist/oauth/mailchimp.js +1 -1
  104. package/dist/oauth/pinterest.cjs +19 -16
  105. package/dist/oauth/pinterest.d.ts +3 -2
  106. package/dist/oauth/pinterest.js +1 -1
  107. package/dist/oauth/spotify.cjs +19 -16
  108. package/dist/oauth/spotify.d.ts +3 -2
  109. package/dist/oauth/spotify.js +1 -1
  110. package/dist/oauth/strava.cjs +19 -16
  111. package/dist/oauth/strava.d.ts +3 -2
  112. package/dist/oauth/strava.js +1 -1
  113. package/dist/oauth/x.cjs +19 -16
  114. package/dist/oauth/x.d.ts +3 -2
  115. package/dist/oauth/x.js +1 -1
  116. package/dist/schemas.cjs +16 -2
  117. package/dist/schemas.d.ts +17 -1
  118. package/dist/schemas.js +5 -3
  119. package/dist/secure.cjs +58 -16
  120. package/dist/secure.d.ts +4 -10
  121. package/dist/secure.js +5 -5
  122. package/dist/utils.cjs +94 -87
  123. package/dist/utils.d.ts +9 -39
  124. package/dist/utils.js +11 -9
  125. package/package.json +3 -4
  126. package/dist/chunk-42XB3YCW.js +0 -22
  127. package/dist/chunk-6R2YZ4AC.js +0 -22
  128. package/dist/chunk-A3N4PVAT.js +0 -70
  129. package/dist/chunk-B737EUJV.js +0 -22
  130. package/dist/chunk-CXLATHS5.js +0 -143
  131. package/dist/chunk-DIVDFNAP.js +0 -0
  132. package/dist/chunk-E3OXBRYF.js +0 -22
  133. package/dist/chunk-EIL2FPSS.js +0 -22
  134. package/dist/chunk-EMKJA2GJ.js +0 -89
  135. package/dist/chunk-FIPU4MLT.js +0 -21
  136. package/dist/chunk-FKRDCWBF.js +0 -22
  137. package/dist/chunk-HP34YGGJ.js +0 -22
  138. package/dist/chunk-IKHPGFCW.js +0 -14
  139. package/dist/chunk-IUYZQTJV.js +0 -30
  140. package/dist/chunk-KRNOMBXQ.js +0 -22
  141. package/dist/chunk-KSWLO5ZU.js +0 -102
  142. package/dist/chunk-N4SX7TZT.js +0 -96
  143. package/dist/chunk-STHEPPUZ.js +0 -11
@@ -43,6 +43,26 @@ var cacheControl = {
43
43
  Expires: "0",
44
44
  Vary: "Cookie"
45
45
  };
46
+ var contentSecurityPolicy = {
47
+ "Content-Security-Policy": [
48
+ "default-src 'none'",
49
+ "script-src 'self'",
50
+ "frame-src 'none'",
51
+ "object-src 'none'",
52
+ "frame-ancestors 'none'",
53
+ "base-uri 'none'"
54
+ ].join("; ")
55
+ };
56
+ var secureHeaders = {
57
+ "X-Content-Type-Options": "nosniff",
58
+ "X-Frame-Options": "DENY",
59
+ "Referrer-Policy": "strict-origin-when-cross-origin"
60
+ };
61
+ var secureApiHeaders = {
62
+ ...cacheControl,
63
+ ...contentSecurityPolicy,
64
+ ...secureHeaders
65
+ };
46
66
 
47
67
  // src/secure.ts
48
68
  var import_crypto = __toESM(require("crypto"), 1);
@@ -71,9 +91,6 @@ var AuthSecurityError = class extends Error {
71
91
  Error.captureStackTrace(this, new.target);
72
92
  }
73
93
  };
74
- var isAuthSecurityError = (error) => {
75
- return error instanceof AuthSecurityError;
76
- };
77
94
 
78
95
  // src/utils.ts
79
96
  var toSnakeCase = (str) => {
@@ -92,71 +109,132 @@ var equals = (a, b) => {
92
109
  if (a === null || b === null || a === void 0 || b === void 0) return false;
93
110
  return a === b;
94
111
  };
95
- var sanitizeURL = (url) => {
112
+ var extractPath = (url) => {
113
+ const pathRegex = /^https?:\/\/[a-zA-Z0-9_\-\.]+(:\d+)?(\/.*)$/;
114
+ const match = url.match(pathRegex);
115
+ return match && match[2] ? match[2] : "/";
116
+ };
117
+
118
+ // src/assert.ts
119
+ var unsafeChars = [
120
+ "<",
121
+ ">",
122
+ '"',
123
+ "`",
124
+ " ",
125
+ "\r",
126
+ "\n",
127
+ " ",
128
+ "\\",
129
+ "%2F",
130
+ "%5C",
131
+ "%2f",
132
+ "%5c",
133
+ "\r\n",
134
+ "%0A",
135
+ "%0D",
136
+ "%0a",
137
+ "%0d",
138
+ "..",
139
+ "//",
140
+ "///",
141
+ "...",
142
+ "%20",
143
+ "\0"
144
+ ];
145
+ var isValidURL = (value) => {
146
+ if (!new RegExp(/^https?:\/\/[^/]/).test(value)) {
147
+ return false;
148
+ }
149
+ const match = value.match(/^(https?:\/\/)(.*)$/);
150
+ if (!match) return false;
151
+ const rest = match[2];
152
+ for (const char of unsafeChars) {
153
+ if (rest.includes(char)) return false;
154
+ }
155
+ const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()?#*+,;=:@-]*)*\/?$/;
156
+ return regex.test(match[0]);
157
+ };
158
+ var isRelativeURL = (value) => {
159
+ if (value.length > 100) return false;
160
+ for (const char of unsafeChars) {
161
+ if (value.includes(char)) return false;
162
+ }
163
+ const regex = /^\/[a-zA-Z0-9\-_\/.?&=#]*\/?$/;
164
+ return regex.test(value);
165
+ };
166
+ var isSameOrigin = (origin, expected) => {
167
+ const originURL = new URL(origin);
168
+ const expectedURL = new URL(expected);
169
+ return equals(originURL.origin, expectedURL.origin);
170
+ };
171
+ var patternToRegex = (pattern) => {
96
172
  try {
97
- let decodedURL = decodeURIComponent(url).trim();
98
- const protocolMatch = decodedURL.match(/^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)/);
99
- let protocol = "";
100
- let rest = decodedURL;
101
- if (protocolMatch) {
102
- protocol = protocolMatch[1];
103
- rest = decodedURL.slice(protocol.length);
104
- const slashIndex = rest.indexOf("/");
105
- if (slashIndex === -1) {
106
- return protocol + rest;
107
- }
108
- const domain = rest.slice(0, slashIndex);
109
- let path = rest.slice(slashIndex).replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
110
- if (path !== "/" && path.endsWith("/")) {
111
- path = path.replace(/\/+$/, "/");
112
- } else if (path !== "/") {
113
- path = path.replace(/\/+$/, "");
114
- }
115
- return protocol + domain + path;
116
- }
117
- let sanitized = decodedURL.replace(/\/\.\.\//g, "/").replace(/\/\.\.$/, "").replace(/\.{2,}/g, "").replace(/\/{2,}/g, "/");
118
- if (sanitized !== "/" && sanitized.endsWith("/")) {
119
- sanitized = sanitized.replace(/\/+$/, "/");
120
- } else if (sanitized !== "/") {
121
- sanitized = sanitized.replace(/\/+$/, "");
122
- }
123
- return sanitized;
173
+ if (pattern.length > 2048) return null;
174
+ pattern = pattern.replace(/\\/g, "");
175
+ const match = pattern.match(/^(https?):\/\/([a-zA-Z0-9.*-]{1,253})(?::(\d{1,5}|\*))?(?:\/.*)?$/);
176
+ if (!match) return null;
177
+ const [, protocol, host, port] = match;
178
+ const hasWildcard = host.includes("*");
179
+ if (hasWildcard && !host.startsWith("*.")) return null;
180
+ if (hasWildcard && host.slice(2).includes("*")) return null;
181
+ const domain = hasWildcard ? host.slice(2) : host;
182
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
183
+ const hostRegex = hasWildcard ? `[^.]+\\.${escapedDomain}` : escapedDomain;
184
+ const portRegex = port === "*" ? ":\\d{1,5}" : port ? `:${port}` : "";
185
+ return new RegExp(`^${protocol}:\\/\\/${hostRegex}${portRegex}$`);
124
186
  } catch {
125
- return url.trim();
187
+ return null;
126
188
  }
127
189
  };
128
- var getNormalizedOriginPath = (path) => {
190
+ var isTrustedOrigin = (url, trustedOrigins) => {
191
+ if (!isValidURL(url) || trustedOrigins.length === 0) return false;
129
192
  try {
130
- const url = new URL(path);
131
- url.hash = "";
132
- url.search = "";
133
- return `${url.origin}${url.pathname}`;
193
+ const urlOrigin = new URL(url).origin;
194
+ for (const pattern of trustedOrigins) {
195
+ const regex = patternToRegex(pattern);
196
+ if (regex?.test(urlOrigin)) return true;
197
+ try {
198
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return true;
199
+ } catch {
200
+ }
201
+ }
134
202
  } catch {
135
- return sanitizeURL(path);
136
203
  }
204
+ return false;
137
205
  };
138
- var formatZodError = (error) => {
139
- if (!error.issues || error.issues.length === 0) {
140
- return {};
141
- }
142
- return error.issues.reduce((previous, issue) => {
143
- const key = issue.path.join(".");
144
- return {
145
- ...previous,
146
- [key]: {
147
- code: issue.code,
148
- message: issue.message
149
- }
206
+
207
+ // src/env.ts
208
+ var import_meta = {};
209
+ var env = new Proxy({}, {
210
+ get(_, prop) {
211
+ if (typeof prop !== "string") return void 0;
212
+ const hasProperty = (process2) => {
213
+ return process2 && Object.prototype.hasOwnProperty.call(process2, prop);
150
214
  };
151
- }, {});
152
- };
215
+ try {
216
+ if (typeof process !== "undefined" && hasProperty(process.env)) {
217
+ return process.env[prop];
218
+ }
219
+ if (typeof import_meta !== "undefined" && hasProperty(import_meta.env)) {
220
+ return import_meta.env[prop];
221
+ }
222
+ if (typeof Deno !== "undefined" && Deno.env?.get) {
223
+ return Deno.env.get(prop);
224
+ }
225
+ if (typeof Bun !== "undefined" && hasProperty(Bun.env)) {
226
+ return Bun.env[prop];
227
+ }
228
+ const globalValue = globalThis[prop];
229
+ return typeof globalValue === "string" ? globalValue : void 0;
230
+ } catch {
231
+ return void 0;
232
+ }
233
+ }
234
+ });
153
235
 
154
- // src/assert.ts
155
- var isValidURL = (value) => {
156
- if (value.includes("\r\n") || value.includes("\n") || value.includes("\r")) return false;
157
- const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()*+,;=:@-]*)*\/?$/;
158
- return regex.test(value);
159
- };
236
+ // src/jose.ts
237
+ var import_jose = require("@aura-stack/jose");
160
238
 
161
239
  // src/secure.ts
162
240
  var generateSecure = (length = 32) => {
@@ -166,13 +244,29 @@ var createHash = (data, base = "hex") => {
166
244
  return import_crypto.default.createHash("sha256").update(data).digest().toString(base);
167
245
  };
168
246
  var createPKCE = async (verifier) => {
169
- const codeVerifier = verifier ?? generateSecure(86);
247
+ const byteLength = verifier ? void 0 : Math.floor(Math.random() * (96 - 32 + 1) + 32);
248
+ const codeVerifier = verifier ?? generateSecure(byteLength ?? 64);
249
+ if (codeVerifier.length < 43 || codeVerifier.length > 128) {
250
+ throw new AuthSecurityError("PKCE_VERIFIER_INVALID", "The code verifier must be between 43 and 128 characters in length.");
251
+ }
170
252
  const codeChallenge = createHash(codeVerifier, "base64url");
171
253
  return { codeVerifier, codeChallenge, method: "S256" };
172
254
  };
173
255
 
174
256
  // src/schemas.ts
175
257
  var import_zod = require("zod");
258
+ var OAuthProviderCredentialsSchema = (0, import_zod.object)({
259
+ id: (0, import_zod.string)(),
260
+ name: (0, import_zod.string)(),
261
+ authorizeURL: (0, import_zod.string)().url(),
262
+ accessToken: (0, import_zod.string)().url(),
263
+ scope: (0, import_zod.string)(),
264
+ userInfo: (0, import_zod.string)().url(),
265
+ responseType: (0, import_zod.enum)(["code", "token", "id_token"]),
266
+ clientId: (0, import_zod.string)(),
267
+ clientSecret: (0, import_zod.string)(),
268
+ profile: import_zod.z.function().optional()
269
+ });
176
270
  var OAuthProviderConfigSchema = (0, import_zod.object)({
177
271
  authorizeURL: (0, import_zod.string)().url(),
178
272
  accessToken: (0, import_zod.string)().url(),
@@ -240,73 +334,82 @@ var OAuthEnvSchema = (0, import_zod.object)({
240
334
  });
241
335
 
242
336
  // src/actions/signIn/authorization.ts
243
- var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod) => {
337
+ var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod, logger) => {
244
338
  const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
245
339
  if (!parsed.success) {
246
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
247
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
340
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
341
+ structuredData: {
342
+ scope: oauthConfig.scope,
343
+ redirect_uri: redirectURI,
344
+ has_state: Boolean(state),
345
+ has_code_challenge: Boolean(codeChallenge),
346
+ code_challenge_method: codeChallengeMethod
347
+ }
348
+ });
349
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
248
350
  }
249
351
  const { authorizeURL, ...options2 } = parsed.data;
250
352
  const { userInfo, accessToken, clientSecret, ...required } = options2;
251
353
  const searchParams = new URLSearchParams(toCastCase(required));
252
354
  return `${authorizeURL}?${searchParams}`;
253
355
  };
254
- var getOriginURL = (request, trustedProxyHeaders) => {
356
+ var getTrustedOrigins = async (request, trustedOrigins) => {
357
+ if (!trustedOrigins) return [];
358
+ const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins;
359
+ return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
360
+ };
361
+ var getOriginURL = async (request, context) => {
255
362
  const headers = request.headers;
256
- if (trustedProxyHeaders) {
257
- const protocol = headers.get("X-Forwarded-Proto") ?? headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? "http";
258
- const host = headers.get("X-Forwarded-Host") ?? headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? null;
259
- return new URL(`${protocol}://${host}${getNormalizedOriginPath(new URL(request.url).pathname)}`);
260
- } else {
261
- return new URL(getNormalizedOriginPath(request.url));
363
+ let origin = new URL(request.url).origin;
364
+ const trustedOrigins = await getTrustedOrigins(request, context?.trustedOrigins);
365
+ trustedOrigins.push(origin);
366
+ if (context?.trustedProxyHeaders) {
367
+ const protocol = headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Proto") ?? "http";
368
+ const host = headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Host") ?? null;
369
+ origin = `${protocol}://${host}`;
370
+ }
371
+ if (!isTrustedOrigin(origin, trustedOrigins)) {
372
+ context?.logger?.log("UNTRUSTED_ORIGIN", { structuredData: { origin } });
373
+ throw new AuthInternalError("UNTRUSTED_ORIGIN", "The constructed origin URL is not trusted.");
262
374
  }
375
+ return origin;
263
376
  };
264
- var createRedirectURI = (request, oauth, basePath, trustedProxyHeaders) => {
265
- const url = getOriginURL(request, trustedProxyHeaders);
266
- return `${url.origin}${basePath}/callback/${oauth}`;
377
+ var createRedirectURI = async (request, oauth, context) => {
378
+ const origin = await getOriginURL(request, context);
379
+ return `${origin}${context.basePath}/callback/${oauth}`;
267
380
  };
268
- var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
381
+ var createRedirectTo = async (request, redirectTo, context) => {
269
382
  try {
270
383
  const headers = request.headers;
271
- const origin = headers.get("Origin");
272
- const referer = headers.get("Referer");
273
- let hostedURL = getOriginURL(request, trustedProxyHeaders);
274
- if (redirectTo) {
275
- if (redirectTo.startsWith("/")) {
276
- return sanitizeURL(redirectTo);
277
- }
278
- const redirectToURL = new URL(sanitizeURL(getNormalizedOriginPath(redirectTo)));
279
- if (!isValidURL(redirectTo) || !equals(redirectToURL.origin, hostedURL.origin)) {
280
- throw new AuthSecurityError(
281
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
282
- "The redirectTo parameter does not match the hosted origin."
283
- );
284
- }
285
- return sanitizeURL(redirectToURL.pathname);
286
- }
287
- if (referer) {
288
- const refererURL = new URL(sanitizeURL(referer));
289
- if (!isValidURL(referer) || !equals(refererURL.origin, hostedURL.origin)) {
290
- throw new AuthSecurityError(
291
- "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
292
- "The referer of the request does not match the hosted origin."
293
- );
384
+ const requestOrigin = await getOriginURL(request, context);
385
+ const origins = await getTrustedOrigins(request, context?.trustedOrigins);
386
+ const validateURL = (url) => {
387
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
388
+ if (isRelativeURL(url)) return url;
389
+ if (origins.length > 0) {
390
+ if (isTrustedOrigin(url, origins)) {
391
+ const urlOrigin = new URL(url).origin;
392
+ for (const pattern of origins) {
393
+ const regex = patternToRegex(pattern);
394
+ if (regex?.test(urlOrigin)) {
395
+ return isSameOrigin(url, request.url) ? extractPath(url) : url;
396
+ }
397
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return url;
398
+ }
399
+ }
400
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
401
+ return "/";
294
402
  }
295
- return sanitizeURL(refererURL.pathname);
296
- }
297
- if (origin) {
298
- const originURL = new URL(sanitizeURL(getNormalizedOriginPath(origin)));
299
- if (!isValidURL(origin) || !equals(originURL.origin, hostedURL.origin)) {
300
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
403
+ if (isSameOrigin(url, requestOrigin)) {
404
+ return extractPath(url);
301
405
  }
302
- return sanitizeURL(originURL.pathname);
303
- }
304
- return "/";
406
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
407
+ return "/";
408
+ };
409
+ return validateURL(redirectTo ?? headers.get("Referer") ?? headers.get("Origin") ?? "/");
305
410
  } catch (error) {
306
- if (isAuthSecurityError(error)) {
307
- throw error;
308
- }
309
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
411
+ context?.logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED");
412
+ return "/";
310
413
  }
311
414
  };
312
415
 
@@ -335,13 +438,17 @@ var signInAction = (oauth) => {
335
438
  request,
336
439
  params: { oauth: oauth2 },
337
440
  searchParams: { redirectTo },
338
- context: { oauth: providers, cookies, trustedProxyHeaders, basePath }
441
+ context
339
442
  } = ctx;
443
+ const { oauth: providers, cookies, logger } = context;
340
444
  const state = generateSecure();
341
- const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
342
- const redirectToValue = createRedirectTo(request, redirectTo, trustedProxyHeaders);
445
+ const redirectURI = await createRedirectURI(request, oauth2, context);
446
+ const redirectToValue = await createRedirectTo(request, redirectTo, context);
343
447
  const { codeVerifier, codeChallenge, method } = await createPKCE();
344
- const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
448
+ const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method, logger);
449
+ logger?.log("SIGN_IN_INITIATED", {
450
+ structuredData: { oauth_provider: oauth2, code_challenge_method: method }
451
+ });
345
452
  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();
346
453
  return Response.json(
347
454
  { oauth: oauth2 },
@@ -1,33 +1,13 @@
1
1
  import * as _aura_stack_router from '@aura-stack/router';
2
- import { z } from 'zod';
3
- import { j as OAuthProviderRecord } from '../../index-B8jeIElf.js';
2
+ import { k as OAuthProviderRecord } from '../../index-CSyIJmCM.js';
3
+ import 'zod';
4
4
  import '../../schemas.js';
5
- import '@aura-stack/router/cookie';
5
+ import '../../jose.js';
6
6
  import '@aura-stack/jose';
7
7
  import '@aura-stack/jose/jose';
8
+ import '@aura-stack/router/cookie';
8
9
  import '../../@types/utility.js';
9
10
 
10
- declare const signInAction: (oauth: OAuthProviderRecord) => _aura_stack_router.RouteEndpoint<"GET", "/signIn/:oauth", {
11
- schemas?: {
12
- params: z.ZodObject<{
13
- oauth: z.ZodEnum<{
14
- [x: string & Record<never, never>]: string & Record<never, never>;
15
- github: "github";
16
- bitbucket: "bitbucket";
17
- figma: "figma";
18
- discord: "discord";
19
- gitlab: "gitlab";
20
- spotify: "spotify";
21
- x: "x";
22
- strava: "strava";
23
- mailchimp: "mailchimp";
24
- pinterest: "pinterest";
25
- }>;
26
- }, z.core.$strip>;
27
- searchParams: z.ZodObject<{
28
- redirectTo: z.ZodOptional<z.ZodString>;
29
- }, z.core.$strip>;
30
- } | undefined;
31
- }>;
11
+ declare const signInAction: (oauth: OAuthProviderRecord) => _aura_stack_router.RouteEndpoint<"GET", "/signIn/:oauth", {}>;
32
12
 
33
13
  export { signInAction };
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  signInAction
3
- } from "../../chunk-3EUWD5BB.js";
4
- import "../../chunk-N4SX7TZT.js";
5
- import "../../chunk-STHEPPUZ.js";
6
- import "../../chunk-N2APGLXA.js";
7
- import "../../chunk-CXLATHS5.js";
8
- import "../../chunk-EIL2FPSS.js";
3
+ } from "../../chunk-7QF22LHP.js";
4
+ import "../../chunk-XUP6KKNG.js";
5
+ import "../../chunk-KJBAQZX2.js";
6
+ import "../../chunk-NUDITUKX.js";
7
+ import "../../chunk-4EKY7655.js";
8
+ import "../../chunk-QQVSRXGX.js";
9
+ import "../../chunk-EBAMFRB7.js";
10
+ import "../../chunk-FRJFWTOY.js";
11
+ import "../../chunk-4MYWAOLG.js";
9
12
  import "../../chunk-RRLIF4PQ.js";
10
- import "../../chunk-YRCB5FLE.js";
11
13
  export {
12
14
  signInAction
13
15
  };