# How to set up Google two-step verification in Bubble

- Tool: Bubble
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: All Bubble plans
- Last updated: March 2026

## TL;DR

You can add Google Authenticator-based two-factor authentication to your Bubble app by generating TOTP secrets, displaying QR codes for the authenticator app, and verifying six-digit codes at login. This requires a TOTP plugin or API service to generate secrets and validate codes. The result is a secure 2FA flow that protects user accounts beyond just passwords.

## Add Google Authenticator Two-Factor Authentication to Your Bubble App

This tutorial guides you through implementing TOTP-based two-factor authentication using Google Authenticator in your Bubble app. You will learn how to generate secrets, display QR codes, verify codes during login, and provide recovery options. This is essential for apps handling sensitive data, financial transactions, or user accounts that need extra security.

## Before you start

- A Bubble account with an existing app that has user authentication (login/signup)
- Basic understanding of Bubble workflows and the Data tab
- A smartphone with Google Authenticator (or any TOTP app) installed for testing
- Familiarity with the API Connector plugin for calling external services

## Step-by-step guide

### 1. Add 2FA Fields to the User Data Type

Go to the Data tab → Data types → User. Add three new fields: 'totp_secret' (text) — stores the secret key for each user, 'two_fa_enabled' (yes/no, default no) — tracks whether the user has enabled 2FA, and 'recovery_codes' (text, list) — stores backup recovery codes. Set Privacy Rules so that totp_secret and recovery_codes are only viewable by the user themselves and never exposed in searches by other users.

> Pro tip: Never expose the totp_secret field to the frontend. Use backend workflows to generate and validate TOTP codes so the secret stays server-side.

**Expected result:** The User data type has three new fields for 2FA: totp_secret, two_fa_enabled, and recovery_codes.

### 2. Install a TOTP Plugin or Configure an External TOTP API

