@aura-stack/auth 0.4.0 → 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 (149) hide show
  1. package/dist/@types/index.d.ts +6 -2
  2. package/dist/@types/router.d.d.ts +6 -2
  3. package/dist/actions/callback/access-token.cjs +103 -59
  4. package/dist/actions/callback/access-token.d.ts +7 -3
  5. package/dist/actions/callback/access-token.js +3 -3
  6. package/dist/actions/callback/callback.cjs +200 -134
  7. package/dist/actions/callback/callback.d.ts +32 -3
  8. package/dist/actions/callback/callback.js +11 -12
  9. package/dist/actions/callback/userinfo.cjs +103 -70
  10. package/dist/actions/callback/userinfo.d.ts +6 -2
  11. package/dist/actions/callback/userinfo.js +7 -8
  12. package/dist/actions/csrfToken/csrfToken.cjs +7 -15
  13. package/dist/actions/csrfToken/csrfToken.d.ts +3 -1
  14. package/dist/actions/csrfToken/csrfToken.js +7 -8
  15. package/dist/actions/index.cjs +502 -295
  16. package/dist/actions/index.d.ts +5 -2
  17. package/dist/actions/index.js +23 -20
  18. package/dist/actions/session/session.cjs +76 -24
  19. package/dist/actions/session/session.d.ts +3 -1
  20. package/dist/actions/session/session.js +6 -4
  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 +91 -132
  25. package/dist/actions/signIn/authorization.d.ts +17 -16
  26. package/dist/actions/signIn/authorization.js +8 -7
  27. package/dist/actions/signIn/signIn.cjs +319 -191
  28. package/dist/actions/signIn/signIn.d.ts +32 -3
  29. package/dist/actions/signIn/signIn.js +10 -9
  30. package/dist/actions/signOut/signOut.cjs +211 -212
  31. package/dist/actions/signOut/signOut.d.ts +9 -1
  32. package/dist/actions/signOut/signOut.js +9 -10
  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 +42 -9
  46. package/dist/assert.d.ts +8 -4
  47. package/dist/assert.js +5 -5
  48. package/dist/{chunk-KJBAQZX2.js → chunk-2A5B7GWR.js} +44 -11
  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-5X7JZMEF.js +0 -0
  54. package/dist/{chunk-TZB6MUXN.js → chunk-7BE46WWS.js} +21 -11
  55. package/dist/chunk-7YYXFKLR.js +35 -0
  56. package/dist/chunk-C3A37LQC.js +33 -0
  57. package/dist/chunk-CITNGXDA.js +31 -0
  58. package/dist/chunk-CWX724AG.js +78 -0
  59. package/dist/chunk-D2CSIUKP.js +74 -0
  60. package/dist/{chunk-ICAZ4OVS.js → chunk-FPCVZUVG.js} +2 -2
  61. package/dist/{chunk-XGLBNXL4.js → chunk-GNNBM2WJ.js} +17 -9
  62. package/dist/chunk-JOCGX3RP.js +59 -0
  63. package/dist/chunk-KBXWTD6E.js +94 -0
  64. package/dist/{chunk-XUP6KKNG.js → chunk-LATR3NIV.js} +48 -37
  65. package/dist/chunk-LAYPUDQF.js +39 -0
  66. package/dist/chunk-LX3TJ2TJ.js +294 -0
  67. package/dist/{chunk-6MXFPFR3.js → chunk-NHZBQNRR.js} +19 -19
  68. package/dist/{chunk-TM5IPSNF.js → chunk-PDP3PHB3.js} +33 -19
  69. package/dist/chunk-PHYNROD4.js +47 -0
  70. package/dist/chunk-QQEKY4XP.js +29 -0
  71. package/dist/{chunk-VNCNJKS2.js → chunk-U4RK4LKJ.js} +82 -1
  72. package/dist/{chunk-RRLIF4PQ.js → chunk-U5663F2U.js} +16 -1
  73. package/dist/chunk-UN7X6SU5.js +53 -0
  74. package/dist/chunk-UZQJJD6A.js +100 -0
  75. package/dist/{chunk-NUDITUKX.js → chunk-V6LLEAR4.js} +22 -15
  76. package/dist/{chunk-4MYWAOLG.js → chunk-WHNDRO3N.js} +20 -1
  77. package/dist/{chunk-5W4BRQYG.js → chunk-XY5R3EHH.js} +6 -3
  78. package/dist/client/client.cjs +135 -0
  79. package/dist/client/client.d.ts +85 -0
  80. package/dist/client/client.js +9 -0
  81. package/dist/client/index.cjs +135 -0
  82. package/dist/client/index.d.ts +14 -0
  83. package/dist/client/index.js +10 -0
  84. package/dist/context.cjs +1237 -0
  85. package/dist/context.d.ts +16 -0
  86. package/dist/context.js +28 -0
  87. package/dist/cookie.cjs +33 -2
  88. package/dist/cookie.d.ts +9 -5
  89. package/dist/cookie.js +3 -2
  90. package/dist/createAuth.cjs +2320 -0
  91. package/dist/createAuth.d.ts +12 -0
  92. package/dist/createAuth.js +48 -0
  93. package/dist/env.cjs +24 -2
  94. package/dist/env.d.ts +4 -1
  95. package/dist/env.js +9 -3
  96. package/dist/errors.cjs +17 -0
  97. package/dist/errors.d.ts +13 -3
  98. package/dist/errors.js +5 -1
  99. package/dist/{index-CSyIJmCM.d.ts → index-_aXtxb_s.d.ts} +383 -13
  100. package/dist/index.cjs +2135 -1547
  101. package/dist/index.d.ts +9 -30
  102. package/dist/index.js +46 -119
  103. package/dist/jose.cjs +52 -14
  104. package/dist/jose.d.ts +12 -25
  105. package/dist/jose.js +11 -3
  106. package/dist/logger.cjs +132 -0
  107. package/dist/logger.d.ts +6 -2
  108. package/dist/logger.js +10 -1
  109. package/dist/oauth/atlassian.cjs +57 -0
  110. package/dist/oauth/atlassian.d.ts +12 -0
  111. package/dist/oauth/atlassian.js +6 -0
  112. package/dist/oauth/bitbucket.d.ts +6 -2
  113. package/dist/oauth/discord.d.ts +6 -2
  114. package/dist/oauth/dropbox.cjs +53 -0
  115. package/dist/oauth/dropbox.d.ts +12 -0
  116. package/dist/oauth/dropbox.js +6 -0
  117. package/dist/oauth/figma.d.ts +6 -2
  118. package/dist/oauth/github.d.ts +6 -2
  119. package/dist/oauth/gitlab.d.ts +6 -2
  120. package/dist/oauth/index.cjs +278 -88
  121. package/dist/oauth/index.d.ts +6 -2
  122. package/dist/oauth/index.js +27 -11
  123. package/dist/oauth/mailchimp.d.ts +6 -2
  124. package/dist/oauth/notion.cjs +131 -0
  125. package/dist/oauth/notion.d.ts +12 -0
  126. package/dist/oauth/notion.js +9 -0
  127. package/dist/oauth/pinterest.d.ts +6 -2
  128. package/dist/oauth/spotify.d.ts +6 -2
  129. package/dist/oauth/strava.d.ts +6 -2
  130. package/dist/oauth/twitch.cjs +95 -0
  131. package/dist/oauth/twitch.d.ts +12 -0
  132. package/dist/oauth/twitch.js +7 -0
  133. package/dist/oauth/x.d.ts +6 -2
  134. package/dist/schemas.cjs +84 -51
  135. package/dist/schemas.d.ts +103 -23
  136. package/dist/schemas.js +1 -1
  137. package/dist/secure.cjs +36 -36
  138. package/dist/secure.d.ts +10 -4
  139. package/dist/secure.js +7 -6
  140. package/dist/utils.cjs +109 -3
  141. package/dist/utils.d.ts +15 -4
  142. package/dist/utils.js +11 -4
  143. package/package.json +9 -5
  144. package/dist/chunk-4EKY7655.js +0 -123
  145. package/dist/chunk-7QF22LHP.js +0 -67
  146. package/dist/chunk-ALG3GIV4.js +0 -95
  147. package/dist/chunk-FRJFWTOY.js +0 -70
  148. package/dist/chunk-PHFH2MGS.js +0 -36
  149. package/dist/chunk-QQVSRXGX.js +0 -149
