Judicial Backend does not implement its own identity store. Instead it uses the BFF (Backend-for-Frontend) pattern: the Express server acts as a proxy between the browser client and a dedicated external authentication API. Clients never communicate with that external API directly — they only talk to this backend, which forwards credentials, holds theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/BladimirGS/judicial-backend/llms.txt
Use this file to discover all available pages before exploring further.
refreshToken in a secure server-set cookie, and returns a short-lived access_token for use in subsequent API calls.
How the BFF Pattern Works
The BFF layer handles three responsibilities on behalf of the client:- Credential forwarding —
POST /api/auth/loginreceives{ usuario, contrasenia }, enriches the payload with theidSistemaidentifier, and forwards the request to the external API’s/api/AuthJWT/Loginendpoint. - Cookie management — the
refreshTokenreturned by the external API is stored in anhttpOnlycookie (path: /api/auth) and never exposed to JavaScript. Rotation on refresh and clearance on logout are handled automatically. - Token relay — only the
access_tokenis returned in the JSON response body for the client to store in memory and attach to subsequent requests.
The
refreshToken cookie is set with httpOnly: true, which means it is completely inaccessible to JavaScript running in the browser. This eliminates an entire class of XSS-based token theft attacks. The cookie is also scoped to path: /api/auth so it is only sent to the token-refresh and logout endpoints.Authentication Flow
Client sends login credentials
The client POSTs
{ usuario, contrasenia } to POST /api/auth/login. The request body is validated by LoginDto using class-validator before it reaches the controller — a 400 is returned immediately if either field is missing or non-string.AuthController delegates to AuthExternalAdapter
AuthController.login() calls AuthExternalAdapter.login(usuario, contrasenia). The adapter constructs a JSON body that includes idSistema (read from envs.ID_SISTEMA) and POSTs it to ${EXTERNAL_AUTH_URL}/api/AuthJWT/Login.External API authenticates and responds
The external auth API validates the credentials and returns an
access_token in the JSON body. The refreshToken is returned as a Set-Cookie header, which the adapter parses via a regex on the raw header value.Backend sets httpOnly cookie and returns access token
AuthController calls res.cookie('refreshToken', refreshToken, COOKIE_OPTIONS) — setting httpOnly: true, the configured secure and sameSite flags, and a maxAge of 24 hours. It then returns { access_token } in the JSON response body via responseUtil.success.Client stores access_token in memory
The client stores the
access_token in application memory (never in localStorage). For all subsequent requests to protected routes it sends the token in the Authorization header as a Bearer token.protect middleware verifies the Bearer token
Every request to a protected route passes through the
protect middleware, which extracts the Bearer token from the Authorization header, fetches the RS256 public key from the external JWKS endpoint, verifies the signature plus iss and aud claims, and populates req.user with the decoded JwtPayload. See JWT Protection for the full verification flow.Token renewal via refresh endpoint
When the access token expires the client calls
POST /api/auth/refresh. The refreshToken cookie is sent automatically by the browser. The backend forwards it to ${EXTERNAL_AUTH_URL}/api/AuthJWT/RefreshToken and, if the external API rotates the refresh token, updates the cookie before returning a new access_token.Route Protection
Protection is applied centrally insrc/routes/index.ts. Auth routes are entirely public; every other route group requires a valid Bearer JWT.
| Route | Protected | Notes |
|---|---|---|
/api/auth/* | No | Login, refresh, and logout — public by design |
/api/apelaciones/* | Yes | Requires Bearer JWT; rate-limited by apiLimiter |
/api/busquedas/* | Yes | Requires Bearer JWT; rate-limited by apiLimiter |
/api/estadisticas/* | Yes | Requires Bearer JWT; rate-limited by apiLimiter |
authLimiter (default: 20 requests per 15-minute window) to slow credential-stuffing attempts.
Required Environment Variables
| Variable | Description |
|---|---|
EXTERNAL_AUTH_URL | Base URL of the external authentication API (no trailing slash). Used by both AuthExternalAdapter and the JWKS client in protect. |
JWT_ISSUER | Expected iss claim in every JWT. Passed as issuer to jwt.verify. |
JWT_AUDIENCE | Expected aud claim in every JWT. Passed as audience to jwt.verify. |
ID_SISTEMA | System identifier forwarded to the external API during login as idSistema. |
COOKIE_SECURE, COOKIE_SAME_SITE, CORS_ORIGINS — control cross-site cookie and CORS behaviour and should also be reviewed for production deployments.
Quick-start: Login and Call a Protected Route
-c cookies.txt flag tells curl to save the refreshToken cookie set by the server; -b cookies.txt sends it on subsequent requests, mirroring what a browser does automatically.
Auth Endpoint Reference
POST /api/auth/login
Authenticate with
usuario and contrasenia. Returns access_token; sets refreshToken httpOnly cookie.POST /api/auth/refresh
Exchange a valid
refreshToken cookie for a new access_token. Rotates the cookie if the external API issues a new refresh token.POST /api/auth/logout
Revoke the session on the external API and clear the
refreshToken cookie.