Skip to content

Authentication

The Authentication module contains two core endpoints: POST /v1/auth/login and POST /v1/auth/logout. Login works for every UserType (INDIVIDUAL, ORGANIZATION, MORIA) with one DTO and sets the access_token cookie (httpOnly) plus the Token header. The shape of data on the login response varies by user type (e.g. organization users receive extra organization fields).

PropertyValue
Base URL{HOST}/v1
AuthBearer JWT (header Authorization) or cookie access_token
Content-Typeapplication/json
Error envelope{ "message": string | string[], "statusCode": number, "error": string }
ValidationGlobal ValidationPipe · whitelist: true, forbidNonWhitelisted: true · unknown fields → 400
Related modulesUsers, Organizations, Onboarding, Security

The FE starts a session with POST /v1/auth/login using email + password. The server validates credentials via LocalAuthGuard and issues a JWT through three channels at once: the httpOnly cookie access_token, the response header Token, and (for clients that manage their own) the data field. Logout requires a still-valid token — the server clears the cookie and ends the backend session.

MethodPathAuthDescription
POST/v1/auth/loginpublicUniversal login (INDIVIDUAL / ORGANIZATION / MORIA)
POST/v1/auth/logoutbearerEnd the active session and clear cookie

Authenticate a user via email + password. The endpoint covers every UserType — the response data shape varies by user type. The server sets the access_token cookie and the Token response header containing the JWT.

FieldTypeRequiredNotes
emailstringyesIsEmail — valid email format
passwordstringyesIsNotEmpty — user password
{
"email": "admin@moriafund.com",
"password": "Password@123"
}
{
"status": "success",
"statusCode": 200,
"message": "login successful",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@moriafund.com",
"user_type": "organization",
"first_name": "Anas",
"last_name": "Malik",
"phone_number": "+628156489101",
"current_login_user_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "660e8400-e29b-41d4-a716-446655440111",
"name": "Moria Fund",
"org_email": "ops@moriafund.com",
"org_phone_number": "+628123456788",
"status": "active",
"accounts": [
{
"id": "770e8400-e29b-41d4-a716-446655440222",
"name": "Main Business Account",
"balance": 10000.5,
"currency": "IDR",
"owner_type": "ORGANIZATION"
}
]
}
}

For user_type === 'individual' or 'moria', the organization fields (organization_id, name, org_email, org_phone_number, status, accounts) are not sent — only BaseUserData properties. The access_token cookie and Token header are always set on success.

StatusWhen
400 Bad RequestUnknown fields, invalid email format, or empty password
401 UnauthorizedWrong credentials (email/password mismatch)
404 Not FoundOrganization account not yet activated, or deactivated
  • Sets the httpOnly cookie access_token for 3600 seconds.
  • Sends the Token (JWT) header on the response.
  • Backend records the login event for audit.

Log out the authenticated user. The server clears the access_token cookie (clearCookie with the same flags as set) and ends the backend session.

{
"status": "success",
"statusCode": 200,
"message": "logout successful",
"data": {}
}

After this call, the FE must clear any local JWT storage and redirect the user to the login screen.

StatusWhen
401 UnauthorizedNo valid Bearer/cookie (e.g. expired token)
403 ForbiddenAccess denied by guard
  • Cookie access_token is removed on the response (Set-Cookie with Max-Age=0).
  • The backend session is marked ended for the related user.

  • moria — platform superadmin
  • organization — organization admin / member
  • individual — end user

The global response interceptor wraps the controller return as:

{
"status": "success",
"statusCode": 200,
"message": "...",
"data": { }
}
{
"message": "Invalid credentials",
"statusCode": 401,
"error": "Unauthorized"
}

message may be a string or an array of strings (multi-field validation error).

  • 400 — body validation
  • 401 — wrong credentials / invalid token
  • 403 — access denied by guard
  • 404 — organization not yet active
  • 500 — internal — show a generic toast