@aura-stack/auth 0.4.0-rc.5 → 0.5.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 (201) hide show
  1. package/dist/@types/index.d.ts +8 -3
  2. package/dist/@types/router.d.cjs +0 -17
  3. package/dist/@types/router.d.d.ts +7 -2
  4. package/dist/@types/router.d.js +0 -1
  5. package/dist/actions/callback/access-token.cjs +130 -71
  6. package/dist/actions/callback/access-token.d.ts +9 -4
  7. package/dist/actions/callback/access-token.js +3 -4
  8. package/dist/actions/callback/callback.cjs +428 -152
  9. package/dist/actions/callback/callback.d.ts +11 -3
  10. package/dist/actions/callback/callback.js +12 -10
  11. package/dist/actions/callback/userinfo.cjs +159 -65
  12. package/dist/actions/callback/userinfo.d.ts +8 -3
  13. package/dist/actions/callback/userinfo.js +7 -6
  14. package/dist/actions/csrfToken/csrfToken.cjs +70 -19
  15. package/dist/actions/csrfToken/csrfToken.js +8 -7
  16. package/dist/actions/index.cjs +780 -348
  17. package/dist/actions/index.d.ts +6 -2
  18. package/dist/actions/index.js +23 -18
  19. package/dist/actions/session/session.cjs +107 -26
  20. package/dist/actions/session/session.js +7 -5
  21. package/dist/actions/signIn/authorization-url.cjs +288 -0
  22. package/dist/actions/signIn/authorization-url.d.ts +31 -0
  23. package/dist/actions/signIn/authorization-url.js +16 -0
  24. package/dist/actions/signIn/authorization.cjs +209 -211
  25. package/dist/actions/signIn/authorization.d.ts +32 -21
  26. package/dist/actions/signIn/authorization.js +12 -9
  27. package/dist/actions/signIn/signIn.cjs +470 -235
  28. package/dist/actions/signIn/signIn.d.ts +12 -3
  29. package/dist/actions/signIn/signIn.js +11 -8
  30. package/dist/actions/signOut/signOut.cjs +376 -228
  31. package/dist/actions/signOut/signOut.d.ts +1 -1
  32. package/dist/actions/signOut/signOut.js +10 -9
  33. package/dist/api/createApi.cjs +750 -0
  34. package/dist/api/createApi.d.ts +12 -0
  35. package/dist/api/createApi.js +19 -0
  36. package/dist/api/getSession.cjs +141 -0
  37. package/dist/api/getSession.d.ts +16 -0
  38. package/dist/api/getSession.js +10 -0
  39. package/dist/api/signIn.cjs +549 -0
  40. package/dist/api/signIn.d.ts +26 -0
  41. package/dist/api/signIn.js +15 -0
  42. package/dist/api/signOut.cjs +279 -0
  43. package/dist/api/signOut.d.ts +16 -0
  44. package/dist/api/signOut.js +13 -0
  45. package/dist/assert.cjs +150 -5
  46. package/dist/assert.d.ts +26 -3
  47. package/dist/assert.js +17 -3
  48. package/dist/{chunk-YRCB5FLE.js → chunk-2A5B7GWR.js} +52 -6
  49. package/dist/chunk-2GQLSIJ2.js +40 -0
  50. package/dist/chunk-2IR674WX.js +44 -0
  51. package/dist/chunk-3J5TUH2I.js +50 -0
  52. package/dist/chunk-4RWSYUKX.js +98 -0
  53. package/dist/chunk-4YHJ4IEQ.js +25 -0
  54. package/dist/chunk-54CZPKR4.js +25 -0
  55. package/dist/chunk-5LZ7TOM3.js +25 -0
  56. package/dist/chunk-7BE46WWS.js +88 -0
  57. package/dist/chunk-7YYXFKLR.js +35 -0
  58. package/dist/chunk-C3A37LQC.js +33 -0
  59. package/dist/chunk-CITNGXDA.js +31 -0
  60. package/dist/chunk-CWX724AG.js +78 -0
  61. package/dist/chunk-D2CSIUKP.js +74 -0
  62. package/dist/chunk-E6G5YCI6.js +25 -0
  63. package/dist/chunk-EBAMFRB7.js +34 -0
  64. package/dist/chunk-EEE7UM5T.js +25 -0
  65. package/dist/{chunk-HT4YLL7N.js → chunk-FPCVZUVG.js} +10 -8
  66. package/dist/chunk-FW4W3REU.js +25 -0
  67. package/dist/chunk-GNNBM2WJ.js +83 -0
  68. package/dist/chunk-IPKO6UQN.js +25 -0
  69. package/dist/chunk-JOCGX3RP.js +59 -0
  70. package/dist/chunk-KBXWTD6E.js +94 -0
  71. package/dist/chunk-KMMAZFSJ.js +25 -0
  72. package/dist/chunk-LATR3NIV.js +117 -0
  73. package/dist/chunk-LAYPUDQF.js +39 -0
  74. package/dist/chunk-LDU7A2JE.js +25 -0
  75. package/dist/chunk-LX3TJ2TJ.js +294 -0
  76. package/dist/chunk-NHZBQNRR.js +143 -0
  77. package/dist/chunk-OVHNRULD.js +33 -0
  78. package/dist/chunk-PDP3PHB3.js +127 -0
  79. package/dist/chunk-PHYNROD4.js +47 -0
  80. package/dist/chunk-QQEKY4XP.js +29 -0
  81. package/dist/chunk-U4RK4LKJ.js +348 -0
  82. package/dist/{chunk-RRLIF4PQ.js → chunk-U5663F2U.js} +16 -1
  83. package/dist/chunk-UN7X6SU5.js +53 -0
  84. package/dist/chunk-UZQJJD6A.js +100 -0
  85. package/dist/chunk-V6LLEAR4.js +80 -0
  86. package/dist/chunk-WHNDRO3N.js +50 -0
  87. package/dist/{chunk-W6LG7BFW.js → chunk-XY5R3EHH.js} +30 -23
  88. package/dist/client/client.cjs +135 -0
  89. package/dist/client/client.d.ts +85 -0
  90. package/dist/client/client.js +9 -0
  91. package/dist/client/index.cjs +135 -0
  92. package/dist/client/index.d.ts +14 -0
  93. package/dist/client/index.js +10 -0
  94. package/dist/context.cjs +1237 -0
  95. package/dist/context.d.ts +16 -0
  96. package/dist/context.js +28 -0
  97. package/dist/cookie.cjs +57 -22
  98. package/dist/cookie.d.ts +11 -6
  99. package/dist/cookie.js +3 -2
  100. package/dist/createAuth.cjs +2320 -0
  101. package/dist/createAuth.d.ts +12 -0
  102. package/dist/createAuth.js +48 -0
  103. package/dist/env.cjs +78 -0
  104. package/dist/env.d.ts +10 -0
  105. package/dist/env.js +12 -0
  106. package/dist/errors.cjs +17 -0
  107. package/dist/errors.d.ts +15 -4
  108. package/dist/errors.js +5 -1
  109. package/dist/headers.cjs +28 -2
  110. package/dist/headers.d.ts +25 -1
  111. package/dist/headers.js +9 -3
  112. package/dist/index-_aXtxb_s.d.ts +1377 -0
  113. package/dist/index.cjs +1843 -610
  114. package/dist/index.d.ts +11 -92
  115. package/dist/index.js +53 -85
  116. package/dist/jose.cjs +113 -38
  117. package/dist/jose.d.ts +12 -23
  118. package/dist/jose.js +17 -7
  119. package/dist/logger.cjs +424 -0
  120. package/dist/logger.d.ts +12 -0
  121. package/dist/logger.js +17 -0
  122. package/dist/oauth/atlassian.cjs +57 -0
  123. package/dist/oauth/atlassian.d.ts +12 -0
  124. package/dist/oauth/atlassian.js +6 -0
  125. package/dist/oauth/bitbucket.cjs +19 -15
  126. package/dist/oauth/bitbucket.d.ts +7 -2
  127. package/dist/oauth/bitbucket.js +1 -1
  128. package/dist/oauth/discord.cjs +27 -24
  129. package/dist/oauth/discord.d.ts +7 -2
  130. package/dist/oauth/discord.js +1 -1
  131. package/dist/oauth/dropbox.cjs +53 -0
  132. package/dist/oauth/dropbox.d.ts +12 -0
  133. package/dist/oauth/dropbox.js +6 -0
  134. package/dist/oauth/figma.cjs +19 -16
  135. package/dist/oauth/figma.d.ts +7 -2
  136. package/dist/oauth/figma.js +1 -1
  137. package/dist/oauth/github.cjs +19 -8
  138. package/dist/oauth/github.d.ts +7 -2
  139. package/dist/oauth/github.js +1 -1
  140. package/dist/oauth/gitlab.cjs +19 -16
  141. package/dist/oauth/gitlab.d.ts +7 -2
  142. package/dist/oauth/gitlab.js +1 -1
  143. package/dist/oauth/index.cjs +529 -239
  144. package/dist/oauth/index.d.ts +7 -2
  145. package/dist/oauth/index.js +39 -22
  146. package/dist/oauth/mailchimp.cjs +19 -16
  147. package/dist/oauth/mailchimp.d.ts +7 -2
  148. package/dist/oauth/mailchimp.js +1 -1
  149. package/dist/oauth/notion.cjs +131 -0
  150. package/dist/oauth/notion.d.ts +12 -0
  151. package/dist/oauth/notion.js +9 -0
  152. package/dist/oauth/pinterest.cjs +19 -16
  153. package/dist/oauth/pinterest.d.ts +7 -2
  154. package/dist/oauth/pinterest.js +1 -1
  155. package/dist/oauth/spotify.cjs +19 -16
  156. package/dist/oauth/spotify.d.ts +7 -2
  157. package/dist/oauth/spotify.js +1 -1
  158. package/dist/oauth/strava.cjs +19 -16
  159. package/dist/oauth/strava.d.ts +7 -2
  160. package/dist/oauth/strava.js +1 -1
  161. package/dist/oauth/twitch.cjs +95 -0
  162. package/dist/oauth/twitch.d.ts +12 -0
  163. package/dist/oauth/twitch.js +7 -0
  164. package/dist/oauth/x.cjs +19 -16
  165. package/dist/oauth/x.d.ts +7 -2
  166. package/dist/oauth/x.js +1 -1
  167. package/dist/schemas.cjs +89 -42
  168. package/dist/schemas.d.ts +114 -18
  169. package/dist/schemas.js +5 -3
  170. package/dist/secure.cjs +73 -31
  171. package/dist/secure.d.ts +11 -11
  172. package/dist/secure.js +7 -6
  173. package/dist/utils.cjs +203 -90
  174. package/dist/utils.d.ts +21 -40
  175. package/dist/utils.js +21 -12
  176. package/package.json +9 -6
  177. package/dist/chunk-3EUWD5BB.js +0 -63
  178. package/dist/chunk-42XB3YCW.js +0 -22
  179. package/dist/chunk-6R2YZ4AC.js +0 -22
  180. package/dist/chunk-A3N4PVAT.js +0 -70
  181. package/dist/chunk-B737EUJV.js +0 -22
  182. package/dist/chunk-CXLATHS5.js +0 -143
  183. package/dist/chunk-E3OXBRYF.js +0 -22
  184. package/dist/chunk-EIL2FPSS.js +0 -22
  185. package/dist/chunk-EMKJA2GJ.js +0 -89
  186. package/dist/chunk-FIPU4MLT.js +0 -21
  187. package/dist/chunk-FKRDCWBF.js +0 -22
  188. package/dist/chunk-GA2SMTJO.js +0 -58
  189. package/dist/chunk-HP34YGGJ.js +0 -22
  190. package/dist/chunk-IKHPGFCW.js +0 -14
  191. package/dist/chunk-IUYZQTJV.js +0 -30
  192. package/dist/chunk-IVET23KF.js +0 -58
  193. package/dist/chunk-JVFTCTTE.js +0 -33
  194. package/dist/chunk-KRNOMBXQ.js +0 -22
  195. package/dist/chunk-KSWLO5ZU.js +0 -102
  196. package/dist/chunk-N2APGLXA.js +0 -71
  197. package/dist/chunk-N4SX7TZT.js +0 -96
  198. package/dist/chunk-STHEPPUZ.js +0 -11
  199. package/dist/chunk-TLE4PXY3.js +0 -39
  200. package/dist/index-B8jeIElf.d.ts +0 -679
  201. /package/dist/{chunk-DIVDFNAP.js → chunk-5X7JZMEF.js} +0 -0
package/dist/index.cjs CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,35 +15,69 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
31
21
  var index_exports = {};
32
22
  __export(index_exports, {
23
+ builtInOAuthProviders: () => builtInOAuthProviders,
33
24
  createAuth: () => createAuth,
34
- createClient: () => import_router7.createClient
25
+ createAuthClient: () => createAuthClient,
26
+ createClient: () => createClient,
27
+ createSyslogMessage: () => createSyslogMessage
35
28
  });
36
29
  module.exports = __toCommonJS(index_exports);
37
- var import_config2 = require("dotenv/config");
38
- var import_router7 = require("@aura-stack/router");
39
30
 
40
- // src/jose.ts
41
- var import_config = require("dotenv/config");
42
- var import_jose = require("@aura-stack/jose");
31
+ // src/createAuth.ts
32
+ var import_router9 = require("@aura-stack/router");
43
33
 
44
- // src/secure.ts
45
- var import_crypto = __toESM(require("crypto"), 1);
34
+ // src/env.ts
35
+ var import_meta = {};
36
+ var env = new Proxy({}, {
37
+ get(_, prop) {
38
+ if (typeof prop !== "string") return void 0;
39
+ const hasProperty = (process2) => {
40
+ return process2 && Object.prototype.hasOwnProperty.call(process2, prop);
41
+ };
42
+ try {
43
+ if (typeof process !== "undefined" && hasProperty(process.env)) {
44
+ return process.env[prop];
45
+ }
46
+ if (typeof import_meta !== "undefined" && hasProperty(import_meta.env)) {
47
+ return import_meta.env[prop];
48
+ }
49
+ if (typeof Deno !== "undefined" && Deno.env?.get) {
50
+ return Deno.env.get(prop);
51
+ }
52
+ if (typeof Bun !== "undefined" && hasProperty(Bun.env)) {
53
+ return Bun.env[prop];
54
+ }
55
+ const globalValue = globalThis[prop];
56
+ return typeof globalValue === "string" ? globalValue : void 0;
57
+ } catch {
58
+ return void 0;
59
+ }
60
+ }
61
+ });
62
+ var getEnv = (key) => {
63
+ const keys = [`AURA_AUTH_${key.toUpperCase()}`, `AURA_${key.toUpperCase()}`, `AUTH_${key.toUpperCase()}`, key.toUpperCase()];
64
+ return env[keys.find((k) => env[k]) ?? ""];
65
+ };
66
+ var getEnvBoolean = (key) => {
67
+ const value = getEnv(key);
68
+ if (value === void 0) return false;
69
+ const normalized = value.trim().toLowerCase();
70
+ if (["1", "true", "yes", "on", "debug"].includes(normalized)) return true;
71
+ return false;
72
+ };
73
+ var getEnvArray = (key, defaultValue = []) => {
74
+ const value = getEnv(key);
75
+ if (!value) return defaultValue;
76
+ return value.split(/[,;\n]+/).map((v) => v.trim()).filter(Boolean);
77
+ };
46
78
 
47
- // src/utils.ts
48
- var import_router = require("@aura-stack/router");
79
+ // src/jose.ts
80
+ var import_jose = require("@aura-stack/jose");
49
81
 
50
82
  // src/errors.ts
51
83
  var OAuthProtocolError = class extends Error {
@@ -80,6 +112,16 @@ var AuthSecurityError = class extends Error {
80
112
  Error.captureStackTrace(this, new.target);
81
113
  }
82
114
  };
