veza/apps/web/src/services/2fa-service.ts

57 lines
1.7 KiB
TypeScript

import { apiClient } from './api/client';
import { requireFeature, FEATURES } from '@/config/features';
interface TwoFactorSetupResponse {
secret: string;
qr_code_url: string;
recovery_codes: string[];
}
interface TwoFactorStatus {
enabled: boolean;
}
/**
* Two-Factor Authentication Service
*
* Backend endpoints: /auth/2fa/setup, /auth/2fa/verify, /auth/2fa/disable, /auth/2fa/status
*
* @see FEATURES.TWO_FACTOR_AUTH
*/
class TwoFactorService {
async getStatus(): Promise<TwoFactorStatus> {
requireFeature('TWO_FACTOR_AUTH');
// apiClient unwraps { success, data } format automatically
const response = await apiClient.get<TwoFactorStatus>('/auth/2fa/status');
return response.data;
}
async setup(): Promise<TwoFactorSetupResponse> {
requireFeature('TWO_FACTOR_AUTH');
// apiClient unwraps { success, data } format automatically
const response =
await apiClient.post<TwoFactorSetupResponse>('/auth/2fa/setup');
return response.data;
}
async verify(secret: string, code: string): Promise<void> {
requireFeature('TWO_FACTOR_AUTH');
// Backend expects { secret, code } and returns { success: true, data: { message: "2FA enabled successfully" } }
await apiClient.post('/auth/2fa/verify', { secret, code });
}
async disable(password: string): Promise<void> {
requireFeature('TWO_FACTOR_AUTH');
// Backend expects { password } and returns { success: true, data: { message: "2FA disabled successfully" } }
await apiClient.post('/auth/2fa/disable', { password });
}
}
export const twoFactorService = new TwoFactorService();
/**
* Check if 2FA is enabled (for UI conditional rendering)
*/
export function is2FAEnabled(): boolean {
return FEATURES.TWO_FACTOR_AUTH;
}