Files
edr-platform/apps/edr-passenger-web/portal/src/lib/api/auth.ts

94 lines
3.8 KiB
TypeScript

import axios from 'axios';
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000';
// IAM (/v1/auth/*) and Fayda (/auth/fayda/*) endpoints use raw axios instead of
// apiClient: apiClient's response interceptor clears the token and redirects to
// /login on any 401 for non-public URLs — but the IAM returns 401 when the
// current password is wrong on change-password, and OTP failures must surface
// as inline errors, not a logout.
export const iamAuthApi = {
// `identifier` can be an email address or a phone number — the IAM accepts
// either in the `email` field of the forgot-password body.
forgotPassword: (identifier: string) =>
axios.post(`${API_URL}/v1/auth/forgot-password`, { email: identifier }),
// Re-sends the registration verification code for a still-pending account.
resendRegistrationCode: (data: { email: string; phoneNumber: string }) =>
axios.post(`${API_URL}/auth/register/resend-code`, data),
// Completes the forgot-password flow using the link sent via SMS:
// ${FE_BASE_URL}/reset-password?email=..&userId=..&verificationCode=..
resetPassword: (data: {
userId: string;
email: string;
verificationCode: string;
newPassword: string;
confirmPassword: string;
}) => axios.patch(`${API_URL}/v1/auth/set-password`, data),
changePassword: (data: {
oldPassword: string;
newPassword: string;
confirmPassword: string;
}) =>
axios.patch(`${API_URL}/v1/auth/change-password`, data, {
headers: { Authorization: `Bearer ${localStorage.getItem('auth_token')}` },
}),
// --- Staged sign-in (/login) -------------------------------------------------
// Step 1: hand the server one field and let it say which branch follows. `identifier`
// is a phone number or an email; the server works out which.
lookupIdentifier: (identifier: string) =>
axios.post<{
success: boolean;
data: {
status: 'PASSWORD' | 'NEEDS_PASSWORD_SETUP' | 'NOT_FOUND';
method?: 'fayda' | 'pending';
maskedPhone?: string;
};
}>(`${API_URL}/auth/identifier/lookup`, { identifier }),
// Step 2a: SMS the code for an account that exists but has no password yet.
// Always resolves — the server reports { sent: true } even for an unknown identifier.
requestPasswordSetup: (identifier: string) =>
axios.post(`${API_URL}/auth/password-setup/request`, { identifier }),
// Step 2b: redeem the code and set the password. Unlike the older Fayda dance this
// returns a usable session directly, so the user lands signed in rather than back on
// the login form. Same response shape as POST /auth/login.
completePasswordSetup: (data: {
identifier: string;
otp: string;
newPassword: string;
confirmPassword: string;
}) =>
axios.post<{
success: boolean;
data: {
token: string;
refreshToken: string;
user: { id: string; iamUserId: string; email: string | null; passengerId: string };
};
}>(`${API_URL}/auth/password-setup/complete`, data),
faydaRequestPasswordSetup: (phoneNumber: string) =>
axios.post(`${API_URL}/auth/fayda/request-password-setup`, { phoneNumber }),
faydaVerifyAndLogin: (data: { phoneNumber: string; otp: string }) =>
axios.post<{
success: boolean;
data: { token: string; refreshToken: string; requiresPassword: boolean; iamUserId: string };
}>(`${API_URL}/auth/fayda/verify-and-login`, data),
// Bearer token comes from faydaVerifyAndLogin's response, not localStorage —
// the user is not logged into the portal at this point.
setFaydaPassword: (
data: { userId: string; newPassword: string; confirmPassword: string },
token: string,
) =>
axios.patch(`${API_URL}/v1/auth/set-fayda-password`, data, {
headers: { Authorization: `Bearer ${token}` },
}),
};