115
+ var AuthClientError = class extends Error {
116
+ type = "AUTH_CLIENT_ERROR";
117
+ code;
118
+ constructor(code, message, options2) {
119
+ super(message, options2);
120
+ this.code = code;
121
+ this.name = new.target.name;
122
+ Error.captureStackTrace(this, new.target);
123
+ }
124
+ };
83
125
  var isNativeError = (error) => {
84
126
  return error instanceof Error;
85
127
  };
@@ -93,112 +135,268 @@ var isAuthSecurityError = (error) => {
93
135
  return error instanceof AuthSecurityError;
94
136
  };
95
137
 
138
+ // src/jose.ts
139
+ var import_jose2 = require("@aura-stack/jose/jose");
140
+ var import_crypto = require("@aura-stack/jose/crypto");
141
+ var createJoseInstance = (secret) => {
142
+ secret ??= getEnv("SECRET");
143
+ if (!secret) {
144
+ throw new AuthInternalError(
145
+ "JOSE_INITIALIZATION_FAILED",
146
+ "AURA_AUTH_SECRET environment variable is not set and no secret was provided."
147
+ );
148
+ }
149
+ const salt = getEnv("SALT");
150
+ if (!salt) {
151
+ throw new AuthInternalError(
152
+ "JOSE_INITIALIZATION_FAILED",
153
+ "AURA_AUTH_SALT or AUTH_SALT environment variable is not set. A salt value is required for key derivation."
154
+ );
155
+ }
156
+ try {
157
+ (0, import_jose.createSecret)(salt);
158
+ } catch (error) {
159
+ throw new AuthInternalError(
160
+ "INVALID_SALT_SECRET_VALUE",
161
+ "AURA_AUTH_SALT/AUTH_SALT is invalid. It must be at least 32 bytes long and meet entropy requirements.",
162
+ { cause: error }
163
+ );
164
+ }
165
+ const jose = (async () => {
166
+ const derivedSigningKey = await (0, import_jose.createDeriveKey)(secret, salt, "signing");
167
+ const derivedEncryptionKey = await (0, import_jose.createDeriveKey)(secret, salt, "encryption");
168
+ const derivedCsrfTokenKey = await (0, import_jose.createDeriveKey)(secret, salt, "csrfToken");
169
+ return {
170
+ jwt: (0, import_jose.createJWT)({ jws: derivedSigningKey, jwe: derivedEncryptionKey }),
171
+ jws: (0, import_jose.createJWS)(derivedCsrfTokenKey),
172
+ jwe: (0, import_jose.createJWE)(derivedEncryptionKey)
173
+ };
174
+ })();
175
+ jose.catch(() => {
176
+ });
177
+ return {
178
+ decodeJWT: async (token, options2) => {
179
+ const { jwt } = await jose;
180
+ return jwt.decodeJWT(token, options2);
181
+ },
182
+ encodeJWT: async (payload) => {
183
+ const { jwt } = await jose;
184
+ return jwt.encodeJWT(payload);
185
+ },
186
+ signJWS: async (...args) => {
187
+ const { jws } = await jose;
188
+ return jws.signJWS(...args);
189
+ },
190
+ verifyJWS: async (...args) => {
191
+ const { jws } = await jose;
192
+ return jws.verifyJWS(...args);
193
+ },
194
+ encryptJWE: async (...args) => {
195
+ const { jwe } = await jose;
196
+ return jwe.encryptJWE(...args);
197
+ },
198
+ decryptJWE: async (...args) => {
199
+ const { jwe } = await jose;
200
+ return jwe.decryptJWE(...args);
201
+ }
202
+ };
203
+ };
204
+ var jwtVerificationOptions = {
205
+ algorithms: ["HS256"],
206
+ typ: "JWT"
207
+ };
208
+
96
209
  // 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(/^_+/, "");
210
+ var import_router = require("@aura-stack/router");
211
+
212
+ // src/assert.ts
213
+ var import_crypto2 = require("@aura-stack/jose/crypto");
214
+ var unsafeChars = [
215
+ "<",
216
+ ">",
217
+ '"',
218
+ "`",
219
+ " ",
220
+ "\r",
221
+ "\n",
222
+ " ",
223
+ "\\",
224
+ "%2F",
225
+ "%5C",
226
+ "%2f",
227
+ "%5c",
228
+ "\r\n",
229
+ "%0A",
230
+ "%0D",
231
+ "%0a",
232
+ "%0d",
233
+ "..",
234
+ "//",
235
+ "///",
236
+ "...",
237
+ "%20",
238
+ "\0"
239
+ ];
240
+ var isValidURL = (value) => {
241
+ if (!new RegExp(/^https?:\/\/[^/]/).test(value)) {
242
+ return false;
243
+ }
244
+ const match = value.match(/^(https?:\/\/)(.*)$/);
245
+ if (!match) return false;
246
+ const rest = match[2];
247
+ for (const char of unsafeChars) {
248
+ if (rest.includes(char)) return false;
249
+ }
250
+ const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()?#*+,;=:@-]*)*\/?$/;
251
+ return regex.test(match[0]);
99
252
  };
100
- var toUpperCase = (str) => {
101
- return str.toUpperCase();
253
+ var isJWTPayloadWithToken = (payload) => {
254
+ return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
102
255
  };
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
- }, {});
256
+ var isRelativeURL = (value) => {
257
+ if (value.length > 100) return false;
258
+ for (const char of unsafeChars) {
259
+ if (value.includes(char)) return false;
260
+ }
261
+ const regex = /^\/[a-zA-Z0-9\-_\/.?&=#]*\/?$/;
262
+ return regex.test(value);
108
263
  };
109
- var equals = (a, b) => {
110
- if (a === null || b === null || a === void 0 || b === void 0) return false;
111
- return a === b;
264
+ var isSameOrigin = (origin, expected) => {
265
+ const originURL = new URL(origin);
266
+ const expectedURL = new URL(expected);
267
+ return equals(originURL.origin, expectedURL.origin);
112
268
  };
113
- var sanitizeURL = (url) => {
269
+ var patternToRegex = (pattern) => {
114
270
  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;
271
+ if (pattern.length > 2048) return null;
272
+ pattern = pattern.replace(/\\/g, "");
273
+ const match = pattern.match(/^(https?):\/\/([a-zA-Z0-9.*-]{1,253})(?::(\d{1,5}|\*))?(?:\/.*)?$/);
274
+ if (!match) return null;
275
+ const [, protocol, host, port] = match;
276
+ const hasWildcard = host.includes("*");
277
+ if (hasWildcard && !host.startsWith("*.")) return null;
278
+ if (hasWildcard && host.slice(2).includes("*")) return null;
279
+ const domain = hasWildcard ? host.slice(2) : host;
280
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
281
+ const hostRegex = hasWildcard ? `[^.]+\\.${escapedDomain}` : escapedDomain;
282
+ const portRegex = port === "*" ? ":\\d{1,5}" : port ? `:${port}` : "";
283
+ return new RegExp(`^${protocol}:\\/\\/${hostRegex}${portRegex}$`);
142
284
  } catch {
143
- return url.trim();
285
+ return null;
144
286
  }
145
287
  };
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 });
288
+ var isTrustedOrigin = (url, trustedOrigins) => {
289
+ if (!isValidURL(url) || trustedOrigins.length === 0) return false;
290
+ try {
291
+ const urlOrigin = new URL(url).origin;
292
+ for (const pattern of trustedOrigins) {
293
+ const regex = patternToRegex(pattern);
294
+ if (regex?.test(urlOrigin)) return true;
295
+ try {
296
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return true;
297
+ } catch {
298
+ }
299
+ }
300
+ } catch {
161
301
  }
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
- );
302
+ return false;
303
+ };
304
+ var timingSafeEqual = (a, b) => {
305
+ const bufferA = import_crypto2.encoder.encode(a);
306
+ const bufferB = import_crypto2.encoder.encode(b);
307
+ const len = Math.max(bufferA.length, bufferB.length);
308
+ let diff = 0;
309
+ for (let i = 0; i < len; i++) {
310
+ diff |= (bufferA[i] ?? 0) ^ (bufferB[i] ?? 0);
173
311
  }
174
- if (isAuthInternalError(error) || isAuthSecurityError(error)) {
175
- const { type, code, message } = error;
312
+ return diff === 0 && bufferA.length === bufferB.length;
313
+ };
314
+
315
+ // src/utils.ts
316
+ var AURA_AUTH_VERSION = "0.4.0";
317
+ var equals = (a, b) => {
318
+ if (a === null || b === null || a === void 0 || b === void 0) return false;
319
+ return a === b;
320
+ };
321
+ var createErrorHandler = (logger) => {
322
+ return (error) => {
323
+ if ((0, import_router.isRouterError)(error)) {
324
+ const { message, status, statusText } = error;
325
+ logger?.log("ROUTER_INTERNAL_ERROR");
326
+ return Response.json({ type: "ROUTER_ERROR", code: "ROUTER_INTERNAL_ERROR", message }, { status, statusText });
327
+ }
328
+ if ((0, import_router.isInvalidZodSchemaError)(error)) {
329
+ logger?.log("INVALID_REQUEST");
330
+ return Response.json({ type: "ROUTER_ERROR", code: "INVALID_REQUEST", message: error.errors }, { status: 422 });
331
+ }
332
+ if (isOAuthProtocolError(error)) {
333
+ const { error: errorCode, message, type, errorURI } = error;
334
+ logger?.log("OAUTH_PROTOCOL_ERROR", {
335
+ structuredData: {
336
+ error: errorCode,
337
+ error_description: message,
338
+ error_uri: errorURI ?? ""
339
+ }
340
+ });
341
+ return Response.json(
342
+ {
343
+ type,
344
+ message
345
+ },
346
+ { status: 400 }
347
+ );
348
+ }
349
+ if (isAuthInternalError(error)) {
350
+ const { type, code, message } = error;
351
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
352
+ structuredData: {
353
+ error: code,
354
+ error_description: message
355
+ }
356
+ });
357
+ return Response.json(
358
+ {
359
+ type,
360
+ message
361
+ },
362
+ { status: 400 }
363
+ );
364
+ }
365
+ if (isAuthSecurityError(error)) {
366
+ const { type, code, message } = error;
367
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
368
+ structuredData: {
369
+ error: code,
370
+ error_description: message
371
+ }
372
+ });
373
+ return Response.json(
374
+ {
375
+ type,
376
+ code,
377
+ message
378
+ },
379
+ { status: 400 }
380
+ );
381
+ }
382
+ logger?.log("SERVER_ERROR");
176
383
  return Response.json(
177
- {
178
- type,
179
- code,
180
- message
181
- },
182
- { status: 400 }
384
+ { type: "SERVER_ERROR", code: "SERVER_ERROR", message: "An unexpected error occurred" },
385
+ { status: 500 }
183
386
  );
184
- }
185
- return Response.json({ type: "SERVER_ERROR", code: "server_error", message: "An unexpected error occurred" }, { status: 500 });
387
+ };
186
388
  };
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
- }
389
+ var getBaseURL = (request) => {
390
+ const url = new URL(request.url);
391
+ return `${url.origin}${url.pathname}`;
196
392
  };
197
393
  var toISOString = (date) => {
198
394
  return new Date(date).toISOString();
199
395
  };
200
396
  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://");
397
+ const headers = request instanceof Headers ? request : request.headers;
398
+ const url = request instanceof Headers ? null : request.url;
399
+ return trustedProxyHeaders ? url?.startsWith("https://") || headers.get("X-Forwarded-Proto") === "https" || (headers.get("Forwarded")?.includes("proto=https") ?? false) : url?.startsWith("https://") ?? false;
202
400
  };
203
401
  var formatZodError = (error) => {
204
402
  if (!error.issues || error.issues.length === 0) {
@@ -215,95 +413,370 @@ var formatZodError = (error) => {
215
413
  };
216
414
  }, {});
217
415
  };
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";
416
+ var extractPath = (url) => {
417
+ const pathRegex = /^https?:\/\/[a-zA-Z0-9_\-\.]+(:\d+)?(\/.*)$/;
418
+ const match = url.match(pathRegex);
419
+ return match && match[2] ? match[2] : "/";
227
420
  };
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);
421
+ var createStructuredData = (data, sdID = "metadata") => {
422
+ const entries = Object.entries(data);
423
+ if (entries.length === 0) return `[${sdID}]`;
424
+ const values = entries.map(([key, value]) => `${key}="${String(value).replace(/(["\\\]])/g, "\\$1")}"`).join(" ");
425
+ return `[${sdID} ${values}]`;
235
426
  };
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 });
427
+ var getErrorName = (error) => {
428
+ if (error instanceof Error) {
429
+ return error.name;
252
430
  }
431
+ return typeof error === "string" ? error : "UnknownError";
253
432
  };
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.");
433
+ var createBasicAuthHeader = (username, password) => {
434
+ const getUsername = getEnv(username.toUpperCase()) ?? username;
435
+ const getPassword = getEnv(password.toUpperCase()) ?? password;
436
+ if (!getUsername || !getPassword) {
437
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "Missing client credentials for OAuth provider configuration.");
275
438
  }
439
+ const credentials = `${getUsername}:${getPassword}`;
440
+ return `Basic ${btoa(credentials)}`;
276
441
  };