Search the Bubble plugin marketplace for a TOTP or 2FA plugin. If a suitable plugin is available, install it. Alternatively, use an external TOTP API service via the API Connector. In the API Connector, add a new API called 'TOTP Service'. Add two calls: one to generate a secret (GET/POST that returns a secret key and a QR code URL), and one to verify a code (POST that accepts the secret and the user's six-digit code, returns true/false). Common TOTP services include authenticator APIs or self-hosted solutions.

**Expected result:** You have a way to generate TOTP secrets and verify codes, either through a plugin or API Connector.

### 3. Build the Enable 2FA Page

Create a page or popup for enabling 2FA. Add a Button labeled 'Enable 2FA'. Create a workflow: when clicked, call the TOTP API to generate a new secret for the user. Save the returned secret to Current User's totp_secret field using a backend workflow (to keep it server-side). Display the QR code image using an Image element with the dynamic source set to the QR code URL returned by the API. Add a Text element showing the manual entry key for users who cannot scan. Below the QR code, add an Input for the user to enter a six-digit verification code and a 'Verify' button.

**Expected result:** Users see a QR code to scan with Google Authenticator and an input to enter their first verification code.

### 4. Verify the Code and Complete 2FA Setup

Create a workflow on the 'Verify' button: call the TOTP verification API with the user's secret and the entered six-digit code. If the API returns success (code is valid), update Current User's two_fa_enabled to 'yes'. Generate 8-10 random recovery codes (use a backend workflow with 'Calculate a random string' repeated 10 times) and save them to Current User's recovery_codes field. Display the recovery codes in a Group so the user can copy them. Show a success message: '2FA has been enabled. Save your recovery codes in a safe place.' If verification fails, show an error: 'Invalid code. Please try again.'

**Expected result:** After scanning the QR code and entering a valid six-digit code, 2FA is enabled and recovery codes are displayed.

### 5. Add 2FA Verification to the Login Flow

Modify your login workflow. After the 'Log the user in' action succeeds, add a condition check: 'Only when Current User's two_fa_enabled is yes'. If true, redirect to a '2fa-verify' page instead of the dashboard. On the 2fa-verify page, add an Input for the six-digit code and a 'Verify' button. The verify workflow calls the TOTP API with Current User's totp_secret and the entered code. If valid, redirect to the dashboard. If invalid, show an error message. Add a 'Use recovery code' link that reveals a separate input — verify the entered code against Current User's recovery_codes list, and if found, remove that code from the list (it is single-use).

> Pro tip: Add a 'Remember this device' checkbox that sets a cookie or a Device data type entry. On future logins from recognized devices, skip the 2FA step.

**Expected result:** Users with 2FA enabled are prompted for a six-digit code after logging in, and can use recovery codes as a fallback.

### 6. Build a Disable 2FA Option

In user settings, add a 'Disable 2FA' button that is only visible when Current User's two_fa_enabled is yes. The workflow should first require the user to enter their current six-digit TOTP code to confirm identity. After successful verification, set Current User's two_fa_enabled to 'no', clear the totp_secret field, and clear the recovery_codes list. Show a confirmation message that 2FA has been disabled.

**Expected result:** Users can disable 2FA from their settings after verifying their current authenticator code.

## Complete code example

File: `Workflow summary`

```text
DATA TYPE CHANGES:
- User (modified)
  - totp_secret (text) — PRIVATE, backend-only access
  - two_fa_enabled (yes/no, default: no)
  - recovery_codes (list of text) — PRIVATE

PRIVACY RULES:
- User: totp_secret — visible only to Current User (via backend workflow)
- User: recovery_codes — visible only to Current User

PAGES:

1. PAGE: settings/security (Enable 2FA section)
   - Button "Enable 2FA" (visible when Current User's two_fa_enabled is no)
   - Group QRCode (hidden by default)
     - Image: QR code URL from TOTP API
     - Text: Manual entry key
     - Input VerifyCode (6 digits)
     - Button "Verify & Enable"
   - Group RecoveryCodes (hidden by default)
     - RepeatingGroup showing recovery codes
     - Text: "Save these codes — each can only be used once"
   - Button "Disable 2FA" (visible when Current User's two_fa_enabled is yes)

2. PAGE: 2fa-verify (shown after login)
   - Text: "Enter your 6-digit authentication code"
   - Input TOTPCode
   - Button "Verify"
   - Link "Use recovery code instead"
   - Input RecoveryCode (hidden by default)
   - Button "Verify Recovery Code" (hidden by default)

WORKFLOWS:
1. Enable 2FA clicked → Call TOTP API: generate secret
   → Backend workflow: save secret to Current User's totp_secret
   → Display QR code image → Show QR code group

2. Verify & Enable clicked → Call TOTP API: verify code
   → If valid: Set two_fa_enabled = yes
   → Generate 10 recovery codes (backend workflow)
   → Save recovery codes → Show RecoveryCodes group
   → If invalid: Show error alert

3. Login workflow → Log the user in
   → Only when Current User's two_fa_enabled is yes:
     Go to page 2fa-verify
   → Only when Current User's two_fa_enabled is no:
     Go to page dashboard

4. Verify (2fa page) → Call TOTP API: verify code
   → If valid: Go to page dashboard
   → If invalid: Show error "Invalid code"

5. Verify Recovery Code → Check if entered code is in Current User's recovery_codes
   → If found: Remove code from list → Go to page dashboard
   → If not found: Show error "Invalid recovery code"

6. Disable 2FA → Verify current TOTP code first
   → If valid: Set two_fa_enabled = no, clear totp_secret, clear recovery_codes
   → Show confirmation
```

## Common mistakes

- **Storing the TOTP secret in a client-visible field** — If the secret is exposed to the frontend, an attacker could generate valid codes without the user's phone. Fix: Use Privacy Rules to hide the totp_secret field from client access. All TOTP operations should run through backend workflows.
- **Not generating recovery codes during setup** — If a user loses their phone and has no recovery codes, they are permanently locked out of their account. Fix: Always generate 8-10 single-use recovery codes during 2FA setup and display them for the user to save.
- **Allowing TOTP codes to be verified multiple times** — TOTP codes are valid for a 30-second window. If your verification does not account for replay, a code could theoretically be reused. Fix: Most TOTP APIs handle this automatically. If building custom verification, track the last verified code timestamp and reject codes from the same time window.

## Best practices

- Always process TOTP secrets and verification in backend workflows to keep secrets server-side.
- Generate 8-10 recovery codes and make each single-use — remove from the list after use.
- Add rate limiting to the 2FA verification page to prevent brute-force attacks (lock after 5 failed attempts).
- Allow users to regenerate recovery codes from settings after re-verifying their current TOTP code.
- Show a clear warning when users disable 2FA explaining the security implications.
- Test the entire flow end-to-end: enable, login with 2FA, use recovery code, disable, re-enable.
- Consider supporting multiple authenticator apps — any TOTP-compatible app works with the same QR code format.

## Frequently asked questions

### Does Google Authenticator work with Bubble apps?

Yes. Google Authenticator uses the standard TOTP (Time-based One-Time Password) protocol. Any app that generates TOTP secrets and QR codes in the correct format will work with Google Authenticator, Microsoft Authenticator, Authy, and other TOTP-compatible apps.

### Can I use SMS-based 2FA instead of an authenticator app?

Yes, but SMS 2FA is less secure due to SIM-swapping attacks. You can implement SMS 2FA using Twilio or similar services via the API Connector. Authenticator-based TOTP is recommended for better security.

### What happens if a user loses their phone?

Recovery codes allow users to log in without their authenticator. They enter a recovery code instead of the 6-digit TOTP code. Each recovery code works once. If they exhaust all recovery codes, an admin must manually disable 2FA on their account.

### How do I handle 2FA for admin accounts?

Consider making 2FA mandatory for admin roles. In the admin creation workflow, automatically enable 2FA and require setup before granting admin access.

### Is there a Bubble plugin that handles the entire 2FA flow?

Some plugins provide partial TOTP functionality, but most require combining with API calls for full implementation. For complex security requirements, teams like RapidDev can build a complete, tested 2FA system tailored to your app.

### Can I enforce 2FA for all users?

Yes. Add a check on page load for authenticated pages: if Current User's two_fa_enabled is 'no', redirect to a setup page that requires enabling 2FA before accessing the app.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/set-up-google-two-factor-authentication-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/set-up-google-two-factor-authentication-in-bubble
