Authentication Basics
Authentication flow
A typical authentication flow consists of four steps:
- Token generation - Sign user data into a token using
SignRaworSignServerResponse. - Token storage - Store the token on the client (cookie, header, local storage).
- Token validation - Verify the token when the client makes a request.
- Authorization - Check whether the authenticated user has permission to access the requested resource.
Example authentication flow
import { SignRaw, Authentication } from "@antelopejs/interface-auth";
import { Controller, Post, Get, JSONBody, HTTPResult } from "@antelopejs/interface-api";
class UserController extends Controller("/users") {
@Post("login")
async login(@JSONBody() credentials: { email: string; password: string }) {
// Validate credentials against your data store
const user = await validateUserCredentials(credentials);
// Step 1: Generate a token
const token = await SignRaw(
{ userId: user.id, role: user.role },
{ expiresIn: "1h" },
);
// Step 2: Return token to the client
const result = new HTTPResult(200, {
success: true,
user: { id: user.id, role: user.role },
});
result.addHeader(
"Set-Cookie",
`ANTELOPEJS_AUTH=${token}; HttpOnly; Path=/`,
);
return result;
}
@Get("profile")
async getProfile(
@Authentication() userData: { userId: number; role: string },
) {
// Steps 3 & 4: Token is automatically validated
// If the token is invalid, an error is thrown before this code runs
return { user: await getUserProfile(userData.userId) };
}
}
Authentication sources
An AuthSource function extracts the authentication token from the incoming HTTP request. The default source checks two locations in order:
- Custom header - The
x-antelopejs-authheader - Cookie - The
ANTELOPEJS_AUTHcookie
Create a custom source
Implement the AuthSource type to extract tokens from a different location.
import { CreateAuthDecorator, AuthSource } from "@antelopejs/interface-auth";
import type { IncomingMessage } from "node:http";
const bearerTokenSource: AuthSource = (req: IncomingMessage) => {
const header = req.headers.authorization;
if (header?.startsWith("Bearer ")) {
return header.slice(7);
}
return undefined;
};
const BearerAuth = CreateAuthDecorator({
source: bearerTokenSource,
});
The AuthSource type signature is:
type AuthSource = (
req: IncomingMessage,
res: ServerResponse,
) => string | undefined;
Authentication verifiers
An AuthVerifier function validates the token and extracts its payload. The default verifier uses ValidateRaw, which delegates to the underlying token verification implementation (typically JWT).
Create a custom verifier
import { CreateAuthDecorator, AuthVerifier } from "@antelopejs/interface-auth";
const base64Verifier: AuthVerifier<{ userId: string }> = (data?: string) => {
if (!data) {
throw new Error("No authentication data provided");
}
try {
const decoded = Buffer.from(data, "base64").toString("utf-8");
return JSON.parse(decoded);
} catch {
throw new Error("Invalid authentication data");
}
};
const Base64Auth = CreateAuthDecorator({
authenticator: base64Verifier,
});
The AuthVerifier type signature is:
type AuthVerifier<T = unknown> = (
data?: string,
options?: VerifyOptions,
) => Promise<T> | T;
Authentication validators
An AuthValidator function performs additional checks on the verified data. Validators run after the verifier and can transform the result or throw an error to reject the request.
import { CreateAuthDecorator, AuthValidator } from "@antelopejs/interface-auth";
interface UserPayload {
userId: number;
role: string;
}
const adminValidator: AuthValidator<UserPayload, UserPayload> = (userData) => {
if (!userData || userData.role !== "admin") {
throw new Error("Admin access required");
}
return userData;
};
const AdminOnly = CreateAuthDecorator({
validator: adminValidator,
});
The AuthValidator type signature is:
type AuthValidator<T = unknown, R = unknown> = (
data: T,
) => Promise<R> | R;
Authentication pipeline
The complete authentication pipeline processes the request through three stages:
source(req, res) => authenticator(token, options) => validator(data) => Parameter
Each stage is optional and falls back to the default behavior when not specified. The source extracts the token, the authenticator verifies it, and the validator performs any additional checks before the data is injected into the handler parameter.