Operate Your Project
Bot Protection
Add bot detection to your Next.js auth routes using Vercel BotID, Cloudflare Turnstile, reCAPTCHA, or hCaptcha — all built into @banata-auth/nextjs.
The bot protection SDK gives you a unified way to add bot detection to your Next.js auth routes. It supports Vercel BotID, Cloudflare Turnstile, Google reCAPTCHA, and hCaptcha out of the box.
You can wire up a provider directly using environment variables, or let the SDK pull your provider configuration from the dashboard automatically at runtime.
Bot protection ships with @banata-auth/nextjs — there is nothing extra to install:
import {
withBotProtection,
createBotIdVerifier,
createConfigAwareVerifier,
} from "@banata-auth/nextjs/bot-protection";Quick Start
Recommended: Config-Aware (Dashboard-Managed)
This approach reads your bot protection settings from the dashboard, so you can change providers or credentials without redeploying:
// app/api/auth/[...all]/route.ts
import { createRouteHandler } from "@banata-auth/nextjs";
import { withBotProtection, createConfigAwareVerifier } from "@banata-auth/nextjs/bot-protection";
const handler = createRouteHandler({
apiKey: process.env.BANATA_API_KEY!,
authUrl: process.env.BANATA_AUTH_URL,
});
const verify = createConfigAwareVerifier({
configApiUrl: process.env.NEXT_PUBLIC_APP_URL + "/api/auth",
});
export const GET = handler.GET;
export const POST = withBotProtection(handler.POST, { verify });With this setup, the verifier will:
- Fetch your Radar config from
/api/auth/banata/config/radar/get - Read the selected bot provider and credentials
- Verify incoming requests against that provider
- Cache the config in memory (default: 1-minute TTL)
Alternative: Direct Provider (Vercel BotID)
If you already have botid installed and want to skip dashboard configuration, you can wire up the provider directly:
// app/api/auth/[...all]/route.ts
import { createRouteHandler } from "@banata-auth/nextjs";
import { withBotProtection, createBotIdVerifier } from "@banata-auth/nextjs/bot-protection";
import { checkBotId } from "botid/server";
const handler = createRouteHandler({
apiKey: process.env.BANATA_API_KEY!,
authUrl: process.env.BANATA_AUTH_URL,
});
const verify = createBotIdVerifier(checkBotId);
export const GET = handler.GET;
export const POST = withBotProtection(handler.POST, { verify });API Reference
withBotProtection(handler, config)
Wraps a Next.js route handler with bot protection. Only requests whose path matches a protected prefix are verified — everything else passes through untouched.
withBotProtection(handler.POST, {
verify: async (request) => {
return { isBot: false };
},
protectedPaths: ["/api/auth/sign-in", "/api/auth/sign-up"],
failOpen: true,
blockedMessage: "Bot detected. Access denied.",
});| Option | Type | Default | Description |
|---|---|---|---|
verify | BotCheckFn | Required | Function that checks whether a request is from a bot |
protectedPaths | string[] | Sign-in, sign-up, forget/reset password | Path prefixes to protect |
failOpen | boolean | true | Allow requests through if verification fails |
blockedMessage | string | "Bot detected. Access denied." | Error message returned to blocked requests |
createBotIdVerifier(checkBotIdFn)
Creates a Vercel BotID verifier function:
import { checkBotId } from "botid/server";
const verify = createBotIdVerifier(checkBotId);Returns a BotCheckFn that calls checkBotId() and maps the result. If BotID throws (for example, when you are not running on Vercel), it returns { isBot: false }.
createConfigAwareVerifier(options)
Creates a verifier that reads provider credentials from the Banata Auth config API at runtime:
const verify = createConfigAwareVerifier({
configApiUrl: "http://localhost:3000/api/auth",
cacheTtlMs: 60000,
failOpen: true,
});| Option | Type | Default | Description |
|---|---|---|---|
configApiUrl | string | Required | Base URL of your Banata Auth API |
cacheTtlMs | number | 60000 (1 min) | How long to cache the Radar config |
cookieHeader | string | From request | Cookie header for authentication |
failOpen | boolean | true | Allow requests through on failure |
Supported Providers
Vercel BotID
- Dashboard fields: API Key
- How it works: An invisible challenge runs automatically on Vercel deployments. The
checkBotId()function verifies the challenge server-side. - Client-side setup: Install the
botidpackage, addwithBotId()to yournext.config.ts, and render<BotIdClient>in your root layout. - Hosting: Vercel only.
Cloudflare Turnstile
- Dashboard fields: Site Key, Secret Key
- How it works: Your client sends a Turnstile token in the
cf-turnstile-responseorx-turnstile-tokenheader. The server verifies it against Cloudflare's siteverify API. - Client-side setup: Add the Turnstile widget to your sign-in and sign-up forms.
- Hosting: Any provider.
Google reCAPTCHA
- Dashboard fields: Site Key, Secret Key
- How it works: Your client sends a reCAPTCHA v3 token in the
x-recaptcha-tokenorg-recaptcha-responseheader. The server verifies it and checks the score (threshold: 0.5). - Client-side setup: Add the reCAPTCHA v3 script to your pages.
- Hosting: Any provider.
hCaptcha
- Dashboard fields: Site Key, Secret Key
- How it works: Your client sends an hCaptcha token in the
x-hcaptcha-tokenorh-captcha-responseheader. The server verifies it against hCaptcha's siteverify API. - Client-side setup: Add the hCaptcha widget to your forms.
- Hosting: Any provider.
Architecture
Client Request
|
v
[Next.js Route Handler]
|
v
[withBotProtection] <-- Matches against protected paths
| Calls your verify() function
| Returns 403 if bot detected
v
[Auth Processing]The withBotProtection wrapper sits between your route handler and the auth layer. It only runs verification on the paths you configure, so non-auth routes are unaffected.
Security Considerations
- Fail-open by default — If the bot detection service is unavailable, requests are allowed through so legitimate users are not locked out. Set
failOpen: falseif you prefer stricter enforcement. - Credentials stay server-side — Provider credentials (API keys, secret keys) are stored in your Radar config and never exposed to the client.
- Config caching — The config-aware verifier caches the Radar config for 1 minute by default. After you change credentials in the dashboard, the new values take effect within that window.
- Token headers — For Turnstile, reCAPTCHA, and hCaptcha, your client must send the verification token in a request header. The expected header names are standardized per provider (see the provider details above).
Next Steps
- Radar — Enable bot detection and configure your provider credentials in the dashboard.