Kulcare Docs

Two-Factor Authentication (2FA) with Device Management Flow

Overview

This document describes the complete implementation of Two-Factor Authentication (2FA) with device trust management in the Kulcare platform. The system supports three 2FA methods (TOTP, SMS, EMAIL) and allows users to trust devices to bypass 2FA on subsequent logins.

Table of Contents

  1. Key Features
  2. Architecture Components
  3. 2FA Setup Flow
  4. Login Flow with 2FA
  5. Device Trust Management
  6. Technical Implementation Details
  7. User Experience Enhancements
  8. Security Considerations
  9. Visual Flow Diagram

Key Features

Supported 2FA Methods

  • TOTP (Time-based One-Time Password): Using authenticator apps like Google Authenticator
  • SMS: Verification codes sent via text message
  • EMAIL: Verification codes sent via email

Device Trust Features

  • Persistent device identification using UUID
  • "Remember this device" option during login
  • Device trust survives logout (UUID preserved)
  • Centralized device management interface
  • Trust/untrust devices from settings

Architecture Components

Frontend Components

  1. TwoFactorSetup (/components/settings/TwoFactorSetup.tsx)

    • Handles 2FA method selection
    • Manages setup flow for each method
    • Shows device trust consent modal for SMS/EMAIL
  2. TwoFactorVerification (/components/auth/TwoFactorVerification.tsx)

    • OTP input interface during login
    • "Remember this device" checkbox for SMS/EMAIL
    • Recovery code support
  3. DeviceManagement (/components/settings/DeviceManagement.tsx)

    • Lists all devices (trusted and untrusted)
    • Shows device details (name, browser, last IP)
    • Trust/revoke trust controls
  4. DeviceTrustConsentModal (/components/settings/DeviceTrustConsentModal.tsx)

    • Explains device trust feature during setup
    • Warns about potential re-login requirement

Services and APIs

  1. deviceApi.ts

    • getDevices(): List all user devices
    • trustDevice(): Mark device as trusted
    • revokeTrust(): Remove device trust
  2. twoFactorApi.ts

    • enable(): Enable 2FA method
    • confirm(): Confirm setup with code
    • verify(): Verify 2FA during login with device trust option
  3. deviceInfo.ts (api-client package)

    • Generates and persists device UUID
    • Collects device information (browser, OS, version)
    • Creates browser fingerprint for web devices

2FA Setup Flow

Step 1: Method Selection

User navigates to Settings > Security > Two-Factor Authentication
  ↓
Selects method: TOTP, SMS, or EMAIL
  ↓
For SMS/EMAIL: Device Trust Consent Modal appears
  - Explains device trust feature
  - Notes possible re-login requirement
  ↓
User proceeds with setup

Step 2: Method-Specific Setup

TOTP Setup:

  1. Backend generates QR code and secret
  2. User scans QR with authenticator app
  3. User enters 6-digit code to confirm
  4. Recovery codes displayed

SMS Setup:

  1. Shows masked phone number
  2. SMS automatically sent
  3. User enters verification code
  4. Recovery codes displayed

EMAIL Setup:

  1. Shows masked email address
  2. Email automatically sent
  3. User enters verification code
  4. Recovery codes displayed

Step 3: Recovery Codes

  • 5 recovery codes generated
  • User must save/download codes
  • Confirmation required before proceeding

Login Flow with 2FA

First Login (No Device Trust)

1. User enters phone + password
   ↓
2. Backend checks if 2FA enabled
   ↓
3. If enabled: Returns temp_auth_token + 2FA method
   ↓
4. Frontend shows 2FA verification screen
   ↓
5. For SMS/EMAIL: "Remember this device" checkbox shown
   ↓
6. User enters code + optionally checks "Remember"
   ↓
7. Frontend sends:
   - code
   - method
   - trust_device: true/false
   - device_uuid
   - device_details
   ↓
8. Backend verifies code
   ↓
9. If trust_device=true: Device registered as trusted
   ↓
