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
| Parameter | Value | Standard |
|---|---|---|
| Algorithm | HMAC-SHA1 | RFC 6238 |
| Code Length | 6 digits | RFC 6238 |
| Time Step | 30 seconds | RFC 6238 |
| Secret Encoding | Base32 | RFC 4648 |
| Issuer Name | RayRay Enterprise | Google Authenticator spec |
Supported Authenticator Apps
RayRay's TOTP implementation is compatible with any RFC 6238-compliant authenticator. The following apps are recommended and tested:
| App | Platform | Features | Recommendation |
|---|---|---|---|
| Google Authenticator | iOS, Android | Simple, widely supported, offline | General users |
| Microsoft Authenticator | iOS, Android | Cloud backup, push notifications for Microsoft accounts | Microsoft 365 environments |
| Authy | iOS, Android, Desktop | Cloud backup, multi-device sync | Users with multiple devices |
| 1Password | iOS, Android, Desktop | Integrated with password manager | 1Password users |
| Bitwarden Authenticator | iOS, Android | Open source, integrates with Bitwarden vault | Bitwarden 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
- Log in to RayRay at
/login - Click your user avatar in the top-right corner
- Select Settings from the dropdown menu
- Scroll to the Security section
Screenshot placeholder: Settings page showing Security section with MFA controls
Step 2: Initialize MFA Setup
- Click Enable MFA button
- The system will generate a unique TOTP secret and QR code
- 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%20EnterpriseStep 3: Scan QR Code
- Open your authenticator app on your mobile device
- Tap the + or Add Account button
- Select Scan QR code or Scan barcode
- Point your camera at the QR code displayed on screen
- 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
- Your authenticator app will display a 6-digit code
- Enter this code in the Verification Code field
- Click Verify and Enable
- 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
- Navigate to
/login - Enter your email and password
- Click Sign In
- New: You'll be prompted for your MFA code
- Open your authenticator app and enter the current 6-digit code
- 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:
- Verify your identity through alternate means
- Reset your MFA configuration
- 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 clearedNew Device Setup
To move MFA to a new device:
- Log in with your old device (if still accessible)
- Go to Settings → Security
- Click Disable MFA
- 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:
- Navigate to User Management
- Find the affected user
- Click Reset MFA
- Confirm the action
- 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
| Role | MFA Requirement | Rationale |
|---|---|---|
| Admin | Mandatory | Full system access, user management |
| Reviewer | Mandatory | Can commit AI extractions to database |
| Analyst | Recommended | Can upload documents and create drafts |
| Observer | Recommended | Read-only access |
NIST Control Alignment
| Control | Requirement | Implementation |
|---|---|---|
IA-2(1) | Multi-Factor Authentication for privileged accounts | TOTP-based MFA mandatory for Admin/Reviewer roles |
IA-5(1) | Password-Based Authentication | Bcrypt hashing + MFA for defense in depth |
IA-6 | Authenticator Feedback | Clear 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
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST | /api/users/mfa/setup | Generate new TOTP secret and QR code | Yes |
POST | /api/users/mfa/verify | Verify OTP and enable MFA for account | Yes |
POST | /api/users/mfa/challenge | Verify OTP during login flow | Yes |
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
| Issue | Possible Causes | Solution |
|---|---|---|
| OTP always rejected | Device time drift | Ensure device time is set to automatic; allow +/- 1 window |
| QR code not scanning | Screen brightness, app permissions | Increase brightness; try manual secret entry |
| "Invalid OTP code" after setup | Entered wrong code or secret | Ensure using the correct account in authenticator; verify secret matches |
| Code expires too quickly | Normal behavior | Codes refresh every 30 seconds; enter the current code promptly |
| Lost access to device | Device lost, stolen, or reset | Contact 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 Message | Meaning | Action |
|---|---|---|
"Invalid OTP code" | OTP does not match expected value | Check time sync; verify correct account |
"MFA secret required for setup" | Verify called without secret | Call /mfa/setup first to get secret |
"MFA not enabled for this user" | Challenge called for non-MFA user | Complete MFA setup first |
"Could not validate credentials" | Token invalid or expired | Log 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, ioSecret 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
- Authentication - OAuth 2.0 + JWT implementation
- Compliance - NIST control mappings
- API Reference - Complete API documentation