Skip to content

Implement TOTP two-factor authentication (RFC 6238) with Yubikey support#9189

Closed
Copilot wants to merge 9 commits intomasterfrom
copilot/add-totp-authentication-feature
Closed

Implement TOTP two-factor authentication (RFC 6238) with Yubikey support#9189
Copilot wants to merge 9 commits intomasterfrom
copilot/add-totp-authentication-feature

Conversation

Copy link

Copilot AI commented Jan 3, 2026

Adds optional TOTP-based two-factor authentication to complement username/password login. Feature is disabled by default and users opt-in individually. Supports both standard 6-digit codes and 8-digit codes for Yubikey compatibility.

Core Implementation

  • lib/LedgerSMB/TOTP.pm: RFC 6238 compliant TOTP module

    • Cryptographically secure secret generation via /dev/urandom
    • Code verification with configurable time window (±30s default)
    • Supports both 6-digit (standard) and 8-digit (Yubikey) codes
    • Configurable digits attribute (default: 6, supports: 8)
    • QR code generation for authenticator app setup
    • Fails closed if secure RNG unavailable
  • lib/LedgerSMB/Scripts/login.pm: Authentication flow integration

    • TOTP verification after password validation (no information leakage)
    • Automatically tries both 6 and 8-digit code verification
    • Returns X-LedgerSMB-TOTP-Required: 1 header when code needed
    • Brute force protection with configurable lockout
  • Database schema (sql/changes/1.13/add-totp-support.sql):

    • totp_secret, totp_enabled, totp_failures, totp_last_used, totp_locked_until columns on users table
    • SQL functions: admin__totp_enable_user, admin__totp_disable_user, user__totp_verify_and_update

User Interface

  • Setup page with QR code display (UI/users/totp_setup.html)
    • Accepts 6-8 digit codes
  • Status management page (UI/users/totp_status.html)
  • Preferences tab integration
  • JavaScript handler for TOTP input during login (UI/js-src/lsmb/TOTPLogin.js)
    • Validates 6-8 digit codes with appropriate error messages

Configuration

totp_settings:
  enabled: false              # Global enable/disable
  max_failures: 5             # Lockout threshold
  lockout_duration: 900       # Seconds (15 min)
  time_window: 1              # ±30s tolerance

Security Features

  • Replay prevention via totp_last_used timestamp tracking
  • Lockout with proper expiration checking (verifies timestamp > current_time)
  • Case-insensitive header handling in JavaScript
  • Anchored regex patterns in validation
  • Flexible code length support (6 or 8 digits)

Supported Devices

  • Google Authenticator
  • Microsoft Authenticator
  • Authy
  • Yubikey (6 or 8-digit codes)
  • 1Password
  • Bitwarden
  • LastPass Authenticator
  • FreeOTP
  • AndOTP

Dependencies

  • Auth::GoogleAuth: TOTP implementation
  • Convert::Base32: Secret encoding
  • GD::Barcode::QRcode: QR generation

Example Usage

# Generate and enable TOTP
my $secret = LedgerSMB::TOTP->generate_secret();
my $totp = LedgerSMB::TOTP->new(
    secret => $secret,
    account => $username,
    issuer => 'LedgerSMB',
    digits => 8  # Optional: 6 (default) or 8 for Yubikey
);

# Verify code
if ($totp->verify_code($user_code)) {
    # Grant access
}

# Generate QR code
my $qr_base64 = $totp->qr_code_base64();

Testing

Unit tests in t/13.1-totp.t cover secret generation, code verification (both 6 and 8-digit), QR generation, and error handling.

Original prompt

Implement Time-based One-Time Password (TOTP) authentication as an additional security measure to complement the existing username/password authentication in LedgerSMB. The implementation should follow these guidelines: - Make TOTP an optional feature that administrators can enable or disable via a configuration setting. - Adhere to standard TOTP algorithms defined in RFC 6238. - Include a user interface for managing TOTP, allowing users to enable, disable, and reset their TOTP configuration. - Implement a QR code generation feature to simplify the TOTP setup process for users in authenticator apps like Google Authenticator. - Provide robust error handling and security measures to prevent abuse, such as brute force protections. - Allow fallback authentication using only username/password for users without TOTP enabled. - Add automated tests to ensure the feature's security and functionality.

This pull request was created from Copilot chat.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 7 commits January 3, 2026 19:07
Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
- Use cryptographically secure random source (/dev/urandom) for TOTP secret generation
- Fix lockout check to properly verify if lockout period has expired
- Fix SQL function variable scope issue in user__totp_verify_and_update

Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
- Remove insecure fallback random generation; fail securely if /dev/urandom unavailable
- Add clarifying comment about credential validation flow in login
- Fix SQL lockout status check to verify timestamp is in future
- Fix JavaScript header comparison to be case-insensitive
- Anchor HTML pattern regex to prevent partial matches

Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
- Anchor regex pattern in JavaScript TOTP input validation
- Fix Enter key handler to call callback directly
- Add periods to documentation list items for consistency

Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement time-based one-time password authentication Implement TOTP two-factor authentication (RFC 6238) Jan 3, 2026
Copilot AI requested a review from ehuelsmann January 3, 2026 19:23
@ehuelsmann
Copy link
Member

@copilot thanks! Can you add the option to allow Yubikey TOTP too?

- Add 'digits' attribute to TOTP module (supports 6 or 8 digits)
- Update verify_code to accept configured digit length
- Update UI to accept 6-8 digit codes
- Update login and user management to try both 6 and 8-digit verification
- Update documentation to mention Yubikey compatibility
- Add tests for 8-digit code verification

Co-authored-by: ehuelsmann <2326559+ehuelsmann@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 4, 2026

@copilot thanks! Can you add the option to allow Yubikey TOTP too?

Yubikey TOTP support has been added in commit 3a28913. The implementation now accepts both 6-digit (standard) and 8-digit (Yubikey default) codes. Key changes:

  • Added digits attribute to TOTP module
  • Updated verification logic to try both 6 and 8-digit codes automatically
  • Updated UI validation to accept 6-8 digit inputs
  • Added comprehensive documentation for Yubikey usage
  • Added tests for 8-digit code verification

Yubikeys and all other RFC 6238 compliant TOTP devices are now fully supported.

Copilot AI changed the title Implement TOTP two-factor authentication (RFC 6238) Implement TOTP two-factor authentication (RFC 6238) with Yubikey support Jan 4, 2026
@ehuelsmann
Copy link
Member

@copilot, please move this branch to my repository ( ehuelsmann/LedgerSMB ).

Copy link
Author

Copilot AI commented Feb 7, 2026

@copilot, please move this branch to my repository ( ehuelsmann/LedgerSMB ).

I don't have the ability to move branches between GitHub repositories as that requires repository administrative permissions.

To move this branch to ehuelsmann/LedgerSMB, you'll need to:

  1. Add ehuelsmann/LedgerSMB as a remote in your local clone
  2. Push the branch there, or
  3. Use GitHub's fork and PR workflow

The code changes are all committed and ready - they just need to be pushed to the target repository through standard git operations.

@ehuelsmann
Copy link
Member

Saved on my own repository; closing this branch.

@ehuelsmann ehuelsmann closed this Feb 7, 2026
@ehuelsmann ehuelsmann deleted the copilot/add-totp-authentication-feature branch February 7, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants