Multi-Factor Authentication (MFA) Setup Guide

Configure TOTP-based multi-factor authentication for enhanced account security

Audience: All users (Analysts, Reviewers, Admins), Security Officers

NIST Controls: IA-2(1), IA-5(1), IA-6

Overview

RayRay implements Time-based One-Time Password (TOTP) multi-factor authentication compliant with RFC 6238. This adds a critical second layer of security beyond your password, significantly reducing the risk of unauthorized access even if credentials are compromised.

How TOTP Works

┌─────────────────┐         ┌─────────────────┐
│   Authenticator │         │    RayRay       │
│      App        │         │    Server       │
└────────┬────────┘         └────────┬────────┘
         │                           │
         │  Shared Secret (Setup)    │
         │ ◄─────────────────────────│
         │                           │
         │  Time-based Algorithm     │
         │  (HMAC-SHA1 + 30s window) │
         │                           │
         │  6-digit OTP              │
         │ ─────────────────────────►│
         │                           │ Verify
         │                           │ (same algorithm)
         │                           │
         │       Access Granted      │
         │ ◄─────────────────────────│

Both the authenticator app and RayRay server compute the same OTP using the shared secret and current time. The code changes every 30 seconds, providing strong protection against replay attacks.

Technical Details

ParameterValueStandard
AlgorithmHMAC-SHA1RFC 6238
Code Length6 digitsRFC 6238
Time Step30 secondsRFC 6238
Secret EncodingBase32RFC 4648
Issuer NameRayRay EnterpriseGoogle Authenticator spec

Supported Authenticator Apps

RayRay's TOTP implementation is compatible with any RFC 6238-compliant authenticator. The following apps are recommended and tested:

AppPlatformFeaturesRecommendation
Google AuthenticatoriOS, AndroidSimple, widely supported, offlineGeneral users
Microsoft AuthenticatoriOS, AndroidCloud backup, push notifications for Microsoft accountsMicrosoft 365 environments
AuthyiOS, Android, DesktopCloud backup, multi-device syncUsers with multiple devices
1PasswordiOS, Android, DesktopIntegrated with password manager1Password users
Bitwarden AuthenticatoriOS, AndroidOpen source, integrates with Bitwarden vaultBitwarden users

Security Note: Apps with cloud backup features (Authy, Microsoft Authenticator) provide convenience but introduce additional attack surface. For maximum security, consider using offline-only authenticators like Google Authenticator without cloud sync.

Step-by-Step Setup Instructions

Prerequisites

  • A RayRay account with Analyst, Reviewer, or Admin role
  • An authenticator app installed on your mobile device
  • Access to the RayRay Settings page

Step 1: Navigate to Security Settings

  1. Log in to RayRay at /login
  2. Click your user avatar in the top-right corner
  3. Select Settings from the dropdown menu
  4. Scroll to the Security section

Screenshot placeholder: Settings page showing Security section with MFA controls

Step 2: Initialize MFA Setup

  1. Click Enable MFA button
  2. The system will generate a unique TOTP secret and QR code
  3. Important: Keep this page open until setup is complete

Behind the scenes, the system:

// API call: POST /api/users/mfa/setup
// Response:
{
  "secret": "JBSWY3DPEHPK3PXP",  // Base32 encoded
  "qr_code": "data:image/png;base64,..."  // QR code image
}

// The QR code encodes the provisioning URI:
otpauth://totp/RayRay%20Enterprise:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=RayRay%20Enterprise

Step 3: Scan QR Code

  1. Open your authenticator app on your mobile device
  2. Tap the + or Add Account button
  3. Select Scan QR code or Scan barcode
  4. Point your camera at the QR code displayed on screen
  5. The app will automatically add "RayRay Enterprise" with your email

Screenshot placeholder: QR code being scanned by Google Authenticator app

