TOTP QR Code for Authenticator Apps

Generate TOTP QR codes that authenticator apps can scan. Learn how otpauth:// URIs are encoded as QR codes and best practices for secure provisioning in your enrollment flow.

Security

Detailed Explanation

Generating TOTP QR Codes

QR codes are the primary method for transferring TOTP secrets from a server to an authenticator app. The QR code encodes an otpauth:// URI that contains the secret and all configuration parameters.

How It Works

The enrollment flow follows these steps:

  1. Server generates a random secret and encodes it as Base32
  2. Server constructs an otpauth://totp/... URI with the secret and parameters
  3. The URI is rendered as a QR code on the enrollment page
  4. User scans the QR code with their authenticator app
  5. The app extracts and stores the secret, issuer, account name, and settings

Generating QR Codes

Server-side (Node.js with qrcode library):

const QRCode = require('qrcode');
const uri = 'otpauth://totp/MyApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=MyApp';
const dataUrl = await QRCode.toDataURL(uri, { width: 256 });
// Send dataUrl to client as <img src={dataUrl} />

Client-side (using a JavaScript QR library):

import { toDataURL } from 'qrcode';
const dataUrl = await toDataURL(uri, { errorCorrectionLevel: 'M', width: 256 });

QR Code Best Practices

  • Size: minimum 256x256 pixels for reliable scanning
  • Error correction: use level M (15% recovery) or Q (25%) for better scan reliability
  • Contrast: black modules on white background — avoid colored or styled QR codes
  • Quiet zone: maintain at least 4 modules of white space around the QR code

Security Considerations

The QR code contains the plaintext secret, so treat it as sensitive data:

  • Never cache the QR code image on CDNs or in browser cache
  • Generate on demand — create the QR code only during the enrollment session
  • Use HTTPS — the page displaying the QR code must be served over TLS
  • Expire the session — invalidate the enrollment page after a timeout or successful verification
  • Show the secret as text too — some users prefer manual entry (provide a "Can't scan?" option)

Fallback: Manual Entry

Always provide the Base32 secret as copyable text alongside the QR code. Users may need manual entry when:

  • Their camera is broken
  • They are using a desktop authenticator
  • The QR code fails to scan
  • Screen reader accessibility is needed

Use Case

Frontend and backend developers building a 2FA enrollment page need to generate and display QR codes securely. This guide covers the full pipeline from URI construction to QR rendering, with important security considerations that prevent secret leakage. It is particularly relevant when designing enrollment UIs, implementing the 'Can't scan the code?' fallback, and ensuring the provisioning page meets security review requirements.

Try It — TOTP Generator

Open full tool