# Two-Factor Authentication (2FA) Options for Twenty CRM: TOTP Implementation Guide

> Explore Two-Factor Authentication (2FA) options for Twenty CRM. Learn how to implement TOTP with otplib for enhanced security using authenticator apps.

- Repository: [Twenty/twenty](https://github.com/twentyhq/twenty)
- Tags: how-to-guide
- Published: 2026-03-27

---

**Twenty CRM currently supports Time-Based One-Time Password (TOTP) as its sole Two-Factor Authentication strategy, utilizing the `otplib` library to enable standard authenticator apps like Google Authenticator and Authy without providing SMS or email-based alternatives.**

Twenty CRM, the open-source customer relationship management platform developed by twentyhq/twenty, implements enterprise-grade security through a dedicated TOTP-based Two-Factor Authentication (2FA) system. Understanding the available 2FA options for Twenty CRM helps administrators secure workspace access and developers extend the authentication layer. The architecture cleanly separates strategy definitions, encryption utilities, and UI components across the server and frontend packages.

## TOTP Strategy Architecture

Twenty CRM implements 2FA through a strategy pattern centered on the `TwoFactorAuthenticationStrategy` enum. Located in [`packages/twenty-shared/src/types/TwoFactorAuthenticationStrategy.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-shared/src/types/TwoFactorAuthenticationStrategy.ts), this enum currently declares only the `TOTP` value, establishing the foundation for the authenticator-app workflow.

The system persists user 2FA configurations via the `TwoFactorAuthenticationMethodEntity` in [`packages/twenty-server/src/engine/core-modules/two-factor-authentication/entities/two-factor-authentication-method.entity.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/two-factor-authentication/entities/two-factor-authentication-method.entity.ts). This entity stores the encrypted secret, the strategy type, and a status field tracking whether the method is `PENDING` or `ENABLED`.

### Core Service and Strategy Components

The `TwoFactorAuthenticationService` in [`packages/twenty-server/src/engine/core-modules/two-factor-authentication/two-factor-authentication.service.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/two-factor-authentication/two-factor-authentication.service.ts) orchestrates the entire 2FA lifecycle. It handles secret generation, URI construction for QR codes, encryption/decryption operations, and workspace policy enforcement. 

Concrete TOTP logic resides in the `TotpStrategy` class at [`packages/twenty-server/src/engine/core-modules/two-factor-authentication/strategies/otp/totp/totp.strategy.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/two-factor-authentication/strategies/otp/totp/totp.strategy.ts). This strategy implements token generation and validation using the `otplib` library, conforming to the standard RFC 6238 TOTP specification.

## Provisioning and Verifying 2FA

The 2FA flow in Twenty CRM follows a three-phase pattern: provisioning, verification, and enforcement. Each phase maps to specific GraphQL mutations exposed through the `TwoFactorAuthenticationResolver` in [`packages/twenty-server/src/engine/core-modules/two-factor-authentication/two-factor-authentication.resolver.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/two-factor-authentication/two-factor-authentication.resolver.ts).

### Step 1: Initiating 2FA Setup

When a user initiates 2FA setup, the system calls `initiateTwoFactorAuthenticationProvisioning`. The service generates a unique secret, encrypts it using `SimpleSecretEncryptionUtil`, and constructs a standard `otpauth://` URI.

```typescript
// Simplified from two-factor-authentication.service.ts
async initiateProvisioning(userId: string, workspaceId: string) {
  const secret = SimpleSecretEncryptionUtil.encrypt(
    this.buildSecretKey(userId, workspaceId),
  );

  const uri = authenticator.keyuri(
    userEmail,
    'Twenty – ' + workspaceName,
    secret,
  );

  await this.twoFactorAuthenticationRepository.save({
    userId,
    workspaceId,
    secret,
    strategy: TwoFactorAuthenticationStrategy.TOTP,
    status: 'PENDING',
  });

  return { uri };
}

```

### Step 2: Displaying the QR Code

The frontend receives the `otpauth://` URI and renders a scannable QR code. The `extractSecretFromOtpUri` utility in [`packages/twenty-front/src/modules/settings/two-factor-authentication/utils/extractSecretFromOtpUri.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-front/src/modules/settings/two-factor-authentication/utils/extractSecretFromOtpUri.ts) parses the URI to display the manual entry secret as a fallback.

```tsx
import { extractSecretFromOtpUri } from '@/settings/two-factor-authentication/utils/extractSecretFromOtpUri';
import QRCode from 'react-qr-code';

export function TwoFactorAuthProvision({ uri }: { uri: string }) {
  const secret = extractSecretFromOtpUri(uri);
  return (
    <div>
      <p>Scan this QR code with your authenticator app:</p>
      <QRCode value={uri} />
      <p>Or enter the secret manually: <code>{secret}</code></p>
    </div>
  );
}

```

### Step 3: Token Verification

After scanning the QR code, the user enters a 6-digit token from their authenticator app. The `verifyTwoFactorAuthenticationMethod` mutation validates this token through the `TotpStrategy.validate` method. Upon successful validation, the system updates the method status from `PENDING` to `ENABLED`.

```typescript
// From totp.strategy.ts validation logic
async verifyMethod(userId: string, workspaceId: string, token: string) {
  const method = await this.repo.findOne({ userId, workspaceId });
  const secret = SimpleSecretEncryptionUtil.decrypt(method.secret);
  const isValid = new TotpStrategy().validate(token, { secret });
  
  if (isValid) {
    method.status = 'ENABLED';
    await this.repo.save(method);
  }
  return isValid;
}

```

The frontend invokes this through a GraphQL mutation:

```tsx
const [verify] = useMutation(VERIFY_2FA_MUTATION);

const handleSubmit = async (code: string) => {
  const result = await verify({ variables: { token: code } });
  if (result.data.verifyTwoFactorAuthenticationMethod.success) {
    // Authentication complete, proceed to application
  }
};

```

## Workspace-Level 2FA Policy Enforcement

Twenty CRM supports mandatory 2FA at the workspace level. When administrators enable the policy via `twoFactorAuthenticationEnabled`, the `TwoFactorAuthenticationService` enforces verification before allowing privileged actions. 

The service throws a `TWO_FACTOR_AUTHENTICATION_VERIFICATION_REQUIRED` error when unverified users attempt restricted operations. This forces users to complete the verification flow described above. The frontend checks policy status through the `useWorkspaceTwoFactorAuthenticationPolicy` hook in [`packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useWorkspaceTwoFactorAuthenticationPolicy.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useWorkspaceTwoFactorAuthenticationPolicy.ts).

## Security Implementation Details

Secret encryption utilizes `SimpleSecretEncryptionUtil` located at [`packages/twenty-server/src/engine/core-modules/two-factor-authentication/utils/simple-secret-encryption.util.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/two-factor-authentication/utils/simple-secret-encryption.util.ts). This utility provides reversible encryption for TOTP secrets at rest, ensuring raw secrets never persist in the database in plaintext.

The system stores method state transitions explicitly. A method begins in `PENDING` status during initial setup, transitions to `ENABLED` after successful verification, and can be deleted via the `deleteTwoFactorAuthenticationMethod` mutation when users need to reset their 2FA configuration.

## Summary

- **Twenty CRM supports exclusively TOTP-based 2FA** defined in the `TwoFactorAuthenticationStrategy` enum, with no current support for SMS or email verification methods.
- **Secrets are encrypted at rest** using `SimpleSecretEncryptionUtil` before storage in the `TwoFactorAuthenticationMethodEntity` database table.
- **The `TotpStrategy` class handles all cryptographic operations** using the industry-standard `otplib` library for token generation and validation.
- **Workspace administrators can enforce mandatory 2FA** through the `twoFactorAuthenticationEnabled` policy, which triggers verification requirements across the workspace.
- **Frontend components manage the user experience** through dedicated hooks like `useCurrentUserWorkspaceTwoFactorAuthentication` and utilities like `extractSecretFromOtpUri`.

## Frequently Asked Questions

### What 2FA methods does Twenty CRM support?

Twenty CRM currently supports only Time-Based One-Time Password (TOTP) through authenticator apps. The `TwoFactorAuthenticationStrategy` enum in [`packages/twenty-shared/src/types/TwoFactorAuthenticationStrategy.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-shared/src/types/TwoFactorAuthenticationStrategy.ts) explicitly defines this single strategy, and the codebase contains no implementation for SMS or email-based verification codes.

### How does Twenty CRM store TOTP secrets securely?

The system encrypts secrets using `SimpleSecretEncryptionUtil` before persisting them via the `TwoFactorAuthenticationMethodEntity`. This ensures that TOTP secrets remain encrypted at rest in the database, decrypted only momentarily during the validation process within the `TotpStrategy` class.

### Can administrators require 2FA for all workspace members?

Yes. When a workspace has `twoFactorAuthenticationEnabled` set to `true`, the `TwoFactorAuthenticationService` enforces verification by throwing `TWO_FACTOR_AUTHENTICATION_VERIFICATION_REQUIRED` for privileged actions. This forces users to complete 2FA setup before accessing workspace resources, with policy status checked through both server-side guards and the frontend's `useWorkspaceTwoFactorAuthenticationPolicy` hook.

### Which authenticator apps are compatible with Twenty CRM?

Any standard authenticator application capable of parsing `otpauth://totp/` URIs works with Twenty CRM, including Google Authenticator, Authy, and Microsoft Authenticator. The `TwoFactorAuthenticationService` generates standard-compliant URIs via the `authenticator.keyuri` method, ensuring broad compatibility with RFC 6238 compliant applications.