Two-Factor Authentication (2FA) Options for Twenty CRM: TOTP Implementation Guide
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, 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. 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 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. 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.
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.
// 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 parses the URI to display the manual entry secret as a fallback.
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.
// 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:
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.
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. 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
TwoFactorAuthenticationStrategyenum, with no current support for SMS or email verification methods. - Secrets are encrypted at rest using
SimpleSecretEncryptionUtilbefore storage in theTwoFactorAuthenticationMethodEntitydatabase table. - The
TotpStrategyclass handles all cryptographic operations using the industry-standardotpliblibrary for token generation and validation. - Workspace administrators can enforce mandatory 2FA through the
twoFactorAuthenticationEnabledpolicy, which triggers verification requirements across the workspace. - Frontend components manage the user experience through dedicated hooks like
useCurrentUserWorkspaceTwoFactorAuthenticationand utilities likeextractSecretFromOtpUri.
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 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.
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 →