277
- var createDerivedSalt = (secret) => {
278
- return import_crypto.default.createHash("sha256").update(secret).update("aura-auth-salt").digest("hex");
442
+ var validateRedirectTo = (url) => {
443
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
444
+ if (isRelativeURL(url)) return url;
445
+ return "/";
279
446
  };
280
447
 
281
- // src/jose.ts
282
- var createJoseInstance = (secret) => {
283
- const env = process.env;
284
- secret ??= env.AURA_AUTH_SECRET ?? env.AUTH_SECRET;
285
- if (!secret) {
286
- throw new AuthInternalError(
287
- "JOSE_INITIALIZATION_FAILED",
288
- "AURA_AUTH_SECRET environment variable is not set and no secret was provided."
289
- );
448
+ // src/logger.ts
449
+ var logMessages = {
450
+ ROUTER_INTERNAL_ERROR: {
451
+ facility: 10,
452
+ severity: "error",
453
+ msgId: "ROUTER_INTERNAL_ERROR",
454
+ message: "Unhandled router error while processing the request"
455
+ },
456
+ INVALID_REQUEST: {
457
+ facility: 10,
458
+ severity: "warning",
459
+ msgId: "INVALID_REQUEST",
460
+ message: "Request validation failed against the expected schema"
461
+ },
462
+ SERVER_ERROR: {
463
+ facility: 10,
464
+ severity: "error",
465
+ msgId: "SERVER_ERROR",
466
+ message: "Unexpected internal server error during authentication"
467
+ },
468
+ OAUTH_PROTOCOL_ERROR: {
469
+ facility: 10,
470
+ severity: "warning",
471
+ msgId: "OAUTH_PROTOCOL_ERROR",
472
+ message: "OAuth provider returned an invalid or unexpected protocol response"
473
+ },
474
+ OAUTH_AUTHORIZATION_ERROR: {
475
+ facility: 10,
476
+ severity: "error",
477
+ msgId: "OAUTH_AUTHORIZATION_ERROR",
478
+ message: "OAuth authorization request was rejected or failed"
479
+ },
480
+ INVALID_OAUTH_CONFIGURATION: {
481
+ facility: 10,
482
+ severity: "error",
483
+ msgId: "INVALID_OAUTH_CONFIGURATION",
484
+ message: "The OAuth provider configuration is invalid or incomplete"
485
+ },
486
+ OAUTH_ACCESS_TOKEN_REQUEST_INITIATED: {
487
+ facility: 10,
488
+ severity: "debug",
489
+ msgId: "OAUTH_ACCESS_TOKEN_REQUEST_INITIATED",
490
+ message: "Starting OAuth access token request to the provider"
491
+ },
492
+ INVALID_OAUTH_ACCESS_TOKEN_RESPONSE: {
493
+ facility: 10,
494
+ severity: "error",
495
+ msgId: "INVALID_OAUTH_ACCESS_TOKEN_RESPONSE",
496
+ message: "OAuth access token endpoint returned an invalid or malformed response"
497
+ },
498
+ OAUTH_ACCESS_TOKEN_ERROR: {
499
+ facility: 10,
500
+ severity: "error",
501
+ msgId: "OAUTH_ACCESS_TOKEN_ERROR",
502
+ message: "OAuth access token endpoint returned an error response"
503
+ },
504
+ OAUTH_ACCESS_TOKEN_SUCCESS: {
505
+ facility: 10,
506
+ severity: "info",
507
+ msgId: "OAUTH_ACCESS_TOKEN_SUCCESS",
508
+ message: "Successfully retrieved OAuth access token from the provider"
509
+ },
510
+ OAUTH_ACCESS_TOKEN_REQUEST_FAILED: {
511
+ facility: 10,
512
+ severity: "error",
513
+ msgId: "OAUTH_ACCESS_TOKEN_REQUEST_FAILED",
514
+ message: "Network or server error while requesting OAuth access token"
515
+ },
516
+ OAUTH_USERINFO_REQUEST_INITIATED: {
517
+ facility: 10,
518
+ severity: "debug",
519
+ msgId: "OAUTH_USERINFO_REQUEST_INITIATED",
520
+ message: "Starting OAuth userinfo request to the provider"
521
+ },
522
+ OAUTH_USERINFO_INVALID_RESPONSE: {
523
+ facility: 10,
524
+ severity: "error",
525
+ msgId: "OAUTH_USERINFO_INVALID_RESPONSE",
526
+ message: "OAuth userinfo endpoint returned an invalid or malformed response"
527
+ },
528
+ OAUTH_USERINFO_ERROR: {
529
+ facility: 10,
530
+ severity: "error",
531
+ msgId: "OAUTH_USERINFO_ERROR",
532
+ message: "OAuth userinfo endpoint returned an error response"
533
+ },
534
+ OAUTH_USERINFO_SUCCESS: {
535
+ facility: 10,
536
+ severity: "info",
537
+ msgId: "OAUTH_USERINFO_SUCCESS",
538
+ message: "Successfully retrieved user information from the OAuth provider"
539
+ },
540
+ OAUTH_USERINFO_REQUEST_FAILED: {
541
+ facility: 10,
542
+ severity: "error",
543
+ msgId: "OAUTH_USERINFO_REQUEST_FAILED",
544
+ message: "Network or server error while requesting user information from the OAuth provider"
545
+ },
546
+ OAUTH_CALLBACK_SUCCESS: {
547
+ facility: 4,
548
+ severity: "info",
549
+ msgId: "OAUTH_CALLBACK_SUCCESS",
550
+ message: "OAuth callback completed successfully and session was created"
551
+ },
552
+ MISMATCHING_STATE: {
553
+ facility: 4,
554
+ severity: "critical",
555
+ msgId: "MISMATCHING_STATE",
556
+ message: "OAuth response state parameter does not match the stored state value"
557
+ },
558
+ POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED: {
559
+ facility: 4,
560
+ severity: "critical",
561
+ msgId: "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
562
+ message: "Blocked redirect to untrusted or external URL (potential open redirect attack)"
563
+ },
564
+ OPEN_REDIRECT_ATTACK: {
565
+ facility: 4,
566
+ severity: "warning",
567
+ msgId: "OPEN_REDIRECT_ATTACK",
568
+ message: "Detected redirect target that does not match the trusted origin"
569
+ },
570
+ SESSION_TOKEN_MISSING: {
571
+ facility: 4,
572
+ severity: "warning",
573
+ msgId: "SESSION_TOKEN_MISSING",
574
+ message: "Session cookie is missing from the request"
575
+ },
576
+ CSRF_TOKEN_MISSING: {
577
+ facility: 4,
578
+ severity: "warning",
579
+ msgId: "CSRF_TOKEN_MISSING",
580
+ message: "CSRF token cookie is missing from the request"
581
+ },
582
+ CSRF_HEADER_MISSING: {
583
+ facility: 4,
584
+ severity: "warning",
585
+ msgId: "CSRF_HEADER_MISSING",
586
+ message: "CSRF header is missing from the request"
587
+ },
588
+ CSRF_TOKEN_INVALID: {
589
+ facility: 4,
590
+ severity: "error",
591
+ msgId: "CSRF_TOKEN_INVALID",
592
+ message: "CSRF token verification failed or token is invalid"
593
+ },
594
+ SIGN_IN_INITIATED: {
595
+ facility: 4,
596
+ severity: "info",
597
+ msgId: "SIGN_IN_INITIATED",
598
+ message: "Starting OAuth sign-in flow for the selected provider"
599
+ },
600
+ SIGN_OUT_ATTEMPT: {
601
+ facility: 4,
602
+ severity: "debug",
603
+ msgId: "SIGN_OUT_ATTEMPT",
604
+ message: "Received sign-out request from client"
605
+ },
606
+ SIGN_OUT_CSRF_VERIFIED: {
607
+ facility: 4,
608
+ severity: "info",
609
+ msgId: "SIGN_OUT_CSRF_VERIFIED",
610
+ message: "CSRF token was successfully verified during sign-out"
611
+ },
612
+ SIGN_OUT_SUCCESS: {
613
+ facility: 4,
614
+ severity: "info",
615
+ msgId: "SIGN_OUT_SUCCESS",
616
+ message: "User session was cleared and sign-out completed successfully"
617
+ },
618
+ SIGN_OUT_REDIRECT: {
619
+ facility: 4,
620
+ severity: "debug",
621
+ msgId: "SIGN_OUT_REDIRECT",
622
+ message: "Redirecting client after successful sign-out"
623
+ },
624
+ AUTH_SESSION_VALID: {
625
+ facility: 4,
626
+ severity: "info",
627
+ msgId: "AUTH_SESSION_VALID",
628
+ message: "Session token is valid and user session was returned"
629
+ },
630
+ AUTH_SESSION_INVALID: {
631
+ facility: 4,
632
+ severity: "notice",
633
+ msgId: "AUTH_SESSION_INVALID",
634
+ message: "Session token is missing, expired, or invalid"
635
+ },
636
+ INVALID_JWT_TOKEN: {
637
+ facility: 4,
638
+ severity: "warning",
639
+ msgId: "INVALID_JWT_TOKEN",
640
+ message: "JWT session token failed validation during sign-out"
641
+ },
642
+ CSRF_TOKEN_REQUESTED: {
643
+ facility: 4,
644
+ severity: "debug",
645
+ msgId: "CSRF_TOKEN_REQUESTED",
646
+ message: "Client requested a CSRF token"
647
+ },
648
+ CSRF_TOKEN_ISSUED: {
649
+ facility: 4,
650
+ severity: "debug",
651
+ msgId: "CSRF_TOKEN_ISSUED",
652
+ message: "Issued a new CSRF token to the client"
653
+ },
654
+ INVALID_URL: {
655
+ facility: 10,
656
+ severity: "error",
657
+ msgId: "INVALID_URL",
658
+ message: "Derived origin URL is invalid or malformed"
659
+ },
660
+ COOKIE_HTTPONLY_DISABLED: {
661
+ facility: 10,
662
+ severity: "critical",
663
+ msgId: "COOKIE_HTTPONLY_DISABLED",
664
+ message: "Cookie is configured without HttpOnly. This allows JavaScript access via document.cookie and increases XSS exposure."
665
+ },
666
+ COOKIE_WILDCARD_DOMAIN: {
667
+ facility: 10,
668
+ severity: "critical",
669
+ msgId: "COOKIE_WILDCARD_DOMAIN",
670
+ message: "Cookie 'Domain' is set to a wildcard, which is insecure and should be avoided."
671
+ },
672
+ COOKIE_SECURE_DISABLED: {
673
+ facility: 10,
674
+ severity: "warning",
675
+ msgId: "COOKIE_SECURE_DISABLED",
676
+ message: "Cookie is configured with 'Secure' but the request is not HTTPS. The 'Secure' attribute will be ignored by the browser."
677
+ },
678
+ COOKIE_SAMESITE_NONE_WITHOUT_SECURE: {
679
+ facility: 10,
680
+ severity: "warning",
681
+ msgId: "COOKIE_SAMESITE_NONE_WITHOUT_SECURE",
682
+ message: "Cookie uses SameSite=None without Secure. Falling back to SameSite=Lax for safer defaults."
683
+ },
684
+ COOKIE_INSECURE_IN_PRODUCTION: {
685
+ facility: 10,
686
+ severity: "critical",
687
+ msgId: "COOKIE_INSECURE_IN_PRODUCTION",
688
+ message: "Cookies are being served over an insecure connection in production, which is a serious security risk."
689
+ },
690
+ COOKIE_HOST_STRATEGY_INSECURE: {
691
+ facility: 10,
692
+ severity: "critical",
693
+ msgId: "COOKIE_HOST_STRATEGY_INSECURE",
694
+ message: "__Host- cookies require a secure HTTPS context. Falling back to standard cookie settings."
695
+ },
696
+ UNTRUSTED_ORIGIN: {
697
+ facility: 10,
698
+ severity: "error",
699
+ msgId: "UNTRUSTED_ORIGIN",
700
+ message: "The constructed origin URL is not trusted."
290
701
  }
291
- const salt = env.AURA_AUTH_SALT ?? env.AUTH_SALT ?? createDerivedSalt(secret);
292
- const { derivedKey: derivedSigningKey } = (0, import_jose.createDeriveKey)(secret, salt, "signing");
293
- const { derivedKey: derivedEncryptionKey } = (0, import_jose.createDeriveKey)(secret, salt, "encryption");
294
- const { derivedKey: derivedCsrfTokenKey } = (0, import_jose.createDeriveKey)(secret, salt, "csrfToken");
295
- const { decodeJWT, encodeJWT } = (0, import_jose.createJWT)({ jws: derivedSigningKey, jwe: derivedEncryptionKey });
296
- const { signJWS, verifyJWS } = (0, import_jose.createJWS)(derivedCsrfTokenKey);
297
- const { encryptJWE, decryptJWE } = (0, import_jose.createJWE)(derivedEncryptionKey);
702
+ };
703
+ var createLogEntry = (key, overrides) => {
704
+ const message = logMessages[key];
298
705
  return {
299
- decodeJWT,
300
- encodeJWT,
301
- signJWS,
302
- verifyJWS,
303
- encryptJWE,
304
- decryptJWE
706
+ ...message,
707
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
708
+ hostname: "aura-auth",
709
+ procId: typeof process !== "undefined" && process.pid ? process.pid.toString() : "-",
710
+ ...overrides
305
711
  };
306
712
  };
713
+ var logLevelToSeverity = {
714
+ debug: ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"],
715
+ info: ["info", "notice", "warning", "error", "critical", "alert", "emergency"],
716
+ warn: ["warning", "error", "critical", "alert", "emergency"],
717
+ error: ["error", "critical", "alert", "emergency"]
718
+ };
719
+ var isValidLogLevel = (value) => {
720
+ return value === "debug" || value === "info" || value === "warn" || value === "error";
721
+ };
722
+ var getSeverityLevel = (severity) => {
723
+ const severities = {
724
+ emergency: 0,
725
+ alert: 1,
726
+ critical: 2,
727
+ error: 3,
728
+ warning: 4,
729
+ notice: 5,
730
+ info: 6,
731
+ debug: 7
732
+ };
733
+ return severities[severity] ?? 6;
734
+ };
735
+ var createSyslogMessage = (options2) => {
736
+ const { timestamp, hostname, appName = "aura-auth", procId = "-", msgId, structuredData, message } = options2;
737
+ const pri = (options2.facility ?? 16) * 8 + getSeverityLevel(options2.severity);
738
+ const structuredDataStr = createStructuredData(structuredData ?? {});
739
+ return `<${pri}>1 ${timestamp} ${hostname} ${appName} ${procId} ${msgId} ${structuredDataStr} ${message}`;
740
+ };
741
+ var createLogger = (logger) => {
742
+ if (!logger) return void 0;
743
+ const level = logger.level;
744
+ const allowedSeverities = logLevelToSeverity[level] ?? [];
745
+ return {
746
+ level,
747
+ log(key, overrides) {
748
+ const entry = createLogEntry(key, overrides);
749
+ if (!allowedSeverities.includes(entry.severity)) return entry;
750
+ logger.log({
751
+ timestamp: entry.timestamp,
752
+ appName: entry.appName ?? "aura-auth",
753
+ hostname: entry.hostname ?? "aura-auth",
754
+ ...entry
755
+ });
756
+ return entry;
757
+ }
758
+ };
759
+ };
760
+ var createProxyLogger = (config2) => {
761
+ const level = getEnv("LOG_LEVEL");
762
+ const debug = getEnvBoolean("DEBUG");
763
+ if (typeof config2?.logger === "object") {
764
+ return createLogger({
765
+ log: config2.logger?.log || createSyslogMessage,
766
+ level: isValidLogLevel(config2.logger?.level) ? config2.logger?.level : isValidLogLevel(level) ? level : "error"
767
+ });
768
+ }
769
+ if (debug || config2?.logger === true || level) {
770
+ return createLogger({
771
+ level: isValidLogLevel(level) ? level : "debug",
772
+ log: (options2) => {
773
+ const message = createSyslogMessage(options2);
774
+ console.log(message);
775
+ }
776
+ });
777
+ }
778
+ return void 0;
779
+ };
307
780
 
308
781
  // src/cookie.ts
309
782
  var import_cookie = require("@aura-stack/router/cookie");
@@ -340,10 +813,11 @@ var setCookie = (cookieName, value, options2) => {
340
813
  var expiredCookieAttributes = {
341
814
  ...defaultCookieOptions,
342
815
  expires: /* @__PURE__ */ new Date(0),
343
- maxAge: 0
816
+ maxAge: 0,
817
+ secure: true
344
818
  };
345
819
  var getCookie = (request, cookieName) => {
346
- const cookies = request.headers.get("Cookie");
820
+ const cookies = request instanceof Request ? request.headers.get("Cookie") : request.get("Cookie");
347
821
  if (!cookies) {
348
822
  throw new AuthInternalError("COOKIE_NOT_FOUND", "No cookies found. There is no active session");
349
823
  }
@@ -361,31 +835,27 @@ var createSessionCookie = async (jose, session) => {
361
835
  throw new AuthInternalError("INVALID_JWT_TOKEN", "Failed to create session cookie", { cause: error });
362
836
  }
363
837
  };
364
- var defineSecureCookieOptions = (useSecure, attributes, strategy) => {
838
+ var defineSecureCookieOptions = (useSecure, attributes, strategy, logger) => {
365
839
  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
- );
840
+ logger?.log("COOKIE_HTTPONLY_DISABLED");
369
841
  }
370
842
  if (attributes.domain === "*") {
371
843
  attributes.domain = void 0;
372
- console.warn("[WARNING]: Cookie 'Domain' is set to '*', which is insecure. Avoid wildcard domains.");
844
+ logger?.log("COOKIE_WILDCARD_DOMAIN");
373
845
  }
374
846
  if (!useSecure) {
375
847
  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
- );
848
+ logger?.log("COOKIE_SECURE_DISABLED");
379
849
  }
380
850
  if (attributes.sameSite == "none") {
381
851
  attributes.sameSite = "lax";
382
- console.warn("[WARNING]: SameSite=None requires Secure attribute. Changing SameSite to 'Lax'.");
852
+ logger?.log("COOKIE_SAMESITE_NONE_WITHOUT_SECURE");
383
853
  }
384
- if (process.env.NODE_ENV === "production") {
385
- console.warn("[WARNING]: In production, ensure cookies are served over HTTPS to maintain security.");
854
+ if (env.NODE_ENV === "production") {
855
+ logger?.log("COOKIE_INSECURE_IN_PRODUCTION");
386
856
  }
387
857
  if (strategy === "host") {
388
- console.warn("[WARNING]: __Host- cookies require a secure context. Falling back to standard cookie settings.");
858
+ logger?.log("COOKIE_HOST_STRATEGY_INSECURE");
389
859
  }
390
860
  return {
391
861
  ...defaultCookieOptions,
@@ -399,7 +869,7 @@ var defineSecureCookieOptions = (useSecure, attributes, strategy) => {
399
869
  ...defaultHostCookieConfig
400
870
  } : { ...defaultCookieOptions, ...attributes, ...defaultSecureCookieConfig };
401
871
  };
402
- var createCookieStore = (useSecure, prefix, overrides) => {
872
+ var createCookieStore = (useSecure, prefix, overrides, logger) => {
403
873
  prefix ??= COOKIE_NAME;
404
874
  const securePrefix = useSecure ? "__Secure-" : "";
405
875
  const hostPrefix = useSecure ? "__Host-" : "";
@@ -412,7 +882,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
412
882
  ...defaultCookieOptions,
413
883
  ...overrides?.sessionToken?.attributes
414
884
  },
415
- overrides?.sessionToken?.attributes?.strategy ?? "secure"
885
+ overrides?.sessionToken?.attributes?.strategy ?? "secure",
886
+ logger
416
887
  )
417
888
  },
418
889
  state: {
@@ -423,7 +894,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
423
894
  ...oauthCookieOptions,
424
895
  ...overrides?.state?.attributes
425
896
  },
426
- overrides?.state?.attributes?.strategy ?? "secure"
897
+ overrides?.state?.attributes?.strategy ?? "secure",
898
+ logger
427
899
  )
428
900
  },
429
901
  csrfToken: {
@@ -432,9 +904,11 @@ var createCookieStore = (useSecure, prefix, overrides) => {
432
904
  useSecure,
433
905
  {
434
906
  ...overrides?.csrfToken?.attributes,
435
- ...defaultHostCookieConfig
907
+ ...defaultHostCookieConfig,
908
+ sameSite: "strict"
436
909
  },
437
- overrides?.csrfToken?.attributes?.strategy ?? "host"
910
+ overrides?.csrfToken?.attributes?.strategy ?? "host",
911
+ logger
438
912
  )
439
913
  },
440
914
  redirectTo: {
@@ -445,7 +919,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
445
919
  ...oauthCookieOptions,
446
920
  ...overrides?.redirectTo?.attributes
447
921
  },
448
- overrides?.redirectTo?.attributes?.strategy ?? "secure"
922
+ overrides?.redirectTo?.attributes?.strategy ?? "secure",
923
+ logger
449
924
  )