@@ -1,57 +1,56 @@
1
1
  import {
2
- OAuthAuthorization
3
- } from "./chunk-KJBAQZX2.js";
4
- import {
2
+ equals,
3
+ extractPath,
5
4
  isRelativeURL,
6
5
  isSameOrigin,
7
6
  isTrustedOrigin,
8
7
  isValidURL,
9
8
  patternToRegex
10
- } from "./chunk-4EKY7655.js";
9
+ } from "./chunk-LX3TJ2TJ.js";
11
10
  import {
12
- equals,
13
- extractPath,
14
- toCastCase
15
- } from "./chunk-QQVSRXGX.js";
11
+ getEnv
12
+ } from "./chunk-WHNDRO3N.js";
16
13
  import {
17
14
  AuthInternalError
18
- } from "./chunk-RRLIF4PQ.js";
15
+ } from "./chunk-U5663F2U.js";
19
16
 
20
17
  // src/actions/signIn/authorization.ts
21
- var createAuthorizationURL = (oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod, logger) => {
22
- const parsed = OAuthAuthorization.safeParse({ ...oauthConfig, redirectURI, state, codeChallenge, codeChallengeMethod });
23
- if (!parsed.success) {
24
- logger?.log("INVALID_OAUTH_CONFIGURATION", {
25
- structuredData: {
26
- scope: oauthConfig.scope,
27
- redirect_uri: redirectURI,
28
- has_state: Boolean(state),
29
- has_code_challenge: Boolean(codeChallenge),
30
- code_challenge_method: codeChallengeMethod
31
- }
32
- });
33
- throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "The OAuth provider configuration is invalid.");
34
- }
35
- const { authorizeURL, ...options } = parsed.data;
36
- const { userInfo, accessToken, clientSecret, ...required } = options;
37
- const searchParams = new URLSearchParams(toCastCase(required));
38
- return `${authorizeURL}?${searchParams}`;
39
- };
40
18
  var getTrustedOrigins = async (request, trustedOrigins) => {
41
19
  if (!trustedOrigins) return [];
42
20
  const raw = typeof trustedOrigins === "function" ? await trustedOrigins(request) : trustedOrigins;
43
21
  return Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : [];
44
22
  };