Manual Entry Alternative: If you cannot scan the QR code, you can manually enter the secret key shown below the QR code. In your authenticator app, select "Enter a setup key" and input:

  • Account: Your email address
  • Key: The 16-character secret (e.g., JBSWY3DPEHPK3PXP)
  • Type: Time-based

Step 4: Verify and Enable

  1. Your authenticator app will display a 6-digit code
  2. Enter this code in the Verification Code field
  3. Click Verify and Enable
  4. You should see a success message confirming MFA is now active

API interaction:

// API call: POST /api/users/mfa/verify
{
  "otp": "123456",
  "secret": "JBSWY3DPEHPK3PXP"
}

// Success response:
{
  "message": "MFA enabled successfully"
}

Step 5: Save Recovery Codes (Recommended)

Critical: If you lose access to your authenticator device, you will be locked out of your account. We recommend saving recovery codes or noting your secret key in a secure password manager.

Recommended recovery options:

  • Store the secret key in a password manager (1Password, Bitwarden, etc.)
  • Write down the secret key and store in a secure physical location
  • Set up the same account on a secondary device (Authy supports this)

Login Flow with MFA

Once MFA is enabled, your login flow changes as follows:

Standard Login

  1. Navigate to /login
  2. Enter your email and password
  3. Click Sign In
  4. New: You'll be prompted for your MFA code
  5. Open your authenticator app and enter the current 6-digit code
  6. Click Verify to complete login

Token flow:

// Step 1: Password login
POST /api/users/login
Response: {
  "access_token": "jwt_token_here",
  "mfa_required": true,  // Indicates MFA challenge needed
  "user": { ... }
}

// Step 2: MFA verification
POST /api/users/mfa/challenge
{
  "otp": "123456"
}
Response: {
  "access_token": "new_jwt_with_mfa_claim",
  "token_type": "bearer"
}

// The new token includes "mfa": true in its claims
{
  "sub": "user@example.com",
  "role": "analyst",
  "mfa": true,
  "exp": 1710000000
}

Recovery Procedures

Lost Device

If you lose access to your authenticator device, contact your system administrator or IT helpdesk. They can:

  1. Verify your identity through alternate means
  2. Reset your MFA configuration
  3. You will then need to set up MFA again with a new device

For Admins: To reset a user's MFA, access the user management interface and clear their MFA secret:

// Admin action: Disable MFA for user
// This is typically done through the admin UI
// The user's mfa_enabled and mfa_secret fields are cleared

New Device Setup

To move MFA to a new device:

  1. Log in with your old device (if still accessible)
  2. Go to Settings → Security
  3. Click Disable MFA
  4. Follow the setup instructions above with your new device

With Authy or similar: If using Authy with multi-device sync, simply install the app on your new device and sync your accounts.

Account Lockout

After multiple failed MFA attempts, your account may be temporarily locked. Wait 15 minutes and try again, or contact your administrator for assistance.

Admin MFA Management

User MFA Status

Administrators can view MFA status for all users:

// API: GET /api/users/ (Admin only)
[
  {
    "id": 1,
    "email": "analyst@example.com",
    "role": "analyst",
    "mfa_enabled": true,
    ...
  },
  {
    "id": 2,
    "email": "reviewer@example.com",
    "role": "reviewer",
    "mfa_enabled": false,
    ...
  }
]

Resetting User MFA

When a user loses their device or encounters issues, admins can reset their MFA:

  1. Navigate to User Management
  2. Find the affected user
  3. Click Reset MFA
  4. Confirm the action
  5. Notify the user they need to set up MFA again

Audit Trail: All MFA administrative actions are logged in the audit system with event type mfa_reset, including the admin user who performed the action.

MFA Enforcement Policies

Recommended Policies

RoleMFA RequirementRationale
AdminMandatoryFull system access, user management
ReviewerMandatoryCan commit AI extractions to database
AnalystRecommendedCan upload documents and create drafts
ObserverRecommendedRead-only access

NIST Control Alignment

