101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
import type { ChallengeResponse, IdentifyResponse, RedirectResponse, SessionStatus, StartResponse, VerifyResponse } from '@KTXC/types/authenticationTypes';
|
|
import { fetchWrapper } from '@KTXC/utils/helpers/fetch-wrapper';
|
|
|
|
export const authenticationService = {
|
|
/**
|
|
* Initialize authentication - get session and available methods
|
|
*/
|
|
async start(): Promise<StartResponse> {
|
|
return fetchWrapper.get('/auth/start', undefined, { skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Identify user - stores identity in session for identity-first flow
|
|
* Returns tenant-wide methods (no user-specific filtering to prevent enumeration)
|
|
*
|
|
* @param session - Session ID from start
|
|
* @param identity - User identity (email/username)
|
|
*/
|
|
async identify(session: string, identity: string): Promise<IdentifyResponse> {
|
|
return fetchWrapper.post('/auth/identify', {
|
|
session,
|
|
identity,
|
|
}, { skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Verify a factor (primary or secondary)
|
|
*
|
|
* @param session - Session ID from init
|
|
* @param method - Provider/method ID (e.g., 'default', 'totp')
|
|
* @param response - User's response (password, code, etc.)
|
|
* @param identity - User identity for credential-based auth (email/username)
|
|
*/
|
|
async verify(
|
|
session: string,
|
|
method: string,
|
|
response: string,
|
|
identity?: string
|
|
): Promise<VerifyResponse> {
|
|
return fetchWrapper.post('/auth/verify', {
|
|
session,
|
|
method,
|
|
response,
|
|
...(identity && { identity }),
|
|
}, { autoRetry: false, skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Begin redirect-based authentication (OIDC/SAML)
|
|
*/
|
|
async beginRedirect(
|
|
session: string,
|
|
method: string,
|
|
returnUrl: string = '/'
|
|
): Promise<RedirectResponse> {
|
|
return fetchWrapper.post('/auth/redirect', {
|
|
session,
|
|
method,
|
|
return_url: returnUrl,
|
|
}, { skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Start a challenge for methods that require it (SMS, email, TOTP)
|
|
*/
|
|
async beginChallenge(session: string, method: string): Promise<ChallengeResponse> {
|
|
return fetchWrapper.post('/auth/challenge', {
|
|
session,
|
|
method,
|
|
}, { skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Get current session status
|
|
*/
|
|
async getStatus(session: string): Promise<SessionStatus> {
|
|
return fetchWrapper.get(`/auth/status?session=${encodeURIComponent(session)}`, undefined, { skipLogoutOnError: true });
|
|
},
|
|
|
|
/**
|
|
* Cancel authentication session
|
|
*/
|
|
async cancelSession(session: string): Promise<void> {
|
|
await fetchWrapper.delete(`/auth/session?session=${encodeURIComponent(session)}`);
|
|
},
|
|
|
|
/**
|
|
* Refresh access token
|
|
*/
|
|
async refresh(): Promise<void> {
|
|
await fetchWrapper.post('/auth/refresh', {});
|
|
},
|
|
|
|
/**
|
|
* Logout
|
|
*/
|
|
async logout(): Promise<void> {
|
|
await fetchWrapper.post('/auth/logout', {});
|
|
},
|
|
};
|