23
+ var getBaseURL = async ({
24
+ ctx,
25
+ request,
26
+ headers: headersInit
27
+ }) => {
28
+ const origin = getEnv("BASE_URL") || ctx?.baseURL;
29
+ if (origin && origin !== "/") return origin;
30
+ if (ctx?.trustedProxyHeaders) {
31
+ const headers = headersInit && new Headers(headersInit) || request?.headers;
32
+ const protocol = headers?.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers?.get("X-Forwarded-Proto") ?? "http";
33
+ const host = headers?.get("Host") ?? headers?.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers?.get("X-Forwarded-Host") ?? null;
34
+ if (host) return `${protocol}://${host}`;
35
+ throw new AuthInternalError(
36
+ "INVALID_OAUTH_CONFIGURATION",
37
+ "The URL cannot be constructed. Please set the BASE_URL environment variable or provide trusted proxy host headers."
38
+ );
39
+ }
40
+ try {
41
+ return new URL(request?.url ?? "not-found").origin;
42
+ } catch (error) {
43
+ throw new AuthInternalError(
44
+ "INVALID_OAUTH_CONFIGURATION",
45
+ "The URL cannot be constructed. Please set the BASE_URL environment variable or enable trustedProxyHeaders.",
46
+ { cause: error }
47
+ );
48
+ }
49
+ };
45
50
  var getOriginURL = async (request, context) => {
46
- const headers = request.headers;
47
- let origin = new URL(request.url).origin;
48
51
  const trustedOrigins = await getTrustedOrigins(request, context?.trustedOrigins);
49
- trustedOrigins.push(origin);
50
- if (context?.trustedProxyHeaders) {
51
- const protocol = headers.get("Forwarded")?.match(/proto=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Proto") ?? "http";
52
- const host = headers.get("Host") ?? headers.get("Forwarded")?.match(/host=([^;]+)/i)?.[1] ?? headers.get("X-Forwarded-Host") ?? null;
53
- origin = `${protocol}://${host}`;
54
- }
52
+ trustedOrigins.push(new URL(request.url).origin);
53
+ const origin = await getBaseURL({ request, ctx: context });
55
54
  if (!isTrustedOrigin(origin, trustedOrigins)) {
56
55
  context?.logger?.log("UNTRUSTED_ORIGIN", { structuredData: { origin } });
57
56
  throw new AuthInternalError("UNTRUSTED_ORIGIN", "The constructed origin URL is not trusted.");
@@ -62,6 +61,17 @@ var createRedirectURI = async (request, oauth, context) => {
62
61
  const origin = await getOriginURL(request, context);
63
62
  return `${origin}${context.basePath}/callback/${oauth}`;
64
63
  };
64
+ var createSignInURL = async ({
65
+ request,
66
+ oauth,
67
+ ctx,
68
+ redirectTo
69
+ }) => {
70
+ const origin = await getOriginURL(request, ctx);
71
+ const searchParams = new URLSearchParams();
72
+ if (redirectTo !== void 0) searchParams.set("redirectTo", String(redirectTo));
73
+ return `${origin}${ctx.basePath}/signIn/${oauth}?${searchParams.toString()}`;
74
+ };
65
75
  var createRedirectTo = async (request, redirectTo, context) => {
66
76
  try {
67
77
  const headers = request.headers;
@@ -98,9 +108,10 @@ var createRedirectTo = async (request, redirectTo, context) => {
98
108
  };
99
109
 
100
110
  export {
101
- createAuthorizationURL,
102
111
  getTrustedOrigins,
112
+ getBaseURL,
103
113
  getOriginURL,
104
114
  createRedirectURI,
115
+ createSignInURL,
105
116
  createRedirectTo
106
117
  };
@@ -0,0 +1,39 @@
1
+ import {
2
+ getSession
3
+ } from "./chunk-CITNGXDA.js";
4
+ import {
5
+ signIn
6
+ } from "./chunk-JOCGX3RP.js";
7
+ import {
8
+ signOut
9
+ } from "./chunk-KBXWTD6E.js";
10
+ import {
11
+ validateRedirectTo
12
+ } from "./chunk-LX3TJ2TJ.js";
13
+
14
+ // src/api/createApi.ts
15
+ var createAuthAPI = (ctx) => {
16
+ return {
17
+ getSession: async (options) => {
18
+ const session = await getSession({ ctx, headers: options.headers });
19
+ return session;
20
+ },
21
+ signIn: async (oauth, options) => {
22
+ return signIn(oauth, {
23
+ ctx,
24
+ headers: options?.headers,
25
+ request: options?.request,
26
+ redirect: options?.redirect,
27
+ redirectTo: options?.redirectTo
28
+ });
29
+ },
30
+ signOut: async (options) => {
31
+ const redirectTo = validateRedirectTo(options?.redirectTo ?? "/");
32
+ return signOut({ ctx, headers: options.headers, redirectTo, skipCSRFCheck: true });
33
+ }
34
+ };
35
+ };
36
+
37
+ export {
38
+ createAuthAPI
39
+ };
@@ -0,0 +1,294 @@
1
+ import {
2
+ getEnv
3
+ } from "./chunk-WHNDRO3N.js";
4
+ import {
5
+ AuthInternalError,
6
+ isAuthInternalError,
7
+ isAuthSecurityError,
8
+ isOAuthProtocolError
9
+ } from "./chunk-U5663F2U.js";
10
+
11
+ // src/utils.ts
12
+ import { isInvalidZodSchemaError, isRouterError } from "@aura-stack/router";
13
+
14
+ // src/assert.ts
15
+ import { encoder } from "@aura-stack/jose/crypto";
16
+ var isFalsy = (value) => {
17
+ return value === false || value === 0 || value === "" || value === null || value === void 0 || Number.isNaN(value);
18
+ };
19
+ var isRequest = (value) => {
20
+ return typeof Request !== "undefined" && value instanceof Request;
21
+ };
22
+ var unsafeChars = [
23
+ "<",
24
+ ">",
25
+ '"',
26
+ "`",
27
+ " ",
28
+ "\r",
29
+ "\n",
30
+ " ",
31
+ "\\",
32
+ "%2F",
33
+ "%5C",
34
+ "%2f",
35
+ "%5c",
36
+ "\r\n",
37
+ "%0A",
38
+ "%0D",
39
+ "%0a",
40
+ "%0d",
41
+ "..",
42
+ "//",
43
+ "///",
44
+ "...",
45
+ "%20",
46
+ "\0"
47
+ ];
48
+ var isValidURL = (value) => {
49
+ if (!new RegExp(/^https?:\/\/[^/]/).test(value)) {
50
+ return false;
51
+ }
52
+ const match = value.match(/^(https?:\/\/)(.*)$/);
53
+ if (!match) return false;
54
+ const rest = match[2];
55
+ for (const char of unsafeChars) {
56
+ if (rest.includes(char)) return false;
57
+ }
58
+ const regex = /^https?:\/\/(?:[a-zA-Z0-9._-]+|localhost|\[[0-9a-fA-F:]+\])(?::\d{1,5})?(?:\/[a-zA-Z0-9._~!$&'()?#*+,;=:@-]*)*\/?$/;
59
+ return regex.test(match[0]);
60
+ };
61
+ var isJWTPayloadWithToken = (payload) => {
62
+ return typeof payload === "object" && payload !== null && "token" in payload && typeof payload?.token === "string";
63
+ };
64
+ var isRelativeURL = (value) => {
65
+ if (value.length > 100) return false;
66
+ for (const char of unsafeChars) {
67
+ if (value.includes(char)) return false;
68
+ }
69
+ const regex = /^\/[a-zA-Z0-9\-_\/.?&=#]*\/?$/;
70
+ return regex.test(value);
71
+ };
72
+ var isSameOrigin = (origin, expected) => {
73
+ const originURL = new URL(origin);
74
+ const expectedURL = new URL(expected);
75
+ return equals(originURL.origin, expectedURL.origin);
76
+ };
77
+ var patternToRegex = (pattern) => {
78
+ try {
79
+ if (pattern.length > 2048) return null;
80
+ pattern = pattern.replace(/\\/g, "");
81
+ const match = pattern.match(/^(https?):\/\/([a-zA-Z0-9.*-]{1,253})(?::(\d{1,5}|\*))?(?:\/.*)?$/);
82
+ if (!match) return null;
83
+ const [, protocol, host, port] = match;
84
+ const hasWildcard = host.includes("*");
85
+ if (hasWildcard && !host.startsWith("*.")) return null;
86
+ if (hasWildcard && host.slice(2).includes("*")) return null;
87
+ const domain = hasWildcard ? host.slice(2) : host;
88
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
89
+ const hostRegex = hasWildcard ? `[^.]+\\.${escapedDomain}` : escapedDomain;
90
+ const portRegex = port === "*" ? ":\\d{1,5}" : port ? `:${port}` : "";
91
+ return new RegExp(`^${protocol}:\\/\\/${hostRegex}${portRegex}$`);
92
+ } catch {
93
+ return null;
94
+ }
95
+ };
96
+ var isTrustedOrigin = (url, trustedOrigins) => {
97
+ if (!isValidURL(url) || trustedOrigins.length === 0) return false;
98
+ try {
99
+ const urlOrigin = new URL(url).origin;
100
+ for (const pattern of trustedOrigins) {
101
+ const regex = patternToRegex(pattern);
102
+ if (regex?.test(urlOrigin)) return true;
103
+ try {
104
+ if (isValidURL(pattern) && equals(new URL(pattern).origin, urlOrigin)) return true;
105
+ } catch {
106
+ }
107
+ }
108
+ } catch {
109
+ }
110
+ return false;
111
+ };
112
+ var timingSafeEqual = (a, b) => {
113
+ const bufferA = encoder.encode(a);
114
+ const bufferB = encoder.encode(b);
115
+ const len = Math.max(bufferA.length, bufferB.length);
116
+ let diff = 0;
117
+ for (let i = 0; i < len; i++) {
118
+ diff |= (bufferA[i] ?? 0) ^ (bufferB[i] ?? 0);
119
+ }
120
+ return diff === 0 && bufferA.length === bufferB.length;
121
+ };
122
+
123
+ // src/utils.ts
124
+ var AURA_AUTH_VERSION = "0.4.0";
125
+ var toSnakeCase = (str) => {
126
+ return str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase().replace(/^_+/, "");
127
+ };
128
+ var toUpperCase = (str) => {
129
+ return str.toUpperCase();
130
+ };
131
+ var toCastCase = (obj, type = "snake") => {
132
+ return Object.entries(obj).reduce((previous, [key, value]) => {
133
+ const newKey = type === "snake" ? toSnakeCase(key) : toUpperCase(key);
134
+ return { ...previous, [newKey]: value };
135
+ }, {});
136
+ };
137
+ var equals = (a, b) => {
138
+ if (a === null || b === null || a === void 0 || b === void 0) return false;
139
+ return a === b;
140
+ };
141
+ var createErrorHandler = (logger) => {
142
+ return (error) => {
143
+ if (isRouterError(error)) {
144
+ const { message, status, statusText } = error;
145
+ logger?.log("ROUTER_INTERNAL_ERROR");
146
+ return Response.json({ type: "ROUTER_ERROR", code: "ROUTER_INTERNAL_ERROR", message }, { status, statusText });
147
+ }
148
+ if (isInvalidZodSchemaError(error)) {
149
+ logger?.log("INVALID_REQUEST");
150
+ return Response.json({ type: "ROUTER_ERROR", code: "INVALID_REQUEST", message: error.errors }, { status: 422 });
151
+ }
152
+ if (isOAuthProtocolError(error)) {
153
+ const { error: errorCode, message, type, errorURI } = error;
154
+ logger?.log("OAUTH_PROTOCOL_ERROR", {
155
+ structuredData: {
156
+ error: errorCode,
157
+ error_description: message,
158
+ error_uri: errorURI ?? ""
159
+ }
160
+ });
161
+ return Response.json(
162
+ {
163
+ type,
164
+ message
165
+ },
166
+ { status: 400 }
167
+ );
168
+ }
169
+ if (isAuthInternalError(error)) {
170
+ const { type, code, message } = error;
171
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
172
+ structuredData: {
173
+ error: code,
174
+ error_description: message
175
+ }
176
+ });
177
+ return Response.json(
178
+ {
179
+ type,
180
+ message
181
+ },
182
+ { status: 400 }
183
+ );
184
+ }
185
+ if (isAuthSecurityError(error)) {
186
+ const { type, code, message } = error;
187
+ logger?.log("INVALID_OAUTH_CONFIGURATION", {
188
+ structuredData: {
189
+ error: code,
190
+ error_description: message
191
+ }
192
+ });
193
+ return Response.json(
194
+ {
195
+ type,
196
+ code,
197
+ message
198
+ },
199
+ { status: 400 }
200
+ );
201
+ }
202
+ logger?.log("SERVER_ERROR");
203
+ return Response.json(
204
+ { type: "SERVER_ERROR", code: "SERVER_ERROR", message: "An unexpected error occurred" },
205
+ { status: 500 }
206
+ );
207
+ };
208
+ };
209
+ var getBaseURL = (request) => {
210
+ const url = new URL(request.url);
211
+ return `${url.origin}${url.pathname}`;
212
+ };
213
+ var toISOString = (date) => {
214
+ return new Date(date).toISOString();
215
+ };
216
+ var useSecureCookies = (request, trustedProxyHeaders) => {
217
+ const headers = request instanceof Headers ? request : request.headers;
218
+ const url = request instanceof Headers ? null : request.url;
219
+ return trustedProxyHeaders ? url?.startsWith("https://") || headers.get("X-Forwarded-Proto") === "https" || (headers.get("Forwarded")?.includes("proto=https") ?? false) : url?.startsWith("https://") ?? false;
220
+ };
221
+ var formatZodError = (error) => {
222
+ if (!error.issues || error.issues.length === 0) {
223
+ return {};
224
+ }
225
+ return error.issues.reduce((previous, issue) => {
226
+ const key = issue.path.join(".");
227
+ return {
228
+ ...previous,
229
+ [key]: {
230
+ code: issue.code,
231
+ message: issue.message
232
+ }
233
+ };
234
+ }, {});
235
+ };
236
+ var extractPath = (url) => {
237
+ const pathRegex = /^https?:\/\/[a-zA-Z0-9_\-\.]+(:\d+)?(\/.*)$/;
238
+ const match = url.match(pathRegex);
239
+ return match && match[2] ? match[2] : "/";
240
+ };
241
+ var createStructuredData = (data, sdID = "metadata") => {
242
+ const entries = Object.entries(data);
243
+ if (entries.length === 0) return `[${sdID}]`;
244
+ const values = entries.map(([key, value]) => `${key}="${String(value).replace(/(["\\\]])/g, "\\$1")}"`).join(" ");
245
+ return `[${sdID} ${values}]`;
246
+ };
247
+ var getErrorName = (error) => {
248
+ if (error instanceof Error) {
249
+ return error.name;
250
+ }
251
+ return typeof error === "string" ? error : "UnknownError";
252
+ };
253
+ var createBasicAuthHeader = (username, password) => {
254
+ const getUsername = getEnv(username.toUpperCase()) ?? username;
255
+ const getPassword = getEnv(password.toUpperCase()) ?? password;
256
+ if (!getUsername || !getPassword) {
257
+ throw new AuthInternalError("INVALID_OAUTH_CONFIGURATION", "Missing client credentials for OAuth provider configuration.");
258
+ }
259
+ const credentials = `${getUsername}:${getPassword}`;
260
+ return `Basic ${btoa(credentials)}`;
261
+ };
262
+ var validateRedirectTo = (url) => {
263
+ if (!isRelativeURL(url) && !isValidURL(url)) return "/";
264
+ if (isRelativeURL(url)) return url;
265
+ return "/";
266
+ };
267
+
268
+ export {
269
+ AURA_AUTH_VERSION,
270
+ toSnakeCase,
271
+ toUpperCase,
272
+ toCastCase,
273
+ equals,
274
+ createErrorHandler,
275
+ getBaseURL,
276
+ toISOString,
277
+ useSecureCookies,
278
+ formatZodError,
279
+ extractPath,
280
+ createStructuredData,
281
+ getErrorName,
282
+ createBasicAuthHeader,
283
+ validateRedirectTo,
284
+ isFalsy,
285
+ isRequest,
286
+ unsafeChars,
287
+ isValidURL,
288
+ isJWTPayloadWithToken,
289
+ isRelativeURL,
290
+ isSameOrigin,
291
+ patternToRegex,
292
+ isTrustedOrigin,
293
+ timingSafeEqual
294
+ };
@@ -1,40 +1,40 @@
1
- import {
2
- createAccessToken
3
- } from "./chunk-TZB6MUXN.js";
4
1
  import {
5
2
  getUserInfo
6
- } from "./chunk-XGLBNXL4.js";
3
+ } from "./chunk-GNNBM2WJ.js";
4
+ import {
5
+ createAccessToken
6
+ } from "./chunk-7BE46WWS.js";
7
7
  import {
8
8
  getOriginURL,
9
9
  getTrustedOrigins
10
- } from "./chunk-XUP6KKNG.js";
11
- import {
12
- OAuthAuthorizationErrorResponse
13
- } from "./chunk-KJBAQZX2.js";
10
+ } from "./chunk-LATR3NIV.js";
14
11
  import {
15
12
  createCSRF
16
- } from "./chunk-NUDITUKX.js";
13
+ } from "./chunk-V6LLEAR4.js";
14
+ import {
15
+ OAuthAuthorizationErrorResponse
16
+ } from "./chunk-2A5B7GWR.js";
17
17
  import {
18
18
  isRelativeURL,
19
19
  isSameOrigin,
20
20
  isTrustedOrigin,
21
- safeEquals
22
- } from "./chunk-4EKY7655.js";
21
+ timingSafeEqual
22
+ } from "./chunk-LX3TJ2TJ.js";
23
23
  import {
24
24
  createSessionCookie,
25
25
  expiredCookieAttributes,
26
26
  getCookie
27
- } from "./chunk-5W4BRQYG.js";
28
- import {
29
- cacheControl
30
- } from "./chunk-EBAMFRB7.js";
27
+ } from "./chunk-XY5R3EHH.js";
31
28
  import {
32
29
  AuthSecurityError,
33
30
  OAuthProtocolError
34
- } from "./chunk-RRLIF4PQ.js";
31
+ } from "./chunk-U5663F2U.js";
32
+ import {
33
+ cacheControl
34
+ } from "./chunk-EBAMFRB7.js";
35
35
 