450
925
  },
451
926
  redirectURI: {
@@ -456,7 +931,8 @@ var createCookieStore = (useSecure, prefix, overrides) => {
456
931
  ...oauthCookieOptions,
457
932
  ...overrides?.redirectURI?.attributes
458
933
  },
459
- overrides?.redirectURI?.attributes?.strategy ?? "secure"
934
+ overrides?.redirectURI?.attributes?.strategy ?? "secure",
935
+ logger
460
936
  )
461
937
  },
462
938
  codeVerifier: {
@@ -467,224 +943,438 @@ var createCookieStore = (useSecure, prefix, overrides) => {
467
943
  ...oauthCookieOptions,
468
944
  ...overrides?.codeVerifier?.attributes
469
945
  },
470
- overrides?.codeVerifier?.attributes?.strategy ?? "secure"
946
+ overrides?.codeVerifier?.attributes?.strategy ?? "secure",
947
+ logger
471
948
  )
472
949
  }
473
950
  };
474
951
  };
475
952
 
476
953
  // 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"
954
+ var github = (options2) => {
955
+ return {
956
+ id: "github",
957
+ name: "GitHub",
958
+ authorizeURL: "https://github.com/login/oauth/authorize",
959
+ accessToken: "https://github.com/login/oauth/access_token",
960
+ userInfo: "https://api.github.com/user",
961
+ scope: "read:user user:email",
962
+ responseType: "code",
963
+ profile: (profile) => {
964
+ return {
965
+ sub: profile.id.toString(),
966
+ name: profile.name ?? profile.login,
967
+ email: profile.email ?? void 0,
968
+ image: profile.avatar_url
969
+ };
970
+ },
971
+ ...options2
972
+ };
485
973
  };
486
974
 
487
975
  // 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) {
497
- return {
498
- sub: profile.uuid ?? profile.account_id,
499
- name: profile.display_name ?? profile.nickname,
500
- image: profile.links.avatar.href
501
- };
502
- }
976
+ var bitbucket = (options2) => {
977
+ return {
978
+ id: "bitbucket",
979
+ name: "Bitbucket",
980
+ authorizeURL: "https://bitbucket.org/site/oauth2/authorize",
981
+ accessToken: "https://bitbucket.org/site/oauth2/access_token",
982
+ userInfo: "https://api.bitbucket.org/2.0/user",
983
+ scope: "account email",
984
+ responseType: "code",
985
+ profile(profile) {
986
+ return {
987
+ sub: profile.uuid ?? profile.account_id,
988
+ name: profile.display_name ?? profile.nickname,
989
+ image: profile.links.avatar?.href,
990
+ email: void 0
991
+ };
992
+ },
993
+ ...options2
994
+ };
503
995
  };
504
996
 
505
997
  // 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
- }
998
+ var figma = (options2) => {
999
+ return {
1000
+ id: "figma",
1001
+ name: "Figma",
1002
+ authorizeURL: "https://www.figma.com/oauth",
1003
+ accessToken: "https://api.figma.com/v1/oauth/token",
1004
+ userInfo: "https://api.figma.com/v1/me",
1005
+ scope: "current_user:read",
1006
+ responseType: "code",
1007
+ profile(profile) {
1008
+ return {
1009
+ sub: profile.id,
1010
+ name: profile.handle,
1011
+ email: profile.email,
1012
+ image: profile.img_url
1013
+ };
1014
+ },
1015
+ ...options2
1016
+ };
522
1017
  };
523
1018
 
524
1019
  // 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
- }
1020
+ var discord = (options2) => {
1021
+ return {
1022
+ id: "discord",
1023
+ name: "Discord",
1024
+ authorizeURL: "https://discord.com/oauth2/authorize",
1025
+ accessToken: "https://discord.com/api/oauth2/token",
1026
+ userInfo: "https://discord.com/api/users/@me",
1027
+ scope: "identify email",
1028
+ responseType: "code",
1029
+ profile(profile) {
1030
+ let image = "";
1031
+ if (profile.avatar === null) {
1032
+ const index = profile.discriminator === "0" ? (BigInt(profile.id) >> 22n) % 6n : Number(profile.discriminator) % 5;
1033
+ image = `https://cdn.discordapp.com/embed/avatars/${index}.png`;
1034
+ } else {
1035
+ const format = profile.avatar.startsWith("a_") ? "gif" : "png";
1036
+ image = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;
1037
+ }
1038
+ return {
1039
+ sub: profile.id,
1040
+ name: profile.global_name ?? profile.username,
1041
+ email: profile.email ?? "",
1042
+ image
1043
+ };
1044
+ },
1045
+ ...options2
1046
+ };
549
1047
  };
550
1048
 
551
1049
  // 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
- }
1050
+ var gitlab = (options2) => {
1051
+ return {
1052
+ id: "gitlab",
1053
+ name: "GitLab",
1054
+ authorizeURL: "https://gitlab.com/oauth/authorize",
1055
+ accessToken: "https://gitlab.com/oauth/token",
1056
+ userInfo: "https://gitlab.com/api/v4/user",
1057
+ scope: "read_user",
1058
+ responseType: "code",
1059
+ profile(profile) {
1060
+ return {
1061
+ sub: profile.id.toString(),
1062
+ name: profile.name ?? profile.username,
1063
+ email: profile.email,
1064
+ image: profile.avatar_url
1065
+ };
1066
+ },
1067
+ ...options2
1068
+ };
568
1069
  };
569
1070
 
570
1071
  // 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
- }
1072
+ var spotify = (options2) => {
1073
+ return {
1074
+ id: "spotify",
1075
+ name: "Spotify",
1076
+ authorizeURL: "https://accounts.spotify.com/authorize",
1077
+ accessToken: "https://accounts.spotify.com/api/token",
1078
+ userInfo: "https://api.spotify.com/v1/me",
1079
+ scope: "user-read-private user-read-email",
1080
+ responseType: "code",
1081
+ profile(profile) {
1082
+ return {
1083
+ sub: profile.id,
1084
+ name: profile.display_name,
1085
+ email: profile.email,
1086
+ image: profile.images[0]?.url ?? void 0
1087
+ };
1088
+ },
1089
+ ...options2
1090
+ };
1091
+ };
1092
+
1093
+ // src/oauth/x.ts
1094
+ var x = (options2) => {
1095
+ return {
1096
+ id: "x",
1097
+ name: "X",
1098
+ authorizeURL: "https://twitter.com/i/oauth2/authorize",
1099
+ accessToken: "https://api.twitter.com/2/oauth2/token",
1100
+ userInfo: "https://api.twitter.com/2/users/me?user.fields=profile_image_url",
1101
+ scope: "tweet.read users.read offline.access",
1102
+ responseType: "code",
1103
+ profile(profile) {
1104
+ return {
1105
+ sub: profile.data.id,
1106
+ name: profile.data.name,
1107
+ image: profile.data.profile_image_url,
1108
+ email: void 0
1109
+ };
1110
+ },
1111
+ ...options2
1112
+ };
1113
+ };
1114
+
1115
+ // src/oauth/strava.ts
1116
+ var strava = (options2) => {
1117
+ return {
1118
+ id: "strava",
1119
+ name: "Strava",
1120
+ authorizeURL: "https://www.strava.com/oauth/authorize",
1121
+ accessToken: "https://www.strava.com/oauth/token",
1122
+ userInfo: "https://www.strava.com/api/v3/athlete",
1123
+ scope: "read",
1124
+ responseType: "code",
1125
+ profile(profile) {
1126
+ return {
1127
+ sub: profile.id.toString(),
1128
+ name: `${profile.firstname} ${profile.lastname}`,
1129
+ image: profile.profile,
1130
+ email: void 0
1131
+ };
1132
+ },
1133
+ ...options2
1134
+ };
1135
+ };
1136
+
1137
+ // src/oauth/mailchimp.ts
1138
+ var mailchimp = (options2) => {
1139
+ return {
1140
+ id: "mailchimp",
1141
+ name: "Mailchimp",
1142
+ authorizeURL: "https://login.mailchimp.com/oauth2/authorize",
1143
+ accessToken: "https://login.mailchimp.com/oauth2/token",
1144
+ userInfo: "https://login.mailchimp.com/oauth2/metadata",
1145
+ scope: "",
1146
+ responseType: "code",
1147
+ profile(profile) {
1148
+ return {
1149
+ sub: profile.user_id,
1150
+ name: profile.accountname,
1151
+ email: profile.login.email,
1152
+ image: profile.login.avatar
1153
+ };
1154
+ },
1155
+ ...options2
1156
+ };
1157
+ };
1158
+
1159
+ // src/oauth/pinterest.ts
1160
+ var pinterest = (options2) => {
1161
+ return {
1162
+ id: "pinterest",
1163
+ name: "Pinterest",
1164
+ authorizeURL: "https://www.pinterest.com/oauth",
1165
+ accessToken: "https://api.pinterest.com/v5/oauth/token",
1166
+ userInfo: "https://api.pinterest.com/v5/user_account",
1167
+ scope: "user_accounts:read",
1168
+ responseType: "code",
1169
+ profile(profile) {
1170
+ return {
1171
+ sub: profile.id,
1172
+ name: profile.username,
1173
+ image: profile.profile_image,
1174
+ email: void 0
1175
+ };
1176
+ },
1177
+ ...options2
1178
+ };
587
1179
  };
588
1180
 
589
- // 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
- }
1181
+ // src/oauth/twitch.ts
1182
+ var twitch = (options2) => {
1183
+ const clientId = options2?.clientId ?? getEnv("TWITCH_CLIENT_ID");
1184
+ return {
1185
+ id: "twitch",
1186
+ name: "Twitch",
1187
+ authorize: {
1188
+ url: "https://id.twitch.tv/oauth2/authorize",
1189
+ params: { scope: "user:read:email", responseType: "code" }
1190
+ },
1191
+ accessToken: "https://id.twitch.tv/oauth2/token",
1192
+ userInfo: {
1193
+ url: "https://api.twitch.tv/helix/users",
1194
+ headers: {
1195
+ "Client-ID": clientId
1196
+ }
1197
+ },
1198
+ profile(profile) {
1199
+ const user = profile.data[0];
1200
+ if (!user) {
1201
+ throw new Error("No user data found in Twitch profile response");
1202
+ }
1203
+ return {
1204
+ sub: user.id,
1205
+ name: user.display_name,
1206
+ email: user.email,
1207
+ picture: user.profile_image_url
1208
+ };
1209
+ },
1210
+ ...options2
1211
+ };
606
1212
  };
607
1213
 
608
- // 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
- }
1214
+ // src/oauth/notion.ts
1215
+ var notion = (options2) => {
1216
+ return {
1217
+ id: "notion",
1218
+ name: "Notion",
1219
+ authorize: {
1220
+ url: "https://api.notion.com/v1/oauth/authorize",
1221
+ params: {
1222
+ owner: "user",
1223
+ scope: "user:read",
1224
+ responseType: "code"
1225
+ }
1226
+ },
1227
+ accessToken: {
1228
+ url: "https://api.notion.com/v1/oauth/token",
1229
+ headers: {
1230
+ Authorization: createBasicAuthHeader(
1231
+ options2?.clientId ?? "NOTION_CLIENT_ID",
1232
+ options2?.clientSecret ?? "NOTION_CLIENT_SECRET"
1233
+ )
1234
+ }
1235
+ },
1236
+ userInfo: {
1237
+ url: "https://api.notion.com/v1/users/me",
1238
+ headers: {
1239
+ "Notion-Version": "2022-06-28"
1240
+ }
1241
+ },
1242
+ profile(profile) {
1243
+ return {
1244
+ sub: profile.id,
1245
+ name: profile.name,
1246
+ image: profile.avatar_url ?? "",
1247
+ email: profile?.bot?.owner?.user?.person?.email
1248
+ };
1249
+ },
1250
+ ...options2
1251
+ };
625
1252
  };
626
1253
 
627
- // 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
- }
1254
+ // src/oauth/dropbox.ts
1255
+ var dropbox = (options2) => {
1256
+ return {
1257
+ id: "dropbox",
1258
+ name: "Dropbox",
1259
+ authorize: {
1260
+ url: "https://www.dropbox.com/oauth2/authorize",
1261
+ params: { scope: "account_info.read" }
1262
+ },
1263
+ accessToken: "https://api.dropboxapi.com/oauth2/token",
1264
+ userInfo: {
1265
+ method: "POST",
1266
+ url: "https://api.dropboxapi.com/2/users/get_current_account"
1267
+ },
1268
+ profile(profile) {
1269
+ return {
1270
+ sub: profile.account_id,
1271
+ name: profile.name.display_name,
1272
+ email: profile.email,
1273
+ image: profile.profile_photo_url
1274
+ };
1275
+ },
1276
+ ...options2
1277
+ };
644
1278
  };
645
1279
 
646
- // 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
- }
1280
+ // src/oauth/atlassian.ts
1281
+ var atlassian = (options2) => {
1282
+ return {
1283
+ id: "atlassian",
1284
+ name: "Atlassian",
1285
+ authorize: {
1286
+ url: "https://auth.atlassian.com/authorize",
1287
+ params: {
1288
+ audience: "api.atlassian.com",
1289
+ scope: "read:me read:account",
1290
+ prompt: "consent"
1291
+ }
1292
+ },
1293
+ authorizeURL: "https://auth.atlassian.com/authorize",
1294
+ accessToken: "https://auth.atlassian.com/oauth/token",
1295
+ userInfo: "https://api.atlassian.com/me",
1296
+ scope: "read:me read:account",
1297
+ responseType: "code",
1298
+ profile(profile) {
1299
+ return {
1300
+ sub: profile.account_id,
1301
+ name: profile.name,
1302
+ email: profile.email,
1303
+ image: profile.picture
1304
+ };
1305
+ },
1306
+ ...options2
1307
+ };
663
1308
  };
