Core ConceptsAuthentication

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.

MethodEndpointDescriptionOperation
POST/api/auth/loginAuthenticate a userlogin
POST/api/auth/signupRegister a new usersignup
DELETE/api/auth/logoutEnd sessionlogout
POST/api/auth/update-passwordChange passwordupdatePassword
GET/api/users/meGet current usergetMe
PATCH/api/users/meUpdate current userupdateMe
DELETE/api/users/meDelete current userdeleteMe

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:

src/modules/auth/auth.router.ts
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:

@/src/modules/auth/auth.interceptors.ts
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=email

See Authentication Setup for the full allowedUsernames configuration and nested field support.

Logout

DELETE /api/auth/logout

Clears 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_TOKEN

Response:

{
  "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_TOKEN

Response: 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_TOKEN

Cookie-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