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>
94 lines
2.3 KiB
TypeScript
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;
|
|
},
|
|
};
|