36
36
  // src/actions/callback/callback.ts
37
- import { z } from "zod";
37
+ import { z } from "zod/v4";
38
38
  import { createEndpoint, createEndpointConfig, HeadersBuilder } from "@aura-stack/router";
39
39
  var callbackConfig = (oauth) => {
40
40
  return createEndpointConfig("/callback/:oauth", {
@@ -50,7 +50,7 @@ var callbackConfig = (oauth) => {
50
50
  state: z.string("Missing state parameter in the OAuth authorization response.")
51
51
  })
52
52
  },
53
- middlewares: [
53
+ use: [
54
54
  (ctx) => {
55
55
  const {
56
56
  searchParams,
@@ -92,7 +92,7 @@ var callbackAction = (oauth) => {
92
92
  const codeVerifier = getCookie(request, cookies.codeVerifier.name);
93
93
  const cookieRedirectTo = getCookie(request, cookies.redirectTo.name);
94
94
  const cookieRedirectURI = getCookie(request, cookies.redirectURI.name);
95
- if (!safeEquals(cookieState, state)) {
95
+ if (!timingSafeEqual(cookieState, state)) {
96
96
  logger?.log("MISMATCHING_STATE", {
97
97
  structuredData: {
98
98
  oauth_provider: oauth2
@@ -1,18 +1,36 @@
1
+ import {
2
+ mailchimp
3
+ } from "./chunk-LDU7A2JE.js";
4
+ import {
5
+ notion
6
+ } from "./chunk-PHYNROD4.js";
7
+ import {
8
+ pinterest
9
+ } from "./chunk-E6G5YCI6.js";
1
10
  import {
2
11
  spotify
3
12
  } from "./chunk-IPKO6UQN.js";
4
13
  import {
5
14
  strava
6
15
  } from "./chunk-54CZPKR4.js";
16
+ import {
17
+ twitch
18
+ } from "./chunk-2GQLSIJ2.js";
7
19
  import {
8
20
  x
9
21
  } from "./chunk-EEE7UM5T.js";
22
+ import {
23
+ atlassian
24
+ } from "./chunk-C3A37LQC.js";
10
25
  import {
11
26
  bitbucket
12
27
  } from "./chunk-4YHJ4IEQ.js";
13
28
  import {
14
29
  discord
15
30
  } from "./chunk-OVHNRULD.js";
31
+ import {
32
+ dropbox
33
+ } from "./chunk-QQEKY4XP.js";
16
34
  import {
17
35
  figma
18
36
  } from "./chunk-KMMAZFSJ.js";
@@ -22,25 +40,19 @@ import {
22
40
  import {
23
41
  gitlab
24
42
  } from "./chunk-5LZ7TOM3.js";
25
- import {
26
- mailchimp
27
- } from "./chunk-LDU7A2JE.js";
28
- import {
29
- pinterest
30
- } from "./chunk-E6G5YCI6.js";
31
43
  import {
32
44
  OAuthEnvSchema,
33
45
  OAuthProviderCredentialsSchema
34
- } from "./chunk-KJBAQZX2.js";
46
+ } from "./chunk-2A5B7GWR.js";
35
47
  import {
36
48
  formatZodError
37
- } from "./chunk-QQVSRXGX.js";
49
+ } from "./chunk-LX3TJ2TJ.js";
38
50
  import {
39
- env
40
- } from "./chunk-4MYWAOLG.js";
51
+ getEnv
52
+ } from "./chunk-WHNDRO3N.js";
41
53
  import {
42
54
  AuthInternalError
43
- } from "./chunk-RRLIF4PQ.js";
55
+ } from "./chunk-U5663F2U.js";
44
56
 
45
57
  // src/oauth/index.ts
46
58
  var builtInOAuthProviders = {
@@ -53,17 +65,19 @@ var builtInOAuthProviders = {
53
65
  x,
54
66
  strava,
55
67
  mailchimp,
56
- pinterest
68
+ pinterest,
69
+ twitch,
70
+ notion,
71
+ dropbox,
72
+ atlassian
57
73
  };
58
74
  var defineOAuthEnvironment = (oauth) => {
59
- const clientIdSuffix = `${oauth.toUpperCase()}_CLIENT_ID`;
60
- const clientSecretSuffix = `${oauth.toUpperCase()}_CLIENT_SECRET`;
61
75
  const loadEnvs = OAuthEnvSchema.safeParse({
62
- clientId: env[`AURA_AUTH_${clientIdSuffix}`] ?? env[`AUTH_${clientIdSuffix}`] ?? env[`${clientIdSuffix}`],
63
- clientSecret: env[`AURA_AUTH_${clientSecretSuffix}`] ?? env[`AUTH_${clientSecretSuffix}`] ?? env[`${clientSecretSuffix}`]
76
+ clientId: getEnv(`${oauth.toUpperCase()}_CLIENT_ID`),
77
+ clientSecret: getEnv(`${oauth.toUpperCase()}_CLIENT_SECRET`)
64
78
  });
65
79
  if (!loadEnvs.success) {
66
- const msg = JSON.stringify(formatZodError(loadEnvs.error), null, 2);
80
+ const msg = JSON.stringify({ [oauth]: formatZodError(loadEnvs.error) }, null, 2);
67
81
  throw new AuthInternalError("INVALID_ENVIRONMENT_CONFIGURATION", msg);
68
82
  }
69
83
  return loadEnvs.data;
@@ -74,7 +88,7 @@ var defineOAuthProviderConfig = (config) => {
74
88
  const oauthConfig = builtInOAuthProviders[config]();
75
89
  const parsed2 = OAuthProviderCredentialsSchema.safeParse({ ...oauthConfig, ...definition });
76
90
  if (!parsed2.success) {
77
- const details = JSON.stringify(formatZodError(parsed2.error), null, 2);
91
+ const details = JSON.stringify({ [config]: formatZodError(parsed2.error) }, null, 2);
78
92
  throw new AuthInternalError(
79
93
  "INVALID_OAUTH_PROVIDER_CONFIGURATION",
80
94
  `Invalid configuration for OAuth provider "${config}": ${details}`
@@ -86,7 +100,7 @@ var defineOAuthProviderConfig = (config) => {
86
100
  const envConfig = hasCredentials ? {} : defineOAuthEnvironment(config.id);
87
101
  const parsed = OAuthProviderCredentialsSchema.safeParse({ ...envConfig, ...config });
88
102
  if (!parsed.success) {
89
- const details = JSON.stringify(formatZodError(parsed.error), null, 2);
103
+ const details = JSON.stringify({ [config.id]: formatZodError(parsed.error) }, null, 2);
90
104
  throw new AuthInternalError(
91
105
  "INVALID_OAUTH_PROVIDER_CONFIGURATION",
92
106
  `Invalid configuration for OAuth provider "${config.id}": ${details}`
@@ -0,0 +1,47 @@
1
+ import {
2
+ createBasicAuthHeader
3
+ } from "./chunk-LX3TJ2TJ.js";
4
+
5
+ // src/oauth/notion.ts
6
+ var notion = (options) => {
7
+ return {
8
+ id: "notion",
9
+ name: "Notion",
10
+ authorize: {
11
+ url: "https://api.notion.com/v1/oauth/authorize",
12
+ params: {
13
+ owner: "user",
14
+ scope: "user:read",
15
+ responseType: "code"
16
+ }
17
+ },
18
+ accessToken: {
19
+ url: "https://api.notion.com/v1/oauth/token",
20
+ headers: {
21
+ Authorization: createBasicAuthHeader(
22
+ options?.clientId ?? "NOTION_CLIENT_ID",
23
+ options?.clientSecret ?? "NOTION_CLIENT_SECRET"
24
+ )
25
+ }
26
+ },
27
+ userInfo: {
28
+ url: "https://api.notion.com/v1/users/me",
29
+ headers: {
30
+ "Notion-Version": "2022-06-28"
31
+ }
32
+ },
33
+ profile(profile) {
34
+ return {
35
+ sub: profile.id,
36
+ name: profile.name,
37
+ image: profile.avatar_url ?? "",
38
+ email: profile?.bot?.owner?.user?.person?.email
39
+ };
40
+ },
41
+ ...options
42
+ };
43
+ };
44
+
45
+ export {
46
+ notion
47
+ };