Centralised authentication middleware (strategy pattern).
All token extraction and verification logic lives in this single file so adding a new auth method (API keys, service accounts, SAML, etc.) means adding one strategy object — no route files need to change.
Strategies
| Name | Token source | Verifier | Sets on req |
|---|---|---|---|
jwt-cookie |
access_token HttpOnly cookie |
HS256 JWT verify + revocation check | req.authUser (JWT payload) |
jwt-bearer |
Authorization: Bearer header |
Same as jwt-cookie | req.authUser |
jwt-query |
?token= query param (SSE) |
Same as jwt-cookie | req.authUser |
trigger-token |
Authorization: Bearer header |
SHA-256 hash lookup in webhook_tokens |
req.triggerToken, req.triggerProject |
CSRF integration
req.authStrategy is set on every authenticated request. The CSRF
middleware in appSetup.js checks COOKIE_STRATEGIES.has(req.authStrategy)
— non-cookie strategies are automatically exempt without manual regex
carve-outs.
Backward compatibility
requireAuth is re-exported from routes/auth.js as an alias for
requireUser so existing imports continue to work without changes.
- Source:
Members
(static, constant) AUTH_COOKIE
JWT cookie name — HttpOnly so JS cannot read the token.
- Source:
(static, constant) AUTH_TYPE :string
Auth strategy identifiers.
Type:
- string
- Source:
(static, constant) COOKIE_STRATEGIES :Set.<string>
Strategies that use cookies and therefore require CSRF protection. Any strategy NOT in this set is automatically CSRF-exempt.
Type:
- Set.<string>
- Source:
(static, constant) requireTrigger
Trigger token auth middleware — per-project Bearer token for CI/CD.
Sets req.triggerToken and req.triggerProject on success.
- Source:
(static, constant) requireUser
JWT auth middleware — tries cookie → bearer → query param.
This is the standard middleware for all user-facing API routes.
Backward-compatible drop-in replacement for the old requireAuth.
- Source:
(static, constant) revokedTokens
Revoked tokens facade — .set() / .has() API matching the original Map
so all existing callers (auth.js logout, refresh) work without changes.
Delegates to Redis when available. Cross-instance sync is handled by
pub/sub — set() publishes to the REVOKE_CHANNEL so other instances
update their local Maps, and has() always checks the local Map (fast,
synchronous, and kept in sync by the subscriber).
- Source:
(inner, constant) REVOKE_CHANNEL
Redis pub/sub channel for broadcasting revocations across instances.
- Source:
(inner, constant) STRATEGIES :Array.<{name: string, extract: function(), verify: function()}>
Type:
- Array.<{name: string, extract: function(), verify: function()}>
- Source:
(inner) _cachedSecret :string|null
Type:
- string | null
- Source:
(inner, constant) _localRevokedTokens
In-memory fallback revocation list: { jti → expiry_timestamp_sec }
- Source:
Methods
(static) authenticate(…allowedNames) → {function}
Create an Express middleware that authenticates the request using the specified strategies (tried in declaration order).
On success, sets req.authUser, req.triggerToken, req.triggerProject,
and req.authStrategy as appropriate for the winning strategy.
Parameters:
| Name | Type | Attributes | Description |
|---|---|---|---|
allowedNames |
string |
<repeatable> |
Strategy names to try (from |
- Source:
Returns:
Express middleware (req, res, next).
- Type
- function
(static) getJwtSecret() → {string}
Get the JWT signing secret.
Resolution order:
JWT_SECRETenv var (required in production, recommended everywhere)- Dev/test only: auto-generate a random 256-bit secret and persist it to
backend/data/.jwt-secretso tokens survive server restarts.
- Source:
Throws:
-
In production if
JWT_SECRETis missing or too short. - Type
- Error
Returns:
The secret (always ≥ 32 chars).
- Type
- string
(static) signJwt(payload, secret, expiresInSecopt) → {string}
Sign a JWT with HS256 using only Node.js crypto (no external library).
Parameters:
| Name | Type | Attributes | Default | Description |
|---|---|---|---|---|
payload |
Object | Claims to include. |
||
secret |
string | HMAC secret (32+ chars recommended). |
||
expiresInSec |
number |
<optional> |
28800 | Token lifetime in seconds (default 8 hours). |
- Source:
Returns:
The signed JWT string.
- Type
- string
(static) verifyJwt(token, secret) → {Object|null}
Verify and decode a JWT signed with HS256.
Returns the decoded payload if valid, or null if invalid/expired/malformed.
Uses constant-time signature comparison and explicit buffer length check.
Parameters:
| Name | Type | Description |
|---|---|---|
token |
string | The JWT string to verify. |
secret |
string | The HMAC secret used for signing. |
- Source:
Returns:
Decoded payload, or null on failure.
- Type
- Object | null
(inner) verifyJwtToken(token) → {Object|null}
JWT verification shared by all jwt-* strategies.
Parameters:
| Name | Type | Description |
|---|---|---|
token |
string | Raw JWT string. |
- Source:
Returns:
Decoded payload or null.
- Type
- Object | null