664
1309
 
665
1310
  // src/schemas.ts
666
- var import_zod = require("zod");
667
- var OAuthProviderConfigSchema = (0, import_zod.object)({
668
- authorizeURL: (0, import_zod.string)().url(),
669
- accessToken: (0, import_zod.string)().url(),
670
- scope: (0, import_zod.string)().optional(),
671
- userInfo: (0, import_zod.string)().url(),
672
- responseType: (0, import_zod.enum)(["code", "token", "id_token"]),
673
- clientId: (0, import_zod.string)(),
674
- clientSecret: (0, import_zod.string)()
1311
+ var import_v4 = require("zod/v4");
1312
+ var AuthorizeConfigSchema = import_v4.z.union([
1313
+ (0, import_v4.string)().url(),
1314
+ (0, import_v4.object)({
1315
+ url: (0, import_v4.string)().url(),
1316
+ params: (0, import_v4.object)({
1317
+ responseType: (0, import_v4.enum)(["code", "token", "id_token", "refresh_token"]).optional(),
1318
+ scope: (0, import_v4.string)().optional()
1319
+ })
1320
+ })
1321
+ ]);
1322
+ var AccessTokenConfigSchema = import_v4.z.union([
1323
+ (0, import_v4.string)().url(),
1324
+ (0, import_v4.object)({
1325
+ url: (0, import_v4.string)().url(),
1326
+ headers: import_v4.z.record((0, import_v4.string)(), (0, import_v4.string)()).optional()
1327
+ })
1328
+ ]);
1329
+ var UserInfoConfigSchema = import_v4.z.union([
1330
+ (0, import_v4.string)().url(),
1331
+ (0, import_v4.object)({
1332
+ url: (0, import_v4.string)().url(),
1333
+ headers: import_v4.z.record((0, import_v4.string)(), (0, import_v4.string)()).optional(),
1334
+ method: (0, import_v4.string)().optional()
1335
+ })
1336
+ ]);
1337
+ var OAuthProviderCredentialsSchema = (0, import_v4.object)({
1338
+ id: (0, import_v4.string)(),
1339
+ name: (0, import_v4.string)(),
1340
+ authorize: AuthorizeConfigSchema.optional(),
1341
+ /** @deprecated */
1342
+ authorizeURL: (0, import_v4.string)().url().optional(),
1343
+ accessToken: AccessTokenConfigSchema,
1344
+ /** @deprecated */
1345
+ scope: (0, import_v4.string)().optional(),
1346
+ userInfo: UserInfoConfigSchema,
1347
+ /** @deprecated */
1348
+ responseType: (0, import_v4.enum)(["code", "token", "id_token", "refresh_token"]).optional(),
1349
+ clientId: (0, import_v4.string)(),
1350
+ clientSecret: (0, import_v4.string)(),
1351
+ profile: import_v4.z.function().optional()
1352
+ });
1353
+ var OAuthProviderConfigSchema = (0, import_v4.object)({
1354
+ authorize: AuthorizeConfigSchema.optional(),
1355
+ /** @deprecated */
1356
+ authorizeURL: (0, import_v4.string)().url().optional(),
1357
+ accessToken: AccessTokenConfigSchema,
1358
+ /** @deprecated */
1359
+ scope: (0, import_v4.string)().optional(),
1360
+ userInfo: UserInfoConfigSchema,
1361
+ /** @deprecated */
1362
+ responseType: (0, import_v4.enum)(["code", "token", "id_token", "refresh_token"]).optional(),
1363
+ clientId: (0, import_v4.string)(),
1364
+ clientSecret: (0, import_v4.string)()
675
1365
  });
676
1366
  var OAuthAuthorization = OAuthProviderConfigSchema.extend({
677
- redirectURI: (0, import_zod.string)(),
678
- state: (0, import_zod.string)(),
679
- codeChallenge: (0, import_zod.string)(),
680
- codeChallengeMethod: (0, import_zod.enum)(["plain", "S256"])
1367
+ redirectURI: (0, import_v4.string)(),
1368
+ state: (0, import_v4.string)(),
1369
+ codeChallenge: (0, import_v4.string)(),
1370
+ codeChallengeMethod: (0, import_v4.enum)(["plain", "S256"])
681
1371
  });
682
- var OAuthAuthorizationResponse = (0, import_zod.object)({
683
- state: (0, import_zod.string)({ message: "Missing state parameter in the OAuth authorization response." }),
684
- code: (0, import_zod.string)({ message: "Missing code parameter in the OAuth authorization response." })
1372
+ var OAuthAuthorizationResponse = (0, import_v4.object)({
1373
+ state: (0, import_v4.string)({ message: "Missing state parameter in the OAuth authorization response." }),
1374
+ code: (0, import_v4.string)({ message: "Missing code parameter in the OAuth authorization response." })
685
1375
  });
686
- var OAuthAuthorizationErrorResponse = (0, import_zod.object)({
687
- error: (0, import_zod.enum)([
1376
+ var OAuthAuthorizationErrorResponse = (0, import_v4.object)({
1377
+ error: (0, import_v4.enum)([
688
1378
  "invalid_request",
689
1379
  "unauthorized_client",
690
1380
  "access_denied",
@@ -693,24 +1383,24 @@ var OAuthAuthorizationErrorResponse = (0, import_zod.object)({
693
1383
  "server_error",
694
1384
  "temporarily_unavailable"
695
1385
  ]),
696
- error_description: (0, import_zod.string)().optional(),
697
- error_uri: (0, import_zod.string)().optional(),
698
- state: (0, import_zod.string)()
1386
+ error_description: (0, import_v4.string)().optional(),
1387
+ error_uri: (0, import_v4.string)().optional(),
1388
+ state: (0, import_v4.string)()
699
1389
  });
700
1390
  var OAuthAccessToken = OAuthProviderConfigSchema.extend({
701
- redirectURI: (0, import_zod.string)(),
702
- code: (0, import_zod.string)(),
703
- codeVerifier: (0, import_zod.string)().min(43).max(128)
1391
+ redirectURI: (0, import_v4.string)(),
1392
+ code: (0, import_v4.string)(),
1393
+ codeVerifier: (0, import_v4.string)().min(43).max(128)
704
1394
  });
705
- var OAuthAccessTokenResponse = (0, import_zod.object)({
706
- access_token: (0, import_zod.string)(),
707
- token_type: (0, import_zod.string)().optional(),
708
- expires_in: (0, import_zod.number)().optional(),
709
- refresh_token: (0, import_zod.string)().optional(),
710
- scope: (0, import_zod.string)().optional().or((0, import_zod.null)())
1395
+ var OAuthAccessTokenResponse = (0, import_v4.object)({
1396
+ access_token: (0, import_v4.string)(),
1397
+ token_type: (0, import_v4.string)().optional(),
1398
+ expires_in: (0, import_v4.number)().optional(),
1399
+ refresh_token: (0, import_v4.string)().optional(),
1400
+ scope: (0, import_v4.union)([(0, import_v4.string)().optional().or((0, import_v4.null)()), (0, import_v4.array)((0, import_v4.string)()).optional()])
711
1401
  });
712
- var OAuthAccessTokenErrorResponse = (0, import_zod.object)({
713
- error: (0, import_zod.enum)([
1402
+ var OAuthAccessTokenErrorResponse = (0, import_v4.object)({
1403
+ error: (0, import_v4.enum)([
714
1404
  "invalid_request",
715
1405
  "invalid_client",
716
1406
  "invalid_grant",
@@ -718,16 +1408,16 @@ var OAuthAccessTokenErrorResponse = (0, import_zod.object)({
718
1408
  "unsupported_grant_type",
719
1409
  "invalid_scope"
720
1410
  ]),
721
- error_description: (0, import_zod.string)().optional(),
722
- error_uri: (0, import_zod.string)().optional()
1411
+ error_description: (0, import_v4.string)().optional(),
1412
+ error_uri: (0, import_v4.string)().optional()
723
1413
  });
724
- var OAuthErrorResponse = (0, import_zod.object)({
725
- error: (0, import_zod.string)(),
726
- error_description: (0, import_zod.string)().optional()
1414
+ var OAuthErrorResponse = (0, import_v4.object)({
1415
+ error: (0, import_v4.string)(),
1416
+ error_description: (0, import_v4.string)().optional()
727
1417
  });
728
- var OAuthEnvSchema = (0, import_zod.object)({
729
- clientId: import_zod.z.string().min(1, "OAuth Client ID is required in the environment variables."),
730
- clientSecret: import_zod.z.string().min(1, "OAuth Client Secret is required in the environment variables.")
1418
+ var OAuthEnvSchema = (0, import_v4.object)({
1419
+ clientId: import_v4.z.string().min(1, "OAuth Client ID is required in the environment variables."),
1420
+ clientSecret: import_v4.z.string().min(1, "OAuth Client Secret is required in the environment variables.")
731
1421
  });
732
1422
 
733
1423
  // src/oauth/index.ts
@@ -741,18 +1431,19 @@ var builtInOAuthProviders = {
741
1431
  x,
742
1432
  strava,
743
1433
  mailchimp,
744
- pinterest
1434
+ pinterest,
1435
+ twitch,
1436
+ notion,
1437
+ dropbox,
1438
+ atlassian
745
1439
  };
746
1440
  var defineOAuthEnvironment = (oauth) => {
747
- const env = process.env;
748
- const clientIdSuffix = `${oauth.toUpperCase()}_CLIENT_ID`;
749
- const clientSecretSuffix = `${oauth.toUpperCase()}_CLIENT_SECRET`;
750
1441
  const loadEnvs = OAuthEnvSchema.safeParse({
751
- clientId: env[`AURA_AUTH_${clientIdSuffix}`] ?? env[`AUTH_${clientIdSuffix}`] ?? env[`${clientIdSuffix}`],
752
- clientSecret: env[`AURA_AUTH_${clientSecretSuffix}`] ?? env[`AUTH_${clientSecretSuffix}`] ?? env[`${clientSecretSuffix}`]
1442
+ clientId: getEnv(`${oauth.toUpperCase()}_CLIENT_ID`),
1443
+ clientSecret: getEnv(`${oauth.toUpperCase()}_CLIENT_SECRET`)
753
1444
  });
754
1445
  if (!loadEnvs.success) {
755
- const msg = JSON.stringify(formatZodError(loadEnvs.error), null, 2);
1446
+ const msg = JSON.stringify({ [oauth]: formatZodError(loadEnvs.error) }, null, 2);
756
1447
  throw new AuthInternalError("INVALID_ENVIRONMENT_CONFIGURATION", msg);
757
1448
  }
758
1449
  return loadEnvs.data;
@@ -760,24 +1451,64 @@ var defineOAuthEnvironment = (oauth) => {
760
1451
  var defineOAuthProviderConfig = (config2) => {
761
1452
  if (typeof config2 === "string") {
762
1453
  const definition = defineOAuthEnvironment(config2);
763
- const oauthConfig = builtInOAuthProviders[config2];
764
- return {
765
- ...oauthConfig,
766
- ...definition
767
- };
1454
+ const oauthConfig = builtInOAuthProviders[config2]();
1455
+ const parsed2 = OAuthProviderCredentialsSchema.safeParse({ ...oauthConfig, ...definition });
1456
+ if (!parsed2.success) {
1457
+ const details = JSON.stringify({ [config2]: formatZodError(parsed2.error) }, null, 2);
1458
+ throw new AuthInternalError(
1459
+ "INVALID_OAUTH_PROVIDER_CONFIGURATION",
1460
+ `Invalid configuration for OAuth provider "${config2}": ${details}`
1461
+ );
1462
+ }
1463
+ return parsed2.data;
1464
+ }
1465
+ const hasCredentials = config2.clientId && config2.clientSecret;
1466
+ const envConfig = hasCredentials ? {} : defineOAuthEnvironment(config2.id);
1467
+ const parsed = OAuthProviderCredentialsSchema.safeParse({ ...envConfig, ...config2 });
1468
+ if (!parsed.success) {
1469
+ const details = JSON.stringify({ [config2.id]: formatZodError(parsed.error) }, null, 2);
1470
+ throw new AuthInternalError(
1471
+ "INVALID_OAUTH_PROVIDER_CONFIGURATION",
1472
+ `Invalid configuration for OAuth provider "${config2.id}": ${details}`
1473
+ );
768
1474
  }
769
- return config2;
1475
+ return parsed.data;
770
1476
  };
771
1477
  var createBuiltInOAuthProviders = (oauth = []) => {
772
1478
  return oauth.reduce((previous, config2) => {
773
1479
  const oauthConfig = defineOAuthProviderConfig(config2);
1480
+ if (oauthConfig.id in previous) {
1481
+ throw new AuthInternalError(
1482
+ "DUPLICATED_OAUTH_PROVIDER_ID",
1483
+ `Duplicate OAuth provider id "${oauthConfig.id}" found. Each provider must have a unique id.`
1484
+ );
1485
+ }
774
1486
  return { ...previous, [oauthConfig.id]: oauthConfig };
775
1487
  }, {});
776
1488
  };
777
1489
 
778
- // src/actions/signIn/signIn.ts
779
- var import_zod2 = require("zod");
780
- var import_router2 = require("@aura-stack/router");
1490
+ // src/context.ts
1491
+ var createContext = (config2) => {
1492
+ const trustedProxyHeadersEnv = getEnv("TRUSTED_PROXY_HEADERS");
1493
+ const useProxyHeaders = trustedProxyHeadersEnv === void 0 ? config2?.trustedProxyHeaders ?? false : getEnvBoolean("TRUSTED_PROXY_HEADERS");
1494
+ const logger = createProxyLogger(config2);
1495
+ const cookiePrefix = config2?.cookies?.prefix;
1496
+ const cookieOverrides = config2?.cookies?.overrides ?? {};
1497
+ const secureCookieStore = createCookieStore(true, cookiePrefix, cookieOverrides, logger);
1498
+ const standardCookieStore = createCookieStore(false, cookiePrefix, cookieOverrides, logger);
1499
+ return {
1500
+ oauth: createBuiltInOAuthProviders(config2?.oauth),
1501
+ cookies: standardCookieStore,
1502
+ jose: createJoseInstance(config2?.secret),
1503
+ secret: config2?.secret,
1504
+ basePath: config2?.basePath ?? "/auth",
1505
+ trustedProxyHeaders: useProxyHeaders,
1506
+ trustedOrigins: getEnvArray("TRUSTED_ORIGINS").length > 0 ? getEnvArray("TRUSTED_ORIGINS") : config2?.trustedOrigins,
1507
+ logger,
1508
+ cookieConfig: { secure: secureCookieStore, standard: standardCookieStore },
1509
+ baseURL: config2?.baseURL
1510
+ };
1511
+ };
781
1512
 
782
1513
  // src/headers.ts
783
1514
  var cacheControl = {
@@ -786,126 +1517,442 @@ var cacheControl = {
786
1517
  Expires: "0",
787
1518
  Vary: "Cookie"
788
1519
  };
1520
+ var contentSecurityPolicy = {
1521
+ "Content-Security-Policy": [
1522
+ "default-src 'none'",
1523
+ "script-src 'self'",
1524
+ "frame-src 'none'",
1525
+ "object-src 'none'",
1526
+ "frame-ancestors 'none'",
1527
+ "base-uri 'none'"
1528
+ ].join("; ")
1529
+ };
1530
+ var secureHeaders = {
1531
+ "X-Content-Type-Options": "nosniff",
1532
+ "X-Frame-Options": "DENY",
1533
+ "Referrer-Policy": "strict-origin-when-cross-origin"
1534
+ };
1535
+ var secureApiHeaders = {
1536
+ ...cacheControl,
1537
+ ...contentSecurityPolicy,
1538
+ ...secureHeaders
1539
+ };
789
1540
 
790
- // src/actions/signIn/authorization.ts
791
- var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod) => {
792
- const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
793
- if (!parsed.success) {
794
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
795
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
1541
+ // src/api/signIn.ts
1542
+ var import_router2 = require("@aura-stack/router");
1543
+
1544
+ // src/secure.ts
1545
+ var generateSecure = (length = 32) => {
1546
+ return import_jose2.base64url.encode((0, import_crypto.getRandomBytes)(length));
1547
+ };
1548
+ var createSecretValue = (length = 32) => {
1549
+ return import_jose2.base64url.encode((0, import_crypto.getRandomBytes)(length));
1550
+ };
1551
+ var createHash = async (data) => {
1552
+ const subtle = (0, import_crypto.getSubtleCrypto)();
1553
+ const digest = await subtle.digest("SHA-256", import_crypto.encoder.encode(data));
1554
+ return import_jose2.base64url.encode(new Uint8Array(digest));
1555
+ };
1556
+ var createPKCE = async (verifier) => {
1557
+ const byteLength = verifier ? void 0 : Math.floor(Math.random() * (96 - 32 + 1) + 32);
1558
+ const codeVerifier = verifier ?? generateSecure(byteLength ?? 64);
1559
+ if (codeVerifier.length < 43 || codeVerifier.length > 128) {
1560
+ throw new AuthSecurityError("PKCE_VERIFIER_INVALID", "The code verifier must be between 43 and 128 characters in length.");
796
1561
  }
797
- const { authorizeURL, ...options2 } = parsed.data;
798
- const { userInfo, accessToken, clientSecret, ...required } = options2;
799
- const searchParams = new URLSearchParams(toCastCase(required));
800
- return `${authorizeURL}?${searchParams}`;
801
- };
802
- var getOriginURL = (request, trustedProxyHeaders) => {
803
- 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));
1562
+ const codeChallenge = await createHash(codeVerifier);
1563
+ return { codeVerifier, codeChallenge, method: "S256" };
1564
+ };
1565
+ var createCSRF = async (jose, csrfCookie) => {
1566
+ try {
1567
+ const token = generateSecure(32);
1568
+ if (csrfCookie) {
1569
+ await jose.verifyJWS(csrfCookie, jwtVerificationOptions);
1570
+ return csrfCookie;
1571
+ }
1572
+ return jose.signJWS({ token });
1573
+ } catch {
1574
+ const token = generateSecure(32);
1575
+ return jose.signJWS({ token });
1576
+ }
1577
+ };
1578
+ var verifyCSRF = async (jose, cookie, header) => {
1579
+ try {
1580
+ const cookiePayload = await jose.verifyJWS(cookie, jwtVerificationOptions);
1581
+ const headerPayload = await jose.verifyJWS(header, jwtVerificationOptions);
1582
+ if (!isJWTPayloadWithToken(cookiePayload)) {
1583
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Cookie payload missing token field.");
1584
+ }
1585
+ if (!isJWTPayloadWithToken(headerPayload)) {
1586
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "Header payload missing token field.");
1587
+ }
1588
+ if (!equals(cookiePayload.token.length, headerPayload.token.length)) {
1589
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1590
+ }
1591
+ if (!timingSafeEqual(cookiePayload.token, headerPayload.token)) {
1592
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1593
+ }
1594
+ return true;
1595
+ } catch {
1596
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "The CSRF tokens do not match.");
1597
+ }
1598
+ };
1599
+
1600
+ // src/actions/signIn/authorization-url.ts
1601
+ var setSearchParams = (url, params) => {
1602
+ for (const [key, value] of Object.entries(params)) {
1603
+ if (value !== void 0 && value !== "") {
1604
+ url.searchParams.set(key, value);
1605
+ }
1606
+ }
1607
+ };
1608
+ var buildAuthorizationURL = (oauth, redirect_uri, state, code_challenge, code_challenge_method) => {
1609
+ const authorizeConfig = oauth.authorize;
1610
+ const baseURL = typeof authorizeConfig === "string" ? authorizeConfig : authorizeConfig?.url ?? oauth.authorizeURL;
1611
+ if (!baseURL) {
1612
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "Missing authorization URL in OAuth provider configuration.");
1613
+ }
1614
+ const url = new URL(baseURL);
1615
+ const authorizeParams = typeof authorizeConfig === "string" ? void 0 : authorizeConfig?.params;
1616
+ setSearchParams(url, {
1617
+ response_type: authorizeParams?.responseType ?? oauth.responseType ?? "code",
1618
+ client_id: oauth.clientId,
1619
+ redirect_uri,
1620
+ state,
1621
+ code_challenge,
1622
+ code_challenge_method,
1623
+ scope: authorizeParams?.scope ?? oauth.scope,
1624
+ prompt: authorizeParams?.prompt,
1625
+ response_mode: authorizeParams?.responseMode,
1626
+ login_hint: authorizeParams?.loginHint,
1627
+ nonce: authorizeParams?.nonce,
1628
+ display: authorizeParams?.display,
1629
+ audience: authorizeParams?.audience
1630
+ });
1631
+ return url.toString();
1632
+ };
1633
+ var createAuthorizationURL = async (oauth, redirectURI, ctx) => {
1634
+ const state = createSecretValue();
1635
+ const { codeVerifier, codeChallenge, method } = await createPKCE();
1636
+ const authorization = buildAuthorizationURL(oauth, redirectURI, state, codeChallenge, method);
1637
+ const parsed = OAuthAuthorization.safeParse({ ...oauth, redirectURI, state, codeChallenge, codeChallengeMethod: method });
1638
+ if (!parsed.success) {
1639
+ ctx?.logger?.log("INVALID_OAUTH_CONFIGURATION", {
1640
+ structuredData: {
1641
+ scope: oauth?.scope ?? "",
1642
+ redirect_uri: redirectURI,
1643
+ has_state: Boolean(state),
1644
+ has_code_challenge: Boolean(codeChallenge),
1645
+ code_challenge_method: method
1646
+ }
1647
+ });
1648
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
810
1649
  }
1650
+ return {
1651
+ authorization,
1652
+ state,
1653
+ codeVerifier,
1654
+ method
1655
+ };
811
1656
  };
812
- var createRedirectURI = (request, oauth, basePath, trustedProxyHeaders) => {
813
- const url = getOriginURL(request, trustedProxyHeaders);
814
- return `${url.origin}${basePath}/callback/${oauth}`;
1657
+
1658
+ // src/actions/signIn/authorization.ts
1659
+ var getTrustedOrigins = async (request, trustedOrigins) => {
1660
+ if (!trustedOrigins) return [];
1661
+ const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins;
1662
+ return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
1663
+ };
1664
+ var getBaseURL2 = async ({
1665
+ ctx,
1666
+ request,
1667
+ headers: headersInit
1668
+ }) => {
1669
+ const origin = getEnv("BASE_URL") || ctx?.baseURL;
1670
+ if (origin && origin !== "/") return origin;
1671
+ if (ctx?.trustedProxyHeaders) {
1672
+ const headers = headersInit && new Headers(headersInit) || request?.headers;
1673
+ const protocol = headers?.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers?.get("X-Forwarded-Proto") ?? "http";
1674
+ const host = headers?.get("Host") ?? headers?.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers?.get("X-Forwarded-Host") ?? null;
1675
+ if (host) return `${protocol}://${host}`;
1676
+ throw new AuthInternalError(
1677
+ "INVALID_OAUTH_CONFIGURATION",
1678
+ "The URL cannot be constructed. Please set the BASE_URL environment variable or provide trusted proxy host headers."
1679
+ );
1680
+ }
1681
+ try {
1682
+ return new URL(request?.url ?? "not-found").origin;
1683
+ } catch (error) {
1684
+ throw new AuthInternalError(
1685
+ "INVALID_OAUTH_CONFIGURATION",
1686
+ "The URL cannot be constructed. Please set the BASE_URL environment variable or enable trustedProxyHeaders.",
1687
+ { cause: error }
1688
+ );
1689
+ }
815
1690
  };
816
- var createRedirectTo = (request, redirectTo, trustedProxyHeaders) => {
1691
+ var getOriginURL = async (request, context) => {
1692
+ const trustedOrigins = await getTrustedOrigins(request, context?.trustedOrigins);
1693
+ trustedOrigins.push(new URL(request.url).origin);
1694
+ const origin = await getBaseURL2({ request, ctx: context });
1695
+ if (!isTrustedOrigin(origin, trustedOrigins)) {
1696
+ context?.logger?.log("UNTRUSTED_ORIGIN", { structuredData: { origin } });
1697
+ throw new AuthInternalError("UNTRUSTED_ORIGIN", "The constructed origin URL is not trusted.");
1698
+ }
1699
+ return origin;
1700
+ };
1701
+ var createRedirectURI = async (request, oauth, context) => {
1702
+ const origin = await getOriginURL(request, context);
1703
+ return `${origin}${context.basePath}/callback/${oauth}`;
1704
+ };
1705
+ var createSignInURL = async ({
1706
+ request,
1707
+ oauth,
1708
+ ctx,
1709
+ redirectTo
1710
+ }) => {
1711
+ const origin = await getOriginURL(request, ctx);
1712
+ const searchParams = new URLSearchParams();
1713
+ if (redirectTo !== void 0) searchParams.set("redirectTo", String(redirectTo));
1714
+ return `${origin}${ctx.basePath}/signIn/${oauth}?${searchParams.toString()}`;
1715
+ };
1716
+ var createRedirectTo = async (request, redirectTo, context) => {
817
1717
  try {
818
1718
  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);
1719
+ const requestOrigin = await getOriginURL(request, context);
1720
+ const origins = await getTrustedOrigins(request, context?.trustedOrigins);
1721
+ const validateURL = (url) => {
1722
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
1723
+ if (isRelativeURL(url)) return url;
1724
+ if (origins.length > 0) {
1725
+ if (isTrustedOrigin(url, origins)) {
1726
+ const urlOrigin = new URL(url).origin;
1727
+ for (const pattern of origins) {
1728
+ const regex = patternToRegex(pattern);
1729
+ if (regex?.test(urlOrigin)) {
1730
+ return isSameOrigin(url, request.url) ? extractPath(url) : url;
1731
+ }
1732
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return url;
1733
+ }
1734
+ }
1735
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
1736
+ return "/";
825
1737
  }
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
- );
1738
+ if (isSameOrigin(url, requestOrigin)) {
1739
+ return extractPath(url);
832
1740
  }
833
- return sanitizeURL(redirectToURL.pathname);
1741
+ context?.logger?.log("OPEN_REDIRECT_ATTACK");
1742
+ return "/";
1743
+ };
1744
+ return validateURL(redirectTo ?? headers.get("Referer") ?? headers.get("Origin") ?? "/");
1745
+ } catch (error) {
1746
+ context?.logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED");
1747
+ return "/";
1748
+ }
1749
+ };
1750
+
1751
+ // src/api/signIn.ts
1752
+ var signIn = async (oauth, {
1753
+ ctx,
1754
+ headers: headersInit,
1755
+ redirectTo = "/",
1756
+ redirect,
1757
+ request: requestInit
1758
+ }) => {
1759
+ const headers = new Headers(headersInit);
1760
+ const provider = ctx.oauth[oauth];
1761
+ if (!provider) {
1762
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", `The OAuth provider "${oauth}" is not configured.`);
1763
+ }
1764
+ let request = requestInit;
1765
+ if (!request) {
1766
+ const origin = await getBaseURL2({ ctx, headers });
1767
+ const url = `${origin}${ctx.basePath}/signIn/${oauth}`;
1768
+ request = new Request(url, { headers });
1769
+ }
1770
+ if (redirect === false) {
1771
+ const signInURL = await createSignInURL({ request, oauth, ctx, redirectTo });
1772
+ return { redirect: false, signInURL };
1773
+ }
1774
+ const redirectURI = await createRedirectURI(request, oauth, ctx);
1775
+ const redirectToValue = await createRedirectTo(request, redirectTo, ctx);
1776
+ const { authorization, state, codeVerifier } = await createAuthorizationURL(provider, redirectURI, ctx);
1777
+ ctx?.logger?.log("SIGN_IN_INITIATED", {
1778
+ structuredData: { oauth_provider: oauth }
1779
+ });
1780
+ const headersList = new import_router2.HeadersBuilder(cacheControl).setHeader("Location", authorization).setCookie(ctx.cookies.state.name, state, ctx.cookies.state.attributes).setCookie(ctx.cookies.redirectURI.name, redirectURI, ctx.cookies.redirectURI.attributes).setCookie(ctx.cookies.redirectTo.name, redirectToValue, ctx.cookies.redirectTo.attributes).setCookie(ctx.cookies.codeVerifier.name, codeVerifier, ctx.cookies.codeVerifier.attributes).toHeaders();
1781
+ return Response.json(
1782
+ { redirect: redirect ?? true, signInURL: authorization },
1783
+ {
1784
+ status: redirect ?? true ? 302 : 200,
1785
+ headers: headersList
834
1786
  }
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
- );
842
- }
843
- return sanitizeURL(refererURL.pathname);
1787
+ );
1788
+ };
1789
+
1790
+ // src/api/signOut.ts
1791
+ var import_router3 = require("@aura-stack/router");
1792
+ var signOut = async ({
1793
+ ctx,
1794
+ headers: headersInit,
1795
+ redirectTo = "/",
1796
+ skipCSRFCheck = false
1797
+ }) => {
1798
+ const headers = new Headers(headersInit);
1799
+ const header = headers.get("X-CSRF-Token");
1800
+ let session = null;
1801
+ let csrfToken = null;
1802
+ try {
1803
+ session = getCookie(headers, ctx.cookies.sessionToken.name);
1804
+ } catch {
1805
+ throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
1806
+ }
1807
+ try {
1808
+ csrfToken = getCookie(headers, ctx.cookies.csrfToken.name);
1809
+ } catch {
1810
+ throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
1811
+ }
1812
+ ctx?.logger?.log("SIGN_OUT_ATTEMPT", {
1813
+ structuredData: {
1814
+ has_session: Boolean(session),
1815
+ has_csrf_token: Boolean(csrfToken),
1816
+ has_csrf_header: Boolean(header),
1817
+ skip_csrf_check: skipCSRFCheck
844
1818
  }
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).");
849
- }
850
- return sanitizeURL(originURL.pathname);
1819
+ });
1820
+ if (!session) {
1821
+ ctx?.logger?.log("SESSION_TOKEN_MISSING");
1822
+ throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
1823
+ }
1824
+ if (!skipCSRFCheck) {
1825
+ if (!csrfToken) {
1826
+ ctx?.logger?.log("CSRF_TOKEN_MISSING");
1827
+ throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
851
1828
  }
852
- return "/";
1829
+ if (!header) {
1830
+ ctx?.logger?.log("CSRF_HEADER_MISSING");
1831
+ throw new AuthSecurityError("CSRF_HEADER_MISSING", "The CSRF header is missing.");
1832
+ }
1833
+ try {
1834
+ await verifyCSRF(ctx.jose, csrfToken, header);
1835
+ } catch (error) {
1836
+ ctx?.logger?.log("CSRF_TOKEN_INVALID", { structuredData: { error_type: getErrorName(error) } });
1837
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "CSRF token verification failed");
1838
+ }
1839
+ ctx?.logger?.log("SIGN_OUT_CSRF_VERIFIED");
1840
+ } else {
1841
+ try {
1842
+ await ctx.jose.verifyJWS(csrfToken);
1843
+ } catch (error) {
1844
+ ctx?.logger?.log("CSRF_TOKEN_INVALID", { structuredData: { error_type: getErrorName(error) } });
1845
+ throw new AuthSecurityError("CSRF_TOKEN_INVALID", "CSRF token verification failed");
1846
+ }
1847
+ }
1848
+ try {
1849
+ await ctx.jose.decodeJWT(session);
1850
+ ctx?.logger?.log("SIGN_OUT_SUCCESS");
853
1851
  } catch (error) {
854
- if (isAuthSecurityError(error)) {
855
- throw error;
1852
+ ctx?.logger?.log("INVALID_JWT_TOKEN", { structuredData: { error_type: getErrorName(error) } });
1853
+ }
1854
+ const headersList = new import_router3.HeadersBuilder(secureApiHeaders).setHeader("Location", redirectTo).setCookie(ctx.cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(ctx.cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1855
+ return Response.json(
1856
+ { redirect: Boolean(redirectTo), url: redirectTo },
1857
+ {
1858
+ status: 202,
1859
+ headers: headersList
856
1860
  }
857
- throw new AuthSecurityError("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", "Invalid origin (potential CSRF).");
1861
+ );
1862
+ };
1863
+
1864
+ // src/api/getSession.ts
1865
+ var getSession = async ({ ctx, headers }) => {
1866
+ try {
1867
+ const session = getCookie(new Headers(headers), ctx.cookies.sessionToken.name);
1868
+ const decoded = await ctx.jose.decodeJWT(session);
1869
+ ctx?.logger?.log("AUTH_SESSION_VALID");
1870
+ const { exp, iat, jti, nbf, aud, iss, ...user } = decoded;
1871
+ return {
1872
+ session: {
1873
+ user,
1874
+ expires: toISOString(exp * 1e3)
1875
+ },
1876
+ authenticated: true
1877
+ };
1878
+ } catch (error) {
1879
+ ctx?.logger?.log("AUTH_SESSION_INVALID", { structuredData: { error_type: getErrorName(error) } });
1880
+ return { session: null, authenticated: false };
858
1881
  }
859
1882
  };
860
1883
 
1884
+ // src/api/createApi.ts
1885
+ var createAuthAPI = (ctx) => {
1886
+ return {
1887
+ getSession: async (options2) => {
1888
+ const session = await getSession({ ctx, headers: options2.headers });
1889
+ return session;
1890
+ },
1891
+ signIn: async (oauth, options2) => {
1892
+ return signIn(oauth, {
1893
+ ctx,
1894
+ headers: options2?.headers,
1895
+ request: options2?.request,
1896
+ redirect: options2?.redirect,
1897
+ redirectTo: options2?.redirectTo
1898
+ });
1899
+ },
1900
+ signOut: async (options2) => {
1901
+ const redirectTo = validateRedirectTo(options2?.redirectTo ?? "/");
1902
+ return signOut({ ctx, headers: options2.headers, redirectTo, skipCSRFCheck: true });
1903
+ }
1904
+ };
1905
+ };
1906
+
861
1907
  // src/actions/signIn/signIn.ts
1908
+ var import_v42 = require("zod/v4");
1909
+ var import_router4 = require("@aura-stack/router");
862
1910
  var signInConfig = (oauth) => {
863
- return (0, import_router2.createEndpointConfig)("/signIn/:oauth", {
1911
+ return (0, import_router4.createEndpointConfig)("/signIn/:oauth", {
864
1912
  schemas: {
865
- params: import_zod2.z.object({
866
- oauth: import_zod2.z.enum(
1913
+ params: import_v42.z.object({
1914
+ oauth: import_v42.z.enum(
867
1915
  Object.keys(oauth),
868
1916
  "The OAuth provider is not supported or invalid."
869
1917
  )
870
1918
  }),
871
- searchParams: import_zod2.z.object({
872
- redirectTo: import_zod2.z.string().optional()
1919
+ searchParams: import_v42.z.object({
1920
+ redirect: import_v42.z.stringbool().optional().default(true),
1921
+ redirectTo: import_v42.z.string().optional()
873
1922
  })
874
1923
  }
875
1924
  });
876
1925
  };
877
1926
  var signInAction = (oauth) => {
878
- return (0, import_router2.createEndpoint)(
1927
+ return (0, import_router4.createEndpoint)(
879
1928
  "GET",
880
1929
  "/signIn/:oauth",
881
1930
  async (ctx) => {
882
1931
  const {
883
1932
  request,
884
1933
  params: { oauth: oauth2 },
885
- searchParams: { redirectTo },
886
- context: { oauth: providers, cookies, trustedProxyHeaders, basePath }
1934
+ searchParams: { redirectTo, redirect },
1935
+ context
887
1936
  } = ctx;
888
- const state = generateSecure();
889
- const redirectURI = createRedirectURI(request, oauth2, basePath, trustedProxyHeaders);
890
- const redirectToValue = createRedirectTo(request, redirectTo, trustedProxyHeaders);
891
- const { codeVerifier, codeChallenge, method } = await createPKCE();
892
- const authorization = createAuthorizationURL(providers[oauth2], redirectURI, state, codeChallenge, method);
893
- 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
- return Response.json(
895
- { oauth: oauth2 },
896
- {
897
- status: 302,
898
- headers
899
- }
900
- );
1937
+ const signInResult = await signIn(oauth2, {
1938
+ ctx: context,
1939
+ headers: request.headers,
1940
+ redirect,
1941
+ redirectTo,
1942
+ request
1943
+ });
1944
+ if (!redirect) {
1945
+ return Response.json(signInResult, { status: 200 });
1946
+ }
1947
+ return signInResult;
901
1948
  },
902
1949
  signInConfig(oauth)
903
1950
  );
904
1951
  };
905
1952
 
906
1953
  // src/actions/callback/callback.ts
907
- var import_zod3 = require("zod");
908
- var import_router3 = require("@aura-stack/router");
1954
+ var import_v43 = require("zod/v4");
1955
+ var import_router5 = require("@aura-stack/router");
909
1956
 
910
1957
  // src/request.ts
911
1958
  var fetchAsync = async (url, options2 = {}, timeout = 5e3) => {
@@ -928,96 +1975,165 @@ var getDefaultUserInfo = (profile) => {
928
1975
  image: profile?.image ?? profile?.picture
929
1976
  };
930
1977
  };
931
- var getUserInfo = async (oauthConfig, accessToken) => {
932
- const userinfoEndpoint = oauthConfig.userInfo;
1978
+ var getUserInfo = async (oauthConfig, accessToken, logger) => {
1979
+ const userInfoConfig = oauthConfig.userInfo;
1980
+ const userinfoURL = typeof userInfoConfig === "string" ? userInfoConfig : userInfoConfig.url;
1981
+ const extraHeaders = typeof userInfoConfig === "string" ? void 0 : userInfoConfig.headers;
1982
+ const method = typeof userInfoConfig === "string" ? "GET" : (userInfoConfig.method ?? "GET").toUpperCase();
933
1983
  try {
934
- const response = await fetchAsync(userinfoEndpoint, {
935
- method: "GET",
1984
+ logger?.log("OAUTH_USERINFO_REQUEST_INITIATED", {
1985
+ structuredData: {
1986
+ endpoint: userinfoURL
1987
+ }
1988
+ });
1989
+ const response = await fetchAsync(userinfoURL, {
1990
+ method,
936
1991
  headers: {
1992
+ "User-Agent": `Aura Auth/${AURA_AUTH_VERSION}`,
937
1993
  Accept: "application/json",
938
- Authorization: `Bearer ${accessToken}`
1994
+ Authorization: `Bearer ${accessToken}`,
1995
+ ...extraHeaders ?? {}
939
1996
  }
940
1997
  });
1998
+ if (!response.ok) {
1999
+ logger?.log("OAUTH_USERINFO_INVALID_RESPONSE");
2000
+ throw new OAuthProtocolError("INVALID_REQUEST", "Invalid userinfo response format");
2001
+ }
941
2002
  const json = await response.json();
942
2003
  const { success, data } = OAuthErrorResponse.safeParse(json);
943
2004
  if (success) {
944
- throw new OAuthProtocolError(
945
- data.error,
946
- data?.error_description ?? "An error occurred while fetching user information."
947
- );
2005
+ logger?.log("OAUTH_USERINFO_ERROR", {
2006
+ message: "Error response received from OAuth userinfo endpoint",
2007
+ structuredData: {
2008
+ error: data.error,
2009
+ error_description: data.error_description ?? ""
2010
+ }
2011
+ });
2012
+ throw new OAuthProtocolError("INVALID_REQUEST", "An error was received from the OAuth userinfo endpoint.");
948
2013
  }
2014
+ logger?.log("OAUTH_USERINFO_SUCCESS");
949
2015
  return oauthConfig?.profile ? oauthConfig.profile(json) : getDefaultUserInfo(json);
950
2016
  } catch (error) {
951
2017
  if (isOAuthProtocolError(error)) {
952
2018
  throw error;
953
2019
  }
2020
+ logger?.log("OAUTH_USERINFO_REQUEST_FAILED");
954
2021
  if (isNativeError(error)) {
955
- throw new OAuthProtocolError("invalid_request", error.message, "", { cause: error });
2022
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information from OAuth provider", "", {
2023
+ cause: error
2024
+ });
956
2025
  }
957
- throw new OAuthProtocolError("invalid_request", "Failed to fetch user information.", "", { cause: error });
2026
+ throw new OAuthProtocolError("SERVER_ERROR", "Failed to fetch user information", "", { cause: error });
958
2027
  }
959
2028
  };
960
2029
 
961
2030
  // src/actions/callback/access-token.ts
962
- var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier) => {
963
- const parsed = OAuthAccessToken.safeParse({ ...oauthConfig, redirectURI, code, codeVerifier });
964
- if (!parsed.success) {
965
- const msg = JSON.stringify(formatZodError(parsed.error), null, 2);
966
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", msg);
2031
+ var createAccessToken = async (oauthConfig, redirectURI, code, codeVerifier, logger) => {
2032
+ const { accessToken, clientId, clientSecret } = oauthConfig;
2033
+ if (!clientId || !clientSecret || !redirectURI || !code || !codeVerifier || !accessToken) {
2034
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
2035
+ structuredData: {
2036
+ has_client_id: Boolean(clientId),
2037
+ has_client_secret: Boolean(clientSecret),
2038
+ has_access_token: Boolean(accessToken),
2039
+ has_redirect_uri: Boolean(redirectURI),
2040
+ has_code: Boolean(code),
2041
+ has_code_verifier: Boolean(codeVerifier)
2042
+ }
2043
+ });
2044
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
967
2045
  }
968
- const { accessToken, clientId, clientSecret, code: codeParsed, redirectURI: redirectParsed } = parsed.data;
2046
+ const tokenURL = typeof accessToken === "string" ? accessToken : accessToken.url;
2047
+ const extraHeaders = typeof accessToken === "string" ? void 0 : accessToken.headers;
969
2048
  try {
970
- const response = await fetchAsync(accessToken, {
2049
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_INITIATED", {
2050
+ structuredData: {
2051
+ has_client_id: Boolean(clientId),
2052
+ redirect_uri: redirectURI,
2053
+ grant_type: "authorization_code"
2054
+ }
2055
+ });
2056
+ const response = await fetchAsync(tokenURL, {
971
2057
  method: "POST",
972
2058
  headers: {
2059
+ ...extraHeaders ?? {},
973
2060
  Accept: "application/json",
974
2061
  "Content-Type": "application/x-www-form-urlencoded"
975
2062
  },
976
2063
  body: new URLSearchParams({
977
2064
  client_id: clientId,
978
2065
  client_secret: clientSecret,
979
- code: codeParsed,
980
- redirect_uri: redirectParsed,
2066
+ code,
2067
+ redirect_uri: redirectURI,
981
2068
  grant_type: "authorization_code",
982
2069
  code_verifier: codeVerifier
983
2070
  }).toString()
984
2071
  });
2072
+ if (!response.ok) {
2073
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
2074
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response");
2075
+ }
985
2076
  const json = await response.json();
986
2077
  const token = OAuthAccessTokenResponse.safeParse(json);
987
2078
  if (!token.success) {
988
2079
  const { success, data } = OAuthAccessTokenErrorResponse.safeParse(json);
989
2080
  if (!success) {
990
- throw new OAuthProtocolError("INVALID_REQUEST", "Invalid access token response format");
2081
+ logger?.log("INVALID_OAUTH_ACCESS_TOKEN_RESPONSE");
2082
+ throw new OAuthProtocolError("invalid_request", "Invalid access token response format");
991
2083
  }
992
- throw new OAuthProtocolError(data.error, data?.error_description ?? "Failed to retrieve access token");
2084
+ logger?.log("OAUTH_ACCESS_TOKEN_ERROR", {
2085
+ structuredData: {
2086
+ error: data.error,
2087
+ error_description: data.error_description ?? ""
2088
+ }
2089
+ });
2090
+ throw new OAuthProtocolError("INVALID_ACCESS_TOKEN", "Failed to retrieve access token");
993
2091
  }
2092
+ logger?.log("OAUTH_ACCESS_TOKEN_SUCCESS");
994
2093
  return token.data;
995
2094
  } catch (error) {
2095
+ logger?.log("OAUTH_ACCESS_TOKEN_REQUEST_FAILED");
2096
+ if (error instanceof Error) {
2097
+ throw new OAuthProtocolError("server_error", "Failed to communicate with OAuth provider", "", { cause: error });
2098
+ }
996
2099
  throw error;
997
2100
  }
998
2101
  };
999
2102
 
1000
2103
  // src/actions/callback/callback.ts
1001
2104
  var callbackConfig = (oauth) => {
1002
- return (0, import_router3.createEndpointConfig)("/callback/:oauth", {
2105
+ return (0, import_router5.createEndpointConfig)("/callback/:oauth", {
1003
2106
  schemas: {
1004
- params: import_zod3.z.object({
1005
- oauth: import_zod3.z.enum(
2107
+ params: import_v43.z.object({
2108
+ oauth: import_v43.z.enum(
1006
2109
  Object.keys(oauth),
1007
2110
  "The OAuth provider is not supported or invalid."
1008
2111
  )
1009
2112
  }),
1010
- searchParams: import_zod3.z.object({
1011
- code: import_zod3.z.string("Missing code parameter in the OAuth authorization response."),
1012
- state: import_zod3.z.string("Missing state parameter in the OAuth authorization response.")
2113
+ searchParams: import_v43.z.object({
2114
+ code: import_v43.z.string("Missing code parameter in the OAuth authorization response."),
2115
+ state: import_v43.z.string("Missing state parameter in the OAuth authorization response.")
1013
2116
  })
1014
2117
  },
1015
- middlewares: [
2118
+ use: [
1016
2119
  (ctx) => {
1017
- const response = OAuthAuthorizationErrorResponse.safeParse(ctx.searchParams);
2120
+ const {
2121
+ searchParams,
2122
+ context: { logger }
2123
+ } = ctx;
2124
+ const response = OAuthAuthorizationErrorResponse.safeParse(searchParams);
1018
2125
  if (response.success) {
1019
2126
  const { error, error_description } = response.data;
1020
- throw new OAuthProtocolError(error, error_description ?? "OAuth Authorization Error");
2127
+ const criticalAuthErrors = ["access_denied", "server_error"];
2128
+ const severity = criticalAuthErrors.includes(error.toLowerCase()) ? "critical" : "warning";
2129
+ logger?.log("OAUTH_AUTHORIZATION_ERROR", {
2130
+ severity,
2131
+ structuredData: {
2132
+ error,
2133
+ error_description: error_description ?? ""
2134
+ }
2135
+ });
2136
+ throw new OAuthProtocolError(error, error_description || "OAuth Authorization Error");
1021
2137
  }
1022
2138
  return ctx;
1023
2139
  }
@@ -1025,7 +2141,7 @@ var callbackConfig = (oauth) => {
1025
2141
  });
1026
2142
  };
1027
2143
  var callbackAction = (oauth) => {
1028
- return (0, import_router3.createEndpoint)(
2144
+ return (0, import_router5.createEndpoint)(
1029
2145
  "GET",
1030
2146
  "/callback/:oauth",
1031
2147
  async (ctx) => {
@@ -1033,31 +2149,54 @@ var callbackAction = (oauth) => {
1033
2149
  request,
1034
2150
  params: { oauth: oauth2 },
1035
2151
  searchParams: { code, state },
1036
- context: { oauth: providers, cookies, jose }
2152
+ context
1037
2153
  } = ctx;
2154
+ const { oauth: providers, cookies, jose, logger, trustedOrigins } = context;
1038
2155
  const oauthConfig = providers[oauth2];
1039
2156
  const cookieState = getCookie(request, cookies.state.name);
2157
+ const codeVerifier = getCookie(request, cookies.codeVerifier.name);
1040
2158
  const cookieRedirectTo = getCookie(request, cookies.redirectTo.name);
1041
2159
  const cookieRedirectURI = getCookie(request, cookies.redirectURI.name);
1042
- const codeVerifier = getCookie(request, cookies.codeVerifier.name);
1043
- if (!equals(cookieState, state)) {
2160
+ if (!timingSafeEqual(cookieState, state)) {
2161
+ logger?.log("MISMATCHING_STATE", {
2162
+ structuredData: {
2163
+ oauth_provider: oauth2
2164
+ }
2165
+ });
1044
2166
  throw new AuthSecurityError(
1045
2167
  "MISMATCHING_STATE",
1046
2168
  "The provided state passed in the OAuth response does not match the stored state."
1047
2169
  );
1048
2170
  }
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
- );
2171
+ const accessToken = await createAccessToken(oauthConfig, cookieRedirectURI, code, codeVerifier, logger);
2172
+ const origins = await getTrustedOrigins(request, trustedOrigins);
2173
+ const requestOrigin = await getOriginURL(request, context);
2174
+ if (!isRelativeURL(cookieRedirectTo)) {
2175
+ const isValid = origins.length > 0 ? isTrustedOrigin(cookieRedirectTo, origins) : isSameOrigin(cookieRedirectTo, requestOrigin);
2176
+ if (!isValid) {
2177
+ logger?.log("POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED", {
2178
+ structuredData: {
2179
+ redirect_path: cookieRedirectTo,
2180
+ provider: oauth2,
2181
+ has_trusted_origins: origins.length > 0,
2182
+ request_origin: requestOrigin
2183
+ }
2184
+ });
2185
+ throw new AuthSecurityError(
2186
+ "POTENTIAL_OPEN_REDIRECT_ATTACK_DETECTED",
2187
+ "Invalid redirect path. Potential open redirect attack detected."
2188
+ );
2189
+ }
1056
2190
  }
1057
- const userInfo = await getUserInfo(oauthConfig, accessToken.access_token);
2191
+ const userInfo = await getUserInfo(oauthConfig, accessToken.access_token, logger);
1058
2192
  const sessionCookie = await createSessionCookie(jose, userInfo);
1059
2193
  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();
2194
+ logger?.log("OAUTH_CALLBACK_SUCCESS", {
2195
+ structuredData: {
2196
+ provider: oauth2
2197
+ }
2198
+ });
2199
+ const headers = new import_router5.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
2200
  return Response.json({ oauth: oauth2 }, { status: 302, headers });
1062
2201
  },
1063
2202
  callbackConfig(oauth)
@@ -1065,74 +2204,63 @@ var callbackAction = (oauth) => {
1065
2204
  };
1066
2205
 
1067
2206
  // src/actions/session/session.ts
1068
- var import_router4 = require("@aura-stack/router");
1069
- var sessionAction = (0, import_router4.createEndpoint)("GET", "/session", async (ctx) => {
2207
+ var import_router6 = require("@aura-stack/router");
2208
+ var sessionAction = (0, import_router6.createEndpoint)("GET", "/session", async (ctx) => {
1070
2209
  const {
1071
2210
  request,
1072
- context: { jose, cookies }
2211
+ context: { cookies }
1073
2212
  } = ctx;
1074
2213
  try {
1075
- const session = getCookie(request, cookies.sessionToken.name);
1076
- const decoded = await jose.decodeJWT(session);
1077
- const { exp, iat, jti, nbf, ...user } = decoded;
1078
- const headers = new Headers(cacheControl);
1079
- return Response.json({ user, expires: toISOString(exp * 1e3) }, { headers });
2214
+ const session = await getSession({ ctx: ctx.context, headers: request.headers });
2215
+ if (!session.authenticated) {
2216
+ throw new AuthInternalError("INVALID_JWT_TOKEN", "Session not authenticated");
2217
+ }
2218
+ return Response.json(session, { headers: secureApiHeaders });
1080
2219
  } catch (error) {
1081
- const headers = new import_router4.HeadersBuilder(cacheControl).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1082
- return Response.json({ authenticated: false, message: "Unauthorized" }, { status: 401, headers });
2220
+ const headers = new import_router6.HeadersBuilder(secureApiHeaders).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
2221
+ return Response.json({ session: null, authenticated: false }, { status: 401, headers });
1083
2222
  }
1084
2223
  });
1085
2224
 
1086
2225
  // src/actions/signOut/signOut.ts
1087
- var import_zod4 = require("zod");
1088
- var import_router5 = require("@aura-stack/router");
1089
- var config = (0, import_router5.createEndpointConfig)({
2226
+ var import_v44 = require("zod/v4");
2227
+ var import_router7 = require("@aura-stack/router");
2228
+ var config = (0, import_router7.createEndpointConfig)({
1090
2229
  schemas: {
1091
- searchParams: import_zod4.z.object({
1092
- token_type_hint: import_zod4.z.literal("session_token"),
1093
- redirectTo: import_zod4.z.string().optional()
2230
+ searchParams: import_v44.z.object({
2231
+ token_type_hint: import_v44.z.literal("session_token"),
2232
+ redirectTo: import_v44.z.string().optional()
1094
2233
  })
1095
2234
  }
1096
2235
  });
1097
- var signOutAction = (0, import_router5.createEndpoint)(
2236
+ var signOutAction = (0, import_router7.createEndpoint)(
1098
2237
  "POST",
1099
2238
  "/signOut",
1100
2239
  async (ctx) => {
1101
2240
  const {
1102
2241
  request,
1103
- headers,
1104
2242
  searchParams: { redirectTo },
1105
- context: { jose, cookies }
2243
+ context
1106
2244
  } = ctx;
1107
- const session = headers.getCookie(cookies.sessionToken.name);
1108
- const csrfToken = headers.getCookie(cookies.csrfToken.name);
1109
- const header = headers.getHeader("X-CSRF-Token");
1110
- if (!session) {
1111
- throw new AuthSecurityError("SESSION_TOKEN_MISSING", "The sessionToken is missing.");
1112
- }
1113
- if (!csrfToken) {
1114
- throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF token is missing.");
1115
- }
1116
- if (!header) {
1117
- throw new AuthSecurityError("CSRF_TOKEN_MISSING", "The CSRF header is missing.");
1118
- }
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, {
1124
- headers: headers.toHeaders()
2245
+ const baseURL = getBaseURL(request);
2246
+ const location = await createRedirectTo(
2247
+ new Request(baseURL, {
2248
+ headers: request.headers
1125
2249
  }),
1126
- redirectTo
2250
+ redirectTo,
2251
+ context
1127
2252
  );
1128
- const headersList = new import_router5.HeadersBuilder(cacheControl).setHeader("Location", location).setCookie(cookies.csrfToken.name, "", expiredCookieAttributes).setCookie(cookies.sessionToken.name, "", expiredCookieAttributes).toHeaders();
1129
- return Response.json({ message: "Signed out successfully" }, { status: import_router5.statusCode.ACCEPTED, headers: headersList });
2253
+ return await signOut({
2254
+ ctx: context,
2255
+ headers: request.headers,
2256
+ redirectTo: location
2257
+ });
1130
2258
  },
1131
2259
  config
1132
2260
  );
1133
2261
 
1134
2262
  // src/actions/csrfToken/csrfToken.ts
1135
- var import_router6 = require("@aura-stack/router");
2263
+ var import_router8 = require("@aura-stack/router");
1136
2264
  var getCSRFToken = (request, cookieName) => {
1137
2265
  try {
1138
2266
  return getCookie(request, cookieName);
@@ -1140,55 +2268,160 @@ var getCSRFToken = (request, cookieName) => {
1140
2268
  return void 0;
1141
2269
  }
1142
2270
  };
1143
- var csrfTokenAction = (0, import_router6.createEndpoint)("GET", "/csrfToken", async (ctx) => {
2271
+ var csrfTokenAction = (0, import_router8.createEndpoint)("GET", "/csrfToken", async (ctx) => {
1144
2272
  const {
1145
2273
  request,
1146
- context: { jose, cookies }
2274
+ context: { jose, cookies, logger }
1147
2275
  } = ctx;
1148
2276
  const token = getCSRFToken(request, cookies.csrfToken.name);
2277
+ logger?.log("CSRF_TOKEN_REQUESTED", { structuredData: { has_token: Boolean(token) } });
1149
2278
  const csrfToken = await createCSRF(jose, token);
1150
- const headers = new Headers(cacheControl);
2279
+ logger?.log("CSRF_TOKEN_ISSUED", { structuredData: { issued: Boolean(csrfToken) } });
2280
+ const headers = new Headers(secureApiHeaders);
1151
2281
  headers.append("Set-Cookie", setCookie(cookies.csrfToken.name, csrfToken, cookies.csrfToken.attributes));
1152
2282
  return Response.json({ csrfToken }, { headers });
1153
2283
  });
1154
2284
 
1155
- // src/index.ts
2285
+ // src/createAuth.ts
1156
2286
  var createInternalConfig = (authConfig) => {
1157
- const useSecure = authConfig?.trustedProxyHeaders ?? false;
2287
+ const context = createContext(authConfig);
1158
2288
  return {
1159
2289
  basePath: authConfig?.basePath ?? "/auth",
1160
- onError: onErrorHandler,
1161
- context: {
1162
- oauth: createBuiltInOAuthProviders(authConfig?.oauth),
1163
- cookies: createCookieStore(useSecure, authConfig?.cookies?.prefix, authConfig?.cookies?.overrides ?? {}),
1164
- jose: createJoseInstance(authConfig?.secret),
1165
- secret: authConfig?.secret,
1166
- basePath: authConfig?.basePath ?? "/auth",
1167
- trustedProxyHeaders: useSecure
1168
- },
1169
- middlewares: [
2290
+ onError: createErrorHandler(context.logger),
2291
+ context,
2292
+ use: [
1170
2293
  (ctx) => {
1171
- const useSecure2 = useSecureCookies(ctx.request, ctx.context.trustedProxyHeaders);
1172
- const cookies = createCookieStore(useSecure2, authConfig?.cookies?.prefix, authConfig?.cookies?.overrides ?? {});
1173
- ctx.context.cookies = cookies;
2294
+ const useSecure = useSecureCookies(ctx.request, ctx.context.trustedProxyHeaders);
2295
+ ctx.context.cookies = useSecure ? context.cookieConfig.secure : context.cookieConfig.standard;
1174
2296
  return ctx;
1175
2297
  }
1176
2298
  ]
1177
2299
  };
1178
2300
  };
1179
- var createAuth = (authConfig) => {
2301
+ var createAuthInstance = (authConfig) => {
1180
2302
  const config2 = createInternalConfig(authConfig);
1181
- const router = (0, import_router7.createRouter)(
2303
+ const router = (0, import_router9.createRouter)(
1182
2304
  [signInAction(config2.context.oauth), callbackAction(config2.context.oauth), sessionAction, signOutAction, csrfTokenAction],
1183
2305
  config2
1184
2306
  );
1185
2307
  return {
1186
2308
  handlers: router,
1187
- jose: config2.context.jose
2309
+ jose: config2.context.jose,
2310
+ api: createAuthAPI(config2.context)
2311
+ };
2312
+ };
2313
+ var createAuth = (config2) => {
2314
+ const authInstance = createAuthInstance(config2);
2315
+ authInstance.handlers.ALL = async (request) => {
2316
+ const method = request.method.toUpperCase();
2317
+ const methodHandlers = {
2318
+ GET: authInstance.handlers.GET,
2319
+ POST: authInstance.handlers.POST
2320
+ };
2321
+ if (method in methodHandlers) {
2322
+ return await methodHandlers[method](request);
2323
+ }
2324
+ return new Response("Method Not Allowed", {
2325
+ status: 405,
2326
+ headers: { Allow: Object.keys(methodHandlers).join(", ") }
2327
+ });
2328
+ };
2329
+ return authInstance;
2330
+ };
2331
+
2332
+ // src/client/client.ts
2333
+ var import_router10 = require("@aura-stack/router");
2334
+ var createClient = import_router10.createClient;
2335
+ var createAuthClient = (options2) => {
2336
+ if (typeof window === "undefined" && !options2.baseURL) {
2337
+ throw new AuthClientError("`baseURL` is required when createAuthClient is used outside the browser.");
2338
+ }
2339
+ const client = createClient({
2340
+ cache: "no-store",
2341
+ credentials: "include",
2342
+ baseURL: options2.baseURL ?? window.location.origin,
2343
+ ...options2
2344
+ });
2345
+ const getCSRFToken2 = async () => {
2346
+ try {
2347
+ const response = await client.get("/csrfToken");
2348
+ if (!response.ok) return null;
2349
+ const data = await response.json();
2350
+ return data.csrfToken;
2351
+ } catch (error) {
2352
+ console.error("Error fetching CSRF token:", error);
2353
+ return null;
2354
+ }
2355
+ };
2356
+ const getSession2 = async () => {
2357
+ try {
2358
+ const response = await client.get("/session");
2359
+ if (!response.ok) return null;
2360
+ const session = await response.json();
2361
+ if (!session?.authenticated) return null;
2362
+ return session.session;
2363
+ } catch (error) {
2364
+ console.error("Error fetching session:", error);
2365
+ return null;
2366
+ }
2367
+ };
2368
+ const signIn2 = async (oauth, options3) => {
2369
+ try {
2370
+ const response = await client.get("/signIn/:oauth", {
2371
+ params: {
2372
+ oauth
2373
+ },
2374
+ searchParams: {
2375
+ ...options3,
2376
+ redirect: false
2377
+ }
2378
+ });
2379
+ const json = await response.json();
2380
+ if ((options3?.redirect ?? true) && typeof window !== "undefined" && json?.signInURL) {
2381
+ window.location.assign(json.signInURL);
2382
+ }
2383
+ return json;
2384
+ } catch (error) {
2385
+ console.error("Error during sign-in:", error);
2386
+ return { redirect: false, signInURL: "/" };
2387
+ }
2388
+ };
2389
+ const signOut2 = async (options3) => {
2390
+ try {
2391
+ const csrfToken = await getCSRFToken2();
2392
+ if (!csrfToken) {
2393
+ throw new AuthClientError("Failed to fetch CSRF token for sign-out.");
2394
+ }
2395
+ const response = await client.post("/signOut", {
2396
+ searchParams: {
2397
+ redirectTo: options3?.redirectTo ?? "/",
2398
+ token_type_hint: "session_token"
2399
+ },
2400
+ headers: {
2401
+ "X-CSRF-Token": csrfToken
2402
+ }
2403
+ });
2404
+ const json = await response.json();
2405
+ if ((options3?.redirect ?? true) && typeof window !== "undefined" && json?.url) {
2406
+ window.location.assign(json.url);
2407
+ }
2408
+ return json;
2409
+ } catch (error) {
2410
+ console.error("Error during sign-out:", error);
2411
+ throw isNativeError(error) ? error : new AuthClientError("Sign-out failed.", "The sign-out request failed.", { cause: error });
2412
+ }
2413
+ };
2414
+ return {
2415
+ getSession: getSession2,
2416
+ signIn: signIn2,
2417
+ signOut: signOut2
1188
2418
  };
1189
2419
  };
1190
2420
  // Annotate the CommonJS export names for ESM import in node:
1191
2421
  0 && (module.exports = {
2422
+ builtInOAuthProviders,
1192
2423
  createAuth,
1193
- createClient
2424
+ createAuthClient,
2425
+ createClient,
2426
+ createSyslogMessage
1194
2427
  });