Routes
Arkos provides a built-in authentication system with JWT and Role-Based Access Control (RBAC). Once configured, it automatically exposes the following endpoints — no route definitions needed.
| Method | Endpoint | Description | Operation |
|---|---|---|---|
| POST | /api/auth/login | Authenticate a user | login |
| POST | /api/auth/signup | Register a new user | signup |
| DELETE | /api/auth/logout | End session | logout |
| POST | /api/auth/update-password | Change password | updatePassword |
| GET | /api/users/me | Get current user | getMe |
| PATCH | /api/users/me | Update current user | updateMe |
| DELETE | /api/users/me | Delete current user | deleteMe |
Authentication requires setup before these endpoints are active. See Authentication Setup for configuration, User Model requirements, and RBAC options.
Configuring Authentication Routes
Every auth endpoint accepts the same configuration object used in ArkosRouter — disable routes, add rate limiting, and more via the config export in src/modules/auth/auth.router.ts where each key maps to the operation name from the table above:
import { ArkosRouter, RouterConfig } from "arkos";
import UpdateMeSchema from "@/src/modules/auth/schemas/update-me.schema"
export const config: RouterConfig = {
login: { rateLimit: { windowMs: 15 * 60_000, max: 10 } },
signup: { disabled: true },
getMe: { rateLimit: { windowMs: 15 * 60_000, max: 30 } },
deleteMe: { disabled: true },
udpateMe: { validation: { body: UpdateMeSchema } },
udpatePassword: { rateLimit: { windowMs: 15 * 60_000, max: 10 } },
};
const router = ArkosRouter();
export default router;See the full configuration object reference at ArkosRouter Configuration Object.
Intercepting Authentication Requests
Every authentication endpoint can be intercepted — run logic before or after any operation without replacing built-in behavior. For example, to send a verification email after signup:
import { ArkosRequest, ArkosResponse, ArkosNextFunction } from "arkos";
export const afterSignup = [
async (req: ArkosRequest, res: ArkosResponse, next: ArkosNextFunction) => {
const user = res.locals.data.data;
emailService.sendVerificationEmail(user.email).catch(console.error);
next();
},
];See Interceptors for the full list of available auth hooks.
Sending Requests
Signup
POST /api/auth/signup
Content-Type: application/json{
"username": "john_doe",
"password": "SecurePassword123!",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe"
}Response:
{
"data": {
"id": "abc123",
"username": "john_doe",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"isActive": true,
"createdAt": "2025-04-05T14:23:45.123Z"
}
}Login
POST /api/auth/login
Content-Type: application/json{
"username": "john_doe",
"password": "SecurePassword123!"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"id": "abc123",
"username": "john_doe",
"email": "john@example.com"
}
}Depending on your sendAccessTokenThrough configuration, the token is set as a cookie, included in the response body, or both (default). See Authentication Setup for configuration.
Logging in with different fields
By default users log in with username. Arkos supports logging in with other fields like email, or even nested relation fields like profile.nickname.
POST /api/auth/login
Content-Type: application/json{
"email": "john@example.com",
"password": "SecurePassword123!"
}When using a non-default field, pass usernameField as a query parameter:
POST /api/auth/login?usernameField=emailSee Authentication Setup for the full allowedUsernames configuration and nested field support.
Logout
DELETE /api/auth/logoutClears the authentication cookie and invalidates the session. Response: 204 No Content.
Update Password
POST /api/auth/update-password
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN{
"currentPassword": "OldPassword123!",
"newPassword": "NewSecurePassword123!"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"id": "abc123",
"username": "john_doe"
}
}Since v1.5.0, Arkos automatically re-authenticates the user after a password update and returns a fresh token — no need to log in again.
Get Current User
GET /api/users/me
Authorization: Bearer YOUR_API_TOKENResponse:
{
"data": {
"id": "abc123",
"username": "john_doe",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"isActive": true,
"createdAt": "2025-04-05T14:23:45.123Z"
}
}Update Current User
PATCH /api/users/me
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN{
"firstName": "John Updated",
"email": "newemail@example.com"
}Response:
{
"data": {
"id": "abc123",
"username": "john_doe",
"email": "newemail@example.com",
"firstName": "John Updated",
"updatedAt": "2025-04-05T15:30:12.456Z"
}
}Delete Current User
DELETE /api/users/me
Authorization: Bearer YOUR_API_TOKENResponse: 204 No Content
Sending the Token
Authenticated endpoints accept the token either via the Authorization header or automatically via cookies (set on login).
Authorization header:
GET /api/users/me
Authorization: Bearer YOUR_API_TOKENCookie-based (set automatically on login):
fetch("/api/users/me", {
credentials: "include",
});Error Responses
// 401 - Invalid or missing token
{
"code": "Unauthorized",
"message": "You are not logged in. Please log in to get access."
}
// 403 - Authenticated but insufficient permissions
{
"code": "Forbidden",
"message": "You do not have permission to perform this action."
}
// 400 - Wrong current password
{
"code": "InvalidCredentials",
"message": "Current password is incorrect."
}For the full list of possible errors, see Error Handling.
Customizing Authentication Routes
- Interceptors — Run logic before or after any auth endpoint
- Authentication Setup — Configure JWT, User Model, and RBAC
- Static RBAC — Role-based access control via enums
- Dynamic RBAC — Runtime-configurable permissions via database
- Permissions — Fine-grained access control