Module: middleware/authenticate

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

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 AUTH_TYPE). If empty, tries ALL strategies.

Source:
Returns:

Express middleware (req, res, next).

Type
function

(static) getJwtSecret() → {string}

Get the JWT signing secret.

Resolution order:

  1. JWT_SECRET env var (required in production, recommended everywhere)
  2. Dev/test only: auto-generate a random 256-bit secret and persist it to backend/data/.jwt-secret so tokens survive server restarts.
Source:
Throws:

In production if JWT_SECRET is 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