# Configuring Logto Verification Records and CAPTCHA Providers: A Complete Guide

> Master configuring Logto verification records and CAPTCHA providers reCAPTCHA Enterprise and Turnstile. Secure your authentication flow with this comprehensive guide.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-04

---

**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`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/interactions.ts), where you can also find the optional `captchaToken` field used when CAPTCHA verification completes:

```typescript
// 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`](https://github.com/logto-io/logto/blob/main/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 `setValue` method when a verification step completes
- The map exposes helper methods like `isMfaVerified` to evaluate multi-factor authentication status
- Records are converted to JSON for API responses using `verificationRecords: this.verificationRecordsArray.map(r => r.toJson())`

```typescript
// 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`](https://github.com/logto-io/logto/blob/main/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`](https://github.com/logto-io/logto/blob/main/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`, `projectId` for 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`](https://github.com/logto-io/logto/blob/main/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`](https://github.com/logto-io/logto/blob/main/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:

```javascript
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:

```javascript
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:

```javascript
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_records` table and are managed through the `VerificationRecordsMap` class in `ExperienceInteraction`
- **CAPTCHA providers** are configured in the `captcha_providers` table with support for reCAPTCHA Enterprise and Cloudflare Turnstile
- The system enforces a **single provider policy** through the `/api/captcha-provider` endpoints
- **Admin console** configuration is available under Security → CAPTCHA for visual management
- Successful CAPTCHA verification adds a `captchaToken` to 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`](https://github.com/logto-io/logto/blob/main/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`](https://github.com/logto-io/logto/blob/main/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`](https://github.com/logto-io/logto/blob/main/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.