Authentication
Efesto does not ship an authentication system. It gives you two hooks and runs them around every request; what happens inside them, JWT, sessions, API keys, OAuth, is your code. This page documents exactly what those hooks are and where they run.
- Express: a global
authMiddlewareyou pass toefesto(), plus a per-method override (_<method>OverrideAuth). - Bun/Elysia: nothing Efesto-specific. You authenticate natively in
setup(e.g.onBeforeHandle), because that hook runs on the root before routes mount.
Anything else (verifying a token, looking up a user, refreshing a session) lives in your middleware, not in the framework.
The global hook
- Express
- Bun/Elysia
You pass authMiddleware to efesto(). It runs before every resolver. To leave an
app open, pass a middleware that just calls next():
import efesto from "efesto";
app.use(
"/api/v1",
efesto({
authMiddleware: (req, res, next) => {
// verify the request here; attach anything you need to `req`
// call next(err) / throw to reject, or next() to allow
next();
},
errorMiddleware: (req, res, next) => next(),
isProduction: false,
options: { absoluteDirRoutes: `${__dirname}/routes` },
})
);
Whatever you attach to req inside this middleware is available in every Efesto
method and in the ABAC check (see ABAC Permissions).
A realistic token-verification middleware is ordinary Express, Efesto does not wrap it:
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) return res.status(401).json({ error: "Missing token" });
try {
req.user = verifyYourToken(token); // your logic / your library
next();
} catch {
res.status(401).json({ error: "Invalid token" });
}
};
The Elysia adapter has no auth hook of its own. Authenticate in setup, which runs
on the root instance before routes are mounted, so it applies to every route:
import efesto from "efesto/elysia";
import { Elysia } from "elysia";
const app = efesto({
isProduction: process.env.NODE_ENV === "production",
routesDir: `${import.meta.dir}/routes`,
prefix: "/api/v1",
setup: (root: Elysia) => {
root.onBeforeHandle(({ headers, set }) => {
const token = headers.authorization?.replace("Bearer ", "");
if (!token) {
set.status = 401;
return { error: "Missing token" };
}
// verify the token here; throw or return a response to reject
});
},
}).listen(2014);
To make user data available to handlers (and to the ABAC ability), use derive:
setup: (root) =>
root.derive(({ headers }) => ({
user: resolveUserFromHeaders(headers), // your logic
})),
Per-endpoint authentication (Express)
Not every endpoint needs the same rule. On the Express stack you override the global
middleware for a single method by declaring _<method>OverrideAuth on the service.
It is a plain middleware and replaces the global one for that verb only:
import { BaseApiService } from "efesto";
import type { Request, Response, NextFunction } from "express";
class Users extends BaseApiService {
constructor() {
super(__filename);
}
// public GET: skip the global auth entirely
_getOverrideAuth = (req: Request, res: Response, next: NextFunction) => {
next();
};
_get(req, res) {
return res.json(listUsers());
}
// POST still uses the global authMiddleware (no override declared)
_post(req, res) {
return res.json(createUser(req.body));
}
}
export default Users;
There is no _overrideAuth equivalent. Per-route auth on the Elysia stack is done
the idiomatic Elysia way (a guard / beforeHandle on the route module, or a scoped
plugin), not through an Efesto convention.
Error handling (Express)
errorMiddleware is the second hook you pass to efesto(). It is wired into the
Express chain so thrown errors and next(err) calls reach it. A pass-through is
valid when you have nothing to handle:
errorMiddleware: (req, res, next) => next();
The ABAC check throws a CASL ForbiddenError when a permission fails, this is the
error you most often handle here. See ABAC Permissions.
What Efesto does not do
These are common needs, but they are your application's responsibility, not framework features. Implement them inside your middleware:
- Token verification / refresh, session stores, API-key lookup, OAuth flows.
- Rate limiting, secure headers, CORS (use standard Express/Elysia middleware).
Once requests are authenticated, authorize them with ABAC.