ControlRequirementImplementation
IA-2(1)Multi-Factor Authentication for privileged accountsTOTP-based MFA mandatory for Admin/Reviewer roles
IA-5(1)Password-Based AuthenticationBcrypt hashing + MFA for defense in depth
IA-6Authenticator FeedbackClear success/failure messages, no OTP exposure in logs

Future: Organization-Wide Enforcement

A planned feature will allow organization administrators to enforce MFA for all users above a specified role threshold. This will include:

  • Grace period for existing users to enable MFA
  • Automatic prompts at login for users without MFA
  • Admin dashboard showing MFA compliance rates

API Endpoints Reference

MethodEndpointDescriptionAuth Required
POST/api/users/mfa/setupGenerate new TOTP secret and QR codeYes
POST/api/users/mfa/verifyVerify OTP and enable MFA for accountYes
POST/api/users/mfa/challengeVerify OTP during login flowYes

Setup Endpoint

POST /api/users/mfa/setup
Authorization: Bearer {jwt_token}

Response 200:
{
  "secret": "JBSWY3DPEHPK3PXP",
  "qr_code": "data:image/png;base64,iVBORw0KGgo..."
}

Response 401:
{
  "detail": "Could not validate credentials"
}

Verify Endpoint

POST /api/users/mfa/verify
Authorization: Bearer {jwt_token}
Content-Type: application/json

Request Body:
{
  "otp": "123456",
  "secret": "JBSWY3DPEHPK3PXP"
}

Response 200:
{
  "message": "MFA enabled successfully"
}

Response 400:
{
  "detail": "Invalid OTP code"
}

Challenge Endpoint

POST /api/users/mfa/challenge
Authorization: Bearer {jwt_token}
Content-Type: application/json

Request Body:
{
  "otp": "123456"
}

Response 200:
{
  "access_token": "<JWT_ACCESS_TOKEN>",
  "token_type": "bearer"
}

Response 401:
{
  "detail": "Invalid MFA code"
}

Troubleshooting

Common Issues

IssuePossible CausesSolution
OTP always rejectedDevice time driftEnsure device time is set to automatic; allow +/- 1 window
QR code not scanningScreen brightness, app permissionsIncrease brightness; try manual secret entry
"Invalid OTP code" after setupEntered wrong code or secretEnsure using the correct account in authenticator; verify secret matches
Code expires too quicklyNormal behaviorCodes refresh every 30 seconds; enter the current code promptly
Lost access to deviceDevice lost, stolen, or resetContact administrator to reset MFA

Time Synchronization

TOTP relies on accurate time. If your device clock drifts by more than 30 seconds, codes may be rejected. RayRay allows a small tolerance window, but for best results:

  • Enable automatic time sync on your mobile device
  • Ensure your device's timezone is correct
  • If issues persist, try refreshing the authenticator app

Error Messages

Error MessageMeaningAction
"Invalid OTP code"OTP does not match expected valueCheck time sync; verify correct account
"MFA secret required for setup"Verify called without secretCall /mfa/setup first to get secret
"MFA not enabled for this user"Challenge called for non-MFA userComplete MFA setup first
"Could not validate credentials"Token invalid or expiredLog in again to get fresh token

Implementation Details

For developers and security auditors, here are the key implementation files:

apps/api/
├── app/services/
│   └── mfa_service.py     # TOTP implementation using pyotp
├── app/routers/
│   └── users.py           # MFA endpoints (/mfa/setup, /verify, /challenge)
└── app/models/
    └── audit.py           # User model with mfa_enabled, mfa_secret

Key dependencies:
- pyotp: RFC 6238 TOTP implementation
- qrcode: QR code generation
- Python standard library: base64, io

Secret Storage

MFA secrets are stored in the database with the user record. In production deployments, ensure:

  • Database encryption at rest
  • TLS for all database connections
  • Audit logging of secret access

Future Enhancement: Consider implementing secret encryption at the application layer using a key management service (KMS) for defense in depth.

Related Documentation