Authentication
@rapidrest/service-core ships one authentication strategy out of the box, JWTStrategy. It doesn't issue tokens or run a login flow, it verifies a token that was already issued somewhere else, by your own login endpoint, by a separate auth service, by whatever identity provider your organization already uses. That's a deliberate choice: a backend service that only knows how to verify a token, and has no opinion on how one gets minted, stays interoperable with whatever the rest of your system already does for login.
The default strategy
A single strategy is designated the global default, used to authenticate every request the server handles, whether or not a given endpoint actually requires it. Freshly scaffolded projects are already configured to use JWTStrategy:
// src/config.ts
auth: {
strategy: "auth.JWTStrategy",
}
Change it by editing auth.strategy in your configuration.
Requiring auth on an endpoint
Authentication happens on every request regardless, but by default nothing is done with the result, an endpoint with no auth requirement runs identically whether the caller sent a token or not. @Auth is what makes a specific endpoint actually require it:
@Auth(['jwt'])
@Get()
public endpointFunc() {
// only reached if 'jwt' authentication succeeded
}
@Auth takes a list of strategy names to attempt, at least one has to succeed for the request to be considered authenticated. Fail every strategy on an endpoint that requires auth, and the request never reaches your handler at all, it's rejected with 401 before that, the same error response shape any other ApiError produces, { message: "Invalid or missing authentication token.", status: 401, code: "api-101" }. That message doesn't distinguish a missing token from an invalid or expired one, on purpose, giving an attacker a different error for "no token" versus "wrong token" is a small but real information leak.
Optional authentication
@Auth takes a second argument, require, defaulting to true. Pass false and the same strategies still run, but a failure no longer rejects the request, it just proceeds without an authenticated user:
@Auth(['jwt'], false)
@Get('/:id')
public getPet(@Param('id') id: string, @User user?: JWTUser) {
// `user` is populated if a valid token was sent, undefined otherwise, either way this runs
}
This is the right shape for an endpoint that behaves differently for a logged-in caller without requiring one, showing a pet's full listing to anyone, but flagging the ones the current user already owns. A missing token and an invalid or expired one are treated identically here too, both just leave user undefined rather than surfacing which case actually happened.
JWTStrategy
JWTStrategy looks for a token in three places, in this order, the last one found wins:
- Query parameter (
auth_token): only ifallowQueryParamis enabled, since passing tokens in URLs is discouraged by default. - Authorization header — matching
jwtorbearerschemes, case-insensitive. - Cookie (
jwtby default; signed cookies ifcookieSecureis set).
class JWTStrategyOptions {
headerKey = 'authorization';
headerScheme = '(jwt|bearer)';
cookieName = 'jwt';
cookieSecure = false;
queryKey = 'auth_token';
allowQueryParam = false;
}
Configure the secret and token options under the auth config key:
conf.defaults({
auth: {
strategy: 'auth.JWTStrategy',
secret: 'change-me-in-production',
options: {
expiresIn: '1 hour',
audience: 'my-api.example.com',
issuer: 'api.example.com',
},
},
});
A verified token populates @User/req.user with a JWTUser, roles and all, for the rest of the request, see Request Parameters for how @User and the other injection decorators work.
See the Auth Library plugin to build your own custom auth server, or Auth Server for a turn-key, production-ready one.