Skip to main content

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.

What Efesto actually provides
  • Express: a global authMiddleware you pass to efesto(), 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​

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" });
}
};

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;
Elysia

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.