Configuring Logto Verification Records and CAPTCHA Providers: A Complete Guide
Logto stores authentication steps in verification records indexed by type in a VerificationRecordsMap, while CAPTCHA providers like reCAPTCHA Enterprise and Turnstile are configured via the /api/captcha-provider endpoint and managed through the Security → CAPTCHA settings in the admin console.
When implementing secure authentication flows in the logto-io/logto identity platform, understanding how verification records and CAPTCHA providers work together is essential. This guide explores the internal architecture of verification tracking and the practical steps for configuring bot protection in your sign-in experiences.
Understanding Verification Records in Logto
Logto tracks every step a user takes during authentication through verification records. These records represent distinct verification methods including password validation, one-time tokens, social logins, Enterprise SSO, and CAPTCHA challenges.
How Verification Records Are Stored
Each verification record is persisted in the verification_records database table. The records are assembled into an array attached to the interaction context, making them accessible to custom token-claims scripts, the admin console, and the front-end experience.
The interaction schema defines these records in packages/schemas/src/types/interactions.ts, where you can also find the optional captchaToken field used when CAPTCHA verification completes:
// From packages/schemas/src/types/interactions.ts
captchaToken?: string; // Present when CAPTCHA verification succeeds
The VerificationRecordsMap Class
The core interaction engine implements verification tracking through the ExperienceInteraction class in packages/core/src/routes/experience/classes/experience-interaction.ts. This class maintains a VerificationRecordsMap that indexes records by VerificationType.
Key implementation details from the source code include:
- Records are added via the
setValuemethod when a verification step completes - The map exposes helper methods like
isMfaVerifiedto evaluate multi-factor authentication status - Records are converted to JSON for API responses using
verificationRecords: this.verificationRecordsArray.map(r => r.toJson())
// Conceptual usage from the ExperienceInteraction implementation
class VerificationRecordsMap {
// Indexes records by verification type
setValue(type: VerificationType, record: VerificationRecord): void;
// Evaluates MFA completion status
isMfaVerified(): boolean;
// Converts records for API responses
get verificationRecordsArray(): VerificationRecord[];
}
Supported CAPTCHA Providers and Configuration
Logto supports two enterprise-grade CAPTCHA providers to protect registration, sign-in, and password-recovery flows. Only one provider can be active at a time according to the single provider policy enforced in the core routes.
reCAPTCHA Enterprise Configuration
The reCAPTCHA Enterprise provider requires specific configuration fields defined in packages/schemas/src/foundations/jsonb-types/captcha.ts:
| Field | Type | Description |
|---|---|---|
type |
string | "RecaptchaEnterprise" |
siteKey |
string | Your reCAPTCHA site key |
secretKey |
string | Your reCAPTCHA secret key |
projectId |
string | Google Cloud project identifier |
domain |
string | Optional custom domain (e.g., recaptcha.net) |
mode |
string | Optional: "invisible" or "checkbox" |
Turnstile Configuration
Cloudflare Turnstile offers a simpler configuration schema with fewer required fields:
| Field | Type | Description |
|---|---|---|
type |
string | "Turnstile" |
siteKey |
string | Your Turnstile site key |
secretKey |
string | Your Turnstile secret key |
Database Schema and REST API
Provider configurations are stored in the captcha_providers table, which was added by the 1.26.0-1741572426-add-captcha-providers alteration script. The REST API exposes these settings through endpoints defined in packages/core/src/routes/captcha-provider/index.ts.
The API enforces a single provider policy, meaning you can configure either reCAPTCHA Enterprise or Turnstile, but not both simultaneously.
Enabling CAPTCHA in Authentication Flows
Once configured, CAPTCHA protection must be explicitly enabled for specific authentication flows through the admin console or management API.
Admin Console Configuration
In the Logto admin console, navigate to Security → CAPTCHA to:
- Toggle CAPTCHA on/off for registration, sign-in, and password-recovery flows
- Select your configured provider (reCAPTCHA Enterprise or Turnstile)
- Enter required credentials (
siteKey,secretKey,projectIdfor reCAPTCHA) - Optionally specify a custom domain for regions where default endpoints are restricted
The UI implementation fetches configuration data from packages/console/src/pages/Security/Captcha/use-data-fetch.ts.
Interaction Flow Integration
When CAPTCHA is enabled, the interaction flow checks the captchaEnabled flag before presenting the widget. Upon successful verification, the captchaToken is added to the interaction record and validated during the authentication process.
The system queries verification records through the database layer defined in packages/core/src/tenants/Queries.ts, ensuring persistence across interaction steps.
Practical Implementation Examples
Below are complete examples for interacting with verification records and configuring CAPTCHA providers via the Logto Management API.
Fetching Verification Records
Retrieve the current interaction state to inspect verification progress:
const interaction = await fetch(
`${baseUrl}/api/interaction/${interactionId}`,
{
headers: {
Authorization: `Bearer ${adminToken}`
}
}
).then(r => r.json());
console.log('Verification records:', interaction.verificationRecords);
Configuring reCAPTCHA Enterprise
Update your CAPTCHA provider configuration using the REST API:
await fetch(`${baseUrl}/api/captcha-provider`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${adminToken}`,
},
body: JSON.stringify({
type: 'RecaptchaEnterprise',
siteKey: 'your-site-key',
secretKey: 'your-secret-key',
projectId: 'your-project-id',
domain: 'recaptcha.net', // Optional: for regions requiring custom domains
mode: 'invisible', // Optional: or 'checkbox'
}),
});
Enabling CAPTCHA via Management API
Activate CAPTCHA protection for your sign-in experience:
await fetch(`${baseUrl}/api/sign-in-experience`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${adminToken}`,
},
body: JSON.stringify({
captchaConfig: {
enabled: true,
},
}),
});
Summary
- Verification records track authentication steps in the
verification_recordstable and are managed through theVerificationRecordsMapclass inExperienceInteraction - CAPTCHA providers are configured in the
captcha_providerstable with support for reCAPTCHA Enterprise and Cloudflare Turnstile - The system enforces a single provider policy through the
/api/captcha-providerendpoints - Admin console configuration is available under Security → CAPTCHA for visual management
- Successful CAPTCHA verification adds a
captchaTokento the interaction record, which is defined in the interaction schema
Frequently Asked Questions
What are verification records in Logto?
Verification records are database entries that track each step a user completes during authentication. Stored in the verification_records table, they represent distinct methods like password verification, social login, or CAPTCHA completion. The ExperienceInteraction class indexes these by type in a VerificationRecordsMap and exposes helper methods like isMfaVerified to evaluate authentication status.
How do I configure CAPTCHA in Logto?
You can configure CAPTCHA through the admin console at Security → CAPTCHA or via the /api/captcha-provider REST endpoint. You must provide the provider type (RecaptchaEnterprise or Turnstile), site key, and secret key. For reCAPTCHA Enterprise, you also need a projectId. Only one provider can be active at a time according to the enforcement logic in packages/core/src/routes/captcha-provider/index.ts.
What CAPTCHA providers does Logto support?
Logto currently supports two providers: reCAPTCHA Enterprise and Cloudflare Turnstile. reCAPTCHA Enterprise supports optional configuration for custom domains and display modes (invisible or checkbox), while Turnstile requires only the site key and secret key. Both are defined in packages/schemas/src/foundations/jsonb-types/captcha.ts.
Where are verification records stored in the database?
Verification records are stored in the verification_records table and queried through the database layer in packages/core/src/tenants/Queries.ts. The records are attached to interaction contexts and converted to JSON for API responses, allowing inspection by custom token-claims scripts and the admin console.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →