Files
maternal-app/maternal-web/lib/api/mfa.ts
Andrei e1842f5c1a Add MFA Setup UI in Settings page
Implements user interface for setting up and managing two-factor authentication:

MFA Setup UI Features:
- MFASettings component with full MFA management UI
- TOTP setup dialog with QR code display
- Manual entry code for authenticator apps
- Backup codes display with copy functionality
- Verification code input for TOTP enabling
- Email MFA setup dialog with confirmation
- Disable MFA dialog with warning
- Real-time MFA status indicator (enabled/disabled)
- Method type chip (Authenticator App / Email)

User Experience:
- Step-by-step TOTP setup wizard
- QR code scanning for easy authenticator app setup
- Backup codes shown only once during setup
- Copy-to-clipboard for backup codes
- Visual feedback (success/error alerts)
- Loading states for all async operations
- Animated transitions with Framer Motion

API Integration:
- MFA API client in lib/api/mfa.ts
- Get MFA status
- Setup TOTP with QR code
- Verify and enable TOTP
- Setup Email MFA
- Disable MFA
- Regenerate backup codes

Settings Page Updates:
- Added Security section with MFA settings
- Integrated MFASettings component
- Maintains existing settings page structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-01 21:06:57 +00:00

94 lines
2.3 KiB
TypeScript

import axios from 'axios';
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3020';
export interface MFAStatus {
enabled: boolean;
method?: 'totp' | 'email';
hasBackupCodes: boolean;
}
export interface TOTPSetupResult {
secret: string;
qrCodeUrl: string;
backupCodes: string[];
}
export const mfaApi = {
// Get MFA status
async getStatus(): Promise<MFAStatus> {
const response = await axios.get(`${API_BASE_URL}/api/v1/auth/mfa/status`, {
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
});
return response.data;
},
// Setup TOTP (Google Authenticator)
async setupTOTP(): Promise<TOTPSetupResult> {
const response = await axios.post(
`${API_BASE_URL}/api/v1/auth/mfa/totp/setup`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
}
);
return response.data;
},
// Enable TOTP
async enableTOTP(code: string): Promise<{ success: boolean; message: string }> {
const response = await axios.post(
`${API_BASE_URL}/api/v1/auth/mfa/totp/enable`,
{ code },
{
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
}
);
return response.data;
},
// Setup Email MFA
async setupEmailMFA(): Promise<{ success: boolean; message: string }> {
const response = await axios.post(
`${API_BASE_URL}/api/v1/auth/mfa/email/setup`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
}
);
return response.data;
},
// Disable MFA
async disableMFA(): Promise<{ success: boolean; message: string }> {
const response = await axios.delete(`${API_BASE_URL}/api/v1/auth/mfa`, {
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
});
return response.data;
},
// Regenerate backup codes
async regenerateBackupCodes(): Promise<{ success: boolean; backupCodes: string[] }> {
const response = await axios.post(
`${API_BASE_URL}/api/v1/auth/mfa/backup-codes/regenerate`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
}
);
return response.data;
},
};