Skip to content

Commit 43638e5

Browse files
committed
only validate Turnstile captcha on Vercel environments (#6314)
1 parent cc5cdd4 commit 43638e5

File tree

2 files changed

+73
-66
lines changed

2 files changed

+73
-66
lines changed

apps/dashboard/src/app/login/auth-actions.ts

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
LoginPayload,
1212
VerifyLoginPayloadParams,
1313
} from "thirdweb/auth";
14+
import { isVercel } from "../../lib/vercel-utils";
1415

1516
export async function getLoginPayload(
1617
params: GenerateLoginPayloadParams,
@@ -45,80 +46,83 @@ export async function doLogin(
4546
throw new Error("API_SERVER_SECRET is not set");
4647
}
4748

48-
if (!turnstileToken) {
49-
return {
50-
error: "Missing Turnstile token.",
51-
};
52-
}
49+
// only validate the turnstile token if we are in a vercel environment
50+
if (isVercel()) {
51+
if (!turnstileToken) {
52+
return {
53+
error: "Missing Turnstile token.",
54+
};
55+
}
5356

54-
// get the request headers
55-
const requestHeaders = await headers();
56-
if (!requestHeaders) {
57-
return {
58-
error: "Failed to get request headers. Please try again.",
59-
};
60-
}
61-
// CF header, fallback to req.ip, then X-Forwarded-For
62-
const [ip, errors] = (() => {
63-
let ip: string | null = null;
64-
const errors: string[] = [];
65-
try {
66-
ip = requestHeaders.get("CF-Connecting-IP") || null;
67-
} catch (err) {
68-
console.error("failed to get IP address from CF-Connecting-IP", err);
69-
errors.push("failed to get IP address from CF-Connecting-IP");
57+
// get the request headers
58+
const requestHeaders = await headers();
59+
if (!requestHeaders) {
60+
return {
61+
error: "Failed to get request headers. Please try again.",
62+
};
7063
}
71-
if (!ip) {
64+
// CF header, fallback to req.ip, then X-Forwarded-For
65+
const [ip, errors] = (() => {
66+
let ip: string | null = null;
67+
const errors: string[] = [];
7268
try {
73-
ip = ipAddress(requestHeaders) || null;
69+
ip = requestHeaders.get("CF-Connecting-IP") || null;
7470
} catch (err) {
75-
console.error(
76-
"failed to get IP address from ipAddress() function",
77-
err,
78-
);
79-
errors.push("failed to get IP address from ipAddress() function");
71+
console.error("failed to get IP address from CF-Connecting-IP", err);
72+
errors.push("failed to get IP address from CF-Connecting-IP");
8073
}
81-
}
82-
if (!ip) {
83-
try {
84-
ip = requestHeaders.get("X-Forwarded-For");
85-
} catch (err) {
86-
console.error("failed to get IP address from X-Forwarded-For", err);
87-
errors.push("failed to get IP address from X-Forwarded-For");
74+
if (!ip) {
75+
try {
76+
ip = ipAddress(requestHeaders) || null;
77+
} catch (err) {
78+
console.error(
79+
"failed to get IP address from ipAddress() function",
80+
err,
81+
);
82+
errors.push("failed to get IP address from ipAddress() function");
83+
}
8884
}
89-
}
90-
return [ip, errors];
91-
})();
85+
if (!ip) {
86+
try {
87+
ip = requestHeaders.get("X-Forwarded-For");
88+
} catch (err) {
89+
console.error("failed to get IP address from X-Forwarded-For", err);
90+
errors.push("failed to get IP address from X-Forwarded-For");
91+
}
92+
}
93+
return [ip, errors];
94+
})();
9295

93-
if (!ip) {
94-
return {
95-
error: "Could not get IP address. Please try again.",
96-
context: errors,
97-
};
98-
}
96+
if (!ip) {
97+
return {
98+
error: "Could not get IP address. Please try again.",
99+
context: errors,
100+
};
101+
}
99102

100-
// https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
101-
// Validate the token by calling the "/siteverify" API endpoint.
102-
const result = await fetch(
103-
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
104-
{
105-
body: JSON.stringify({
106-
secret: process.env.TURNSTILE_SECRET_KEY,
107-
response: turnstileToken,
108-
remoteip: ip,
109-
}),
110-
method: "POST",
111-
headers: {
112-
"Content-Type": "application/json",
103+
// https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
104+
// Validate the token by calling the "/siteverify" API endpoint.
105+
const result = await fetch(
106+
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
107+
{
108+
body: JSON.stringify({
109+
secret: process.env.TURNSTILE_SECRET_KEY,
110+
response: turnstileToken,
111+
remoteip: ip,
112+
}),
113+
method: "POST",
114+
headers: {
115+
"Content-Type": "application/json",
116+
},
113117
},
114-
},
115-
);
118+
);
116119

117-
const outcome = await result.json();
118-
if (!outcome.success) {
119-
return {
120-
error: "Could not validate captcha.",
121-
};
120+
const outcome = await result.json();
121+
if (!outcome.success) {
122+
return {
123+
error: "Could not validate captcha.",
124+
};
125+
}
122126
}
123127

124128
const cookieStore = await cookies();

apps/dashboard/src/lib/vercel-utils.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { isBrowser } from "utils/isBrowser";
22

3+
export function isVercel() {
4+
return !!(process.env.vercel || process.env.NEXT_PUBLIC_VERCEL_ENV);
5+
}
6+
37
export function getVercelEnv() {
4-
const onVercel = process.env.vercel || process.env.NEXT_PUBLIC_VERCEL_ENV;
5-
if (!onVercel) {
8+
if (!isVercel()) {
69
return "development";
710
}
811
return (process.env.VERCEL_ENV ||

0 commit comments

Comments
 (0)