import axios from 'axios' const client = axios.create({ baseURL: '/api/fa', timeout: 15000, }) client.interceptors.request.use((config) => { const token = localStorage.getItem('fa_token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) client.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { localStorage.removeItem('fa_token') localStorage.removeItem('fa_user') window.location.href = '/login' } return Promise.reject(error) } ) export default client // ── 인증 / 2FA(OTP) — /api/fa/auth (client baseURL '/api/fa' → 상대 '/auth/...') ────────── // 응답은 봉투 없이 flat( res.data ). login: OTP off → { twofa:"false", token, username, role, workstationCode }, // OTP on → { twofa:"true", verifyToken, verifyMethod:(OTP|OTP_SETUP), secret?, otpAuthUri?, qrImage? }. // 보안 불변: setup/OTP_SETUP 응답의 secret/qrImage 는 화면 표시용만 — 로그/저장 절대 금지. export const login = (username: string, password: string) => client.post('/auth/login', { username, password }) // 로그인 2단계: verify-token + Authenticator 6자리 → access 발급. export const verifyOtp = (verifyToken: string, code: string) => client.post('/auth/verify-otp', { verifyToken, code }) // 내 정보(access 토큰). flat { username, role }. export const getMe = () => client.get('/auth/me') // 마이페이지 OTP 등록/재설정/해제 + 비밀번호 변경(access 토큰 필요). // otpSetup 응답(flat OtpSetupResponse: { secret, otpAuthUri, qrImage })은 등록 순간에만 노출. export const otpSetup = () => client.post('/auth/otp/setup') export const otpConfirm = (code: string) => client.post('/auth/otp/confirm', { code }) export const otpDisable = () => client.post('/auth/otp/disable') export const changePassword = (currentPassword: string, newPassword: string) => client.post('/auth/change-password', { currentPassword, newPassword })