mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-08 04:57:36 +00:00
refactor(turnstile-spin): tighten auth handling, expand documentation, and add tldraw-offline matcher
This commit is contained in:
1 parent
20dc5f4489
commit
03ef5c94ea
14 files changed
+1559
-499
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Next.js (Pages Router)
|
||||
|
||||
For older Next.js projects using `pages/` rather than `app/`. The form posts directly to the Worker; no React state required.
|
||||
For older Next.js projects using `pages/` rather than `app/`. The widget renders client-side; siteverify lives in the API route.
|
||||
|
||||
```tsx title="pages/signup.tsx"
|
||||
import Script from "next/script";
|
||||
@@ -9,12 +9,12 @@ export default function SignupPage() {
|
||||
return (
|
||||
<>
|
||||
<Script src="https://challenges.cloudflare.com/turnstile/v0/api.js" />
|
||||
<form action="https://YOUR_WORKER_URL/" method="POST">
|
||||
<form action="/api/signup" method="POST">
|
||||
<input name="email" type="email" required />
|
||||
<div
|
||||
className="cf-turnstile"
|
||||
data-sitekey="YOUR_SITEKEY"
|
||||
data-action="turnstile-spin-v1"
|
||||
data-action="signup"
|
||||
/>
|
||||
<button type="submit">Sign up</button>
|
||||
</form>
|
||||
@@ -23,25 +23,48 @@ export default function SignupPage() {
|
||||
}
|
||||
```
|
||||
|
||||
## Variant: API route on your own backend
|
||||
This native form navigates to the API response, so it does not need client-side reset code.
|
||||
|
||||
If you want to call siteverify from your own API route (e.g. you have application logic between siteverify and the actual signup), proxy the call through `pages/api/signup.ts`:
|
||||
API route (canonical siteverify):
|
||||
|
||||
```ts title="pages/api/signup.ts"
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
const expectedHostnames = new Set(
|
||||
(process.env.TURNSTILE_HOSTNAMES ?? "")
|
||||
.split(",")
|
||||
.map((h) => h.trim())
|
||||
.filter(Boolean),
|
||||
);
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse,
|
||||
) {
|
||||
const token = req.body["cf-turnstile-response"] ?? req.body.token;
|
||||
const verify = await fetch("https://YOUR_WORKER_URL/", {
|
||||
if (expectedHostnames.size === 0) {
|
||||
return res.status(403).json({ error: "Verification failed" });
|
||||
}
|
||||
const remoteip =
|
||||
(req.headers["x-forwarded-for"] as string | undefined)?.split(",")[0] ??
|
||||
req.socket.remoteAddress;
|
||||
|
||||
const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ token }),
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: new URLSearchParams({
|
||||
secret: process.env.TURNSTILE_SECRET!,
|
||||
response: token,
|
||||
...(remoteip ? { remoteip } : {}),
|
||||
}),
|
||||
});
|
||||
const data = await verify.json();
|
||||
if (!data.success) {
|
||||
const result = await verify.json();
|
||||
if (
|
||||
verify.ok !== true ||
|
||||
result.success !== true ||
|
||||
result.action !== "signup" ||
|
||||
!expectedHostnames.has(result.hostname)
|
||||
) {
|
||||
return res.status(403).json({ error: "Verification failed" });
|
||||
}
|
||||
// process signup
|
||||
@@ -49,11 +72,11 @@ export default async function handler(
|
||||
}
|
||||
```
|
||||
|
||||
Note: This pattern uses the Spin Worker as a siteverify proxy from your Node backend. It still works, just adds a hop. For pure SPA-style forms, the direct-post pattern above is simpler.
|
||||
`signup` is the stable action for this surface. Preserve an existing custom migration action and compare the returned action to the same value. Siteverify is mandatory for every widget mode, including pre-clearance. Set `TURNSTILE_HOSTNAMES` to the deployment-specific frontend hostnames; a production value must not include `localhost` or `127.0.0.1`.
|
||||
|
||||
## Substitutions
|
||||
|
||||
| Placeholder | Replace with |
|
||||
| ------------------ | ------------------------------------------- |
|
||||
| `YOUR_WORKER_URL` | Deployed Worker URL from Step 5 |
|
||||
| `YOUR_SITEKEY` | Widget site key from Step 4 |
|
||||
| Placeholder | Replace with |
|
||||
| ------------------- | -------------------------------------------------------------------- |
|
||||
| `YOUR_SITEKEY` | The widget site key from Step 8 |
|
||||
| `TURNSTILE_SECRET` | Env-var name. Value is the secret captured in Step 8, kept off disk. |
|
||||
Reference in new issue
Block a user