10. Auth tokens returned
   ↓
11. User may need to re-login once (expected behavior)

Subsequent Login (Device Trusted)

1. User enters phone + password
   ↓
2. Frontend sends login with device_details
   ↓
3. Backend recognizes trusted device UUID
   ↓
4. 2FA skipped automatically
   ↓
5. Direct login to dashboard

Device Trust Management

Device Identification

Each device is identified by:

  • device_uuid: Persistent UUID stored in localStorage
  • device_type: Always "web" for browser apps
  • device_name: Browser name + OS (e.g., "Chrome on Linux")
  • app_type: "cms" for the CMS application
  • browser_fingerprint: JSON with user agent, screen size, timezone

Device UUID Persistence

// UUID Generation (deviceInfo.ts)
function getDeviceUUID(): string {
  const STORAGE_KEY = 'kulcare-device-uuid'
  let uuid = localStorage.getItem(STORAGE_KEY)
  
  if (!uuid) {
    uuid = generateUUID()
    localStorage.setItem(STORAGE_KEY, uuid)
  }
  
  return uuid
}

Logout Behavior

The device UUID is specifically preserved during logout:

// Auth store logout
keys.forEach(key => {
  if (key === "kulcare-device-uuid") {
    // Preserve device UUID for trusted device functionality
    return
  }
  // Remove other localStorage items
})

Device Management UI

The DeviceManagement component shows:

  • All devices with trust status
  • Trust indicators (green for trusted, gray for untrusted)
  • Device details (browser, version, last IP)
  • Trust/Revoke buttons
  • Summary cards (total trusted/untrusted)

Technical Implementation Details

API Request Structure

Login with Device Details:

{
  "user_signin_form": {
    "country_code": "+1",
    "phone_number": "1234567890",
    "password": "password",
    "platform": "web"
  },
  "device_details": {
    "device_uuid": "uuid-here",
    "device_type": "web",
    "device_token": "uuid-here",
    "device_name": "Chrome on macOS",
    "device_version": "Chrome 120.0",
    "app_version": "1.0.0",
    "app_type": "cms",
    "browser_fingerprint": "{...}"
  }
}

2FA Verification with Trust:

{
  "code": "123456",
  "method": "SMS",
  "trust_device": true,
  "device_uuid": "uuid-here",
  "device_details": { /* same as above */ }
}

State Management

  • Device UUID: Stored in localStorage
  • Auth tokens: Managed by Zustand auth store
  • Device list: Fetched on demand, not cached

User Experience Enhancements

Warning Messages

  1. During 2FA Setup (SMS/EMAIL):

    • "Note: You may need to sign in again after OTP verification when first enabling this feature."
  2. During Login (when checkbox checked):

    • "Note: You may need to sign in once more after verification"

Visual Indicators

  • Trusted devices: Green background with shield check icon
  • Untrusted devices: Gray background with shield off icon
  • Current device: "(This device)" label
  • Trust status badges

Error Handling

  • "Devices do not exist" API error handled gracefully
  • Empty device list shows helpful message
  • Network errors show toast notifications

Security Considerations

  1. Device UUID Persistence: Survives logout but not browser data clearing
  2. Trust Revocation: Invalidates all sessions on that device
  3. IP Tracking: Last trusted IP stored for security monitoring
  4. No Silent Trust: User must explicitly check "Remember this device"
  5. Recovery Codes: One-time use, securely generated

Visual Flow Diagram

Device Management Flow

Summary

The 2FA with device management system provides a secure yet user-friendly authentication experience. Key achievements:

  1. Persistent Device Identity: Device UUID survives logout
  2. User Control: Explicit consent for device trust
  3. Transparent UX: Clear warnings about re-login requirement
  4. Comprehensive Management: Full device visibility and control
  5. Secure Implementation: Follows security best practices

The implementation balances security requirements with user convenience, allowing trusted devices to bypass 2FA while maintaining full user control over device trust status.

On this page