reCAPTCHA Bot Protection
Protect login and signup endpoints from bots using Google reCAPTCHA. nauth-toolkit supports v2 (checkbox), v3 (score-based), and Enterprise.
Overview
- Backend: Optional
@nauth-toolkit/recaptchapackage. Configure provider,minimumScore, and optionalactionScoresfor v3/Enterprise. Use@RequireRecaptcha()decorator on endpoints that need protection. - Frontend: Client sends
recaptchaTokenin login/signup requests. Angular SDK can auto-generate tokens for v3/Enterprise viaRecaptchaServiceandprovideRecaptcha().
Backend Setup
Installation
- npm
- Yarn
- pnpm
- Bun
npm install @nauth-toolkit/recaptcha
yarn add @nauth-toolkit/recaptcha
pnpm add @nauth-toolkit/recaptcha
bun add @nauth-toolkit/recaptcha
Configuration
- NestJS
- Express
- Fastify
import { AuthModule } from '@nauth-toolkit/nestjs';
import { RecaptchaEnterpriseProvider } from '@nauth-toolkit/recaptcha';
@Module({
imports: [
AuthModule.forRoot({
recaptcha: {
enabled: true,
provider: new RecaptchaEnterpriseProvider({
projectId: process.env.RECAPTCHA_PROJECT_ID!,
apiKey: process.env.RECAPTCHA_API_KEY!,
siteKey: process.env.RECAPTCHA_SITE_KEY!,
}),
minimumScore: 0.5,
actionScores: { // Optional: per-action overrides
login: 0.3, // More permissive for returning users
signup: 0.7, // Stricter for new registrations
},
},
}),
],
})
export class AppModule {}
// In your controller, mark endpoints that need protection:
import { RequireRecaptcha } from '@nauth-toolkit/nestjs';
@Controller('auth')
export class AuthController {
@Public()
@RequireRecaptcha() // Require reCAPTCHA for login
@Post('login')
async login(@Body() dto: LoginDTO) {
return this.authService.login(dto);
}
@Public()
@RequireRecaptcha() // Require reCAPTCHA for signup
@Post('signup')
async signup(@Body() dto: SignupDTO) {
return this.authService.signup(dto);
}
}
import { NAuth } from '@nauth-toolkit/core';
import { RecaptchaEnterpriseProvider } from '@nauth-toolkit/recaptcha';
const nauth = await NAuth.create(config, dataSource);
The recaptcha configuration is passed as part of the config object passed to NAuth.create():
recaptcha: {
enabled: true,
provider: new RecaptchaEnterpriseProvider({
projectId: process.env.RECAPTCHA_PROJECT_ID!,
apiKey: process.env.RECAPTCHA_API_KEY!,
siteKey: process.env.RECAPTCHA_SITE_KEY!,
}),
minimumScore: 0.5,
actionScores: { // Optional: per-action overrides
login: 0.3,
signup: 0.7,
},
},
import { NAuth } from '@nauth-toolkit/core';
import { RecaptchaEnterpriseProvider } from '@nauth-toolkit/recaptcha';
const nauth = await NAuth.create(config, dataSource);
The recaptcha configuration is passed as part of the config object passed to NAuth.create():
recaptcha: {
enabled: true,
provider: new RecaptchaEnterpriseProvider({
projectId: process.env.RECAPTCHA_PROJECT_ID!,
apiKey: process.env.RECAPTCHA_API_KEY!,
siteKey: process.env.RECAPTCHA_SITE_KEY!,
}),
minimumScore: 0.5,
actionScores: { // Optional: per-action overrides
login: 0.3,
signup: 0.7,
},
},
See RecaptchaConfig for all options. For v2 or v3, use RecaptchaV2Provider or RecaptchaV3Provider.
Startup Validation
By default, nauth validates your reCAPTCHA credentials at startup by sending a probe request to Google's API. This catches misconfigured API keys, wrong project IDs, or disabled APIs before a real user hits the endpoint.
recaptcha: {
enabled: true,
provider: new RecaptchaEnterpriseProvider({ /* ... */ }),
validateOnStartup: 'warn', // Default: log warning if credentials are invalid
// validateOnStartup: 'error', // Halt startup on invalid credentials
// validateOnStartup: false, // Skip validation entirely
},
| Mode | Behavior |
|---|---|
'warn' (default) | Logs a warning with actionable hint, continues startup |
'error' | Throws NAuthException and halts startup |
false | Skips validation entirely |
Use 'error' in production to fail fast on misconfigured credentials. Use 'warn' during development when iterating on reCAPTCHA setup.
Frontend Setup
Angular (v3/Enterprise)
- Add
recaptchato NAuthClientConfig and useprovideRecaptcha():
import { provideRecaptcha } from '@nauth-toolkit/client-angular/standalone';
export const appConfig: ApplicationConfig = {
providers: [
{ provide: NAUTH_CLIENT_CONFIG, useValue: { baseUrl: '...', tokenDelivery: 'cookies', recaptcha: { enabled: true, version: 'enterprise', siteKey: '...' } } },
provideRecaptcha({ enabled: true, version: 'enterprise', siteKey: '...' }),
// ...
],
};
AuthService.login()andsignup()automatically obtain and send the token. No changes needed in login/signup components.
Vanilla / React / Vue
- Load the reCAPTCHA script: for Enterprise
https://www.google.com/recaptcha/enterprise.js?render=YOUR_SITE_KEY, for v3https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY. - Before calling
client.login()orclient.signup(), rungrecaptcha.enterprise.execute(siteKey, { action: 'login' })(orgrecaptcha.executefor v3) and pass the result asrecaptchaTokenin the request or as the third argument tologin(identifier, password, recaptchaToken).
Google Cloud Setup (Enterprise)
- Enable reCAPTCHA Enterprise API in Google Cloud Console.
- Create a Score-based site key in reCAPTCHA Enterprise. Add domains (e.g.
localhost, your production domain). - Create an API key in APIs & Services > Credentials. Restrict it to reCAPTCHA Enterprise API. For server-to-server calls, do not use HTTP referrer restrictions (use None or IP).
- Set env:
RECAPTCHA_PROJECT_ID,RECAPTCHA_API_KEY,RECAPTCHA_SITE_KEY.
Security
- Keep API keys and secret keys server-side only. Only the site key is public.
- Use
@RequireRecaptcha()decorator on public endpoints vulnerable to bot attacks (login, signup, password reset). - Set
minimumScorebased on your risk tolerance (0.5 is a common default). UseactionScoresfor per-action thresholds. - Score checks only apply when the provider returns a score (v3/Enterprise score-based keys). Enterprise checkbox keys skip score validation automatically.
Related
- RecaptchaConfig
- reCAPTCHA Overview
- NAuthClientConfig (
recaptchaproperty) - Configuration (reCAPTCHA section)