You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The idle-timeout block in get_current_user only read last_activity
from the JWT, but no issuance code wrote it — so the check ran zero
times on real tokens. Read activity from Redis first (update_activity
was already writing there but had no consumer), fall back to the JWT
last_activity claim, fall back to iat. Emit last_activity=iat in
create_access_token for first-request bootstrap.
Folds in remaining PR-review blockers:
- bb43712cae28 alembic merge resolves dual-head from rebase past
the head referenced by cae28b15a507
- TOKEN_EXPIRY 10080->20 min default documented in CHANGELOG
Behavior Changes with migration & rollback guidance
- drop dead refresh_token_expiry config field + 3 doc references
- /auth/logout current_user: dict -> EmailUser (matches actual
return type of get_current_user)
- /admin/logout test rewritten with TestClient + CSRF deny-path
regression (was asyncio.run on MagicMock — bypassed middleware
and would pass even if the route was unregistered)
Coverage on diff: 91% -> ~100%. New unit tests cover every branch
of the idle-timeout block plus the Redis-success and fresh-session
paths in TokenBlocklistService that were previously unreached.
Refs #4317, #4371
Signed-off-by: Jonathan Springer <jps@s390x.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,9 +9,23 @@
9
9
-**🛡️ Content Security – Malicious Pattern Detection (US-3)** ([#4072](https://github.com/IBM/mcp-context-forge/pull/4072), [#538](https://github.com/IBM/mcp-context-forge/issues/538)) – Regex-based scanning for XSS, SQL injection, command injection, and template-injection patterns. Applied on the single **and** bulk create/update paths for resources, prompts, and tools (tool `name`, `description`, and JSON-serialized `inputSchema`). New config: `CONTENT_PATTERN_DETECTION_ENABLED`, `CONTENT_BLOCKED_PATTERNS`, `CONTENT_PATTERN_VALIDATION_MODE` (`strict` | `moderate` | `lenient`). Lenient mode logs every matched pattern in a payload (was: only the first).
-**⚡ ReDoS Defense for Pattern Scanning** ([#4072](https://github.com/IBM/mcp-context-forge/pull/4072)) – `CONTENT_PATTERN_MAX_SCAN_SIZE` (default 200 KB) caps scan input length deterministically; `CONTENT_PATTERN_REGEX_TIMEOUT` (default 1.0 s) per-pattern. Patterns are pre-compiled once at service init instead of re-compiled per request.
12
+
-**🔐 JWT Token Security – Server-Side Revocation, Idle Timeout, Logout** ([#4371](https://github.com/IBM/mcp-context-forge/pull/4371), [#4317](https://github.com/IBM/mcp-context-forge/issues/4317)) – New `TokenBlocklistService` (Redis-cached, DB-persisted) for immediate JWT invalidation. Idle-timeout enforcement on every authenticated request, with activity tracking in Redis (falls back to JWT `iat` when Redis is unavailable). New `POST /auth/logout` (Bearer auth) and enhanced `POST /admin/logout` (cookie auth) revoke the caller's token in the blocklist before clearing session state. Comprehensive audit-log fields (`security_event`, `security_severity`, `jti`, `reason`) for every revocation/idle-timeout event. New config: `TOKEN_IDLE_TIMEOUT`, `TOKEN_BLOCKLIST_CLEANUP_HOURS`. Addresses X-Force Red audit findings on session-token management.
12
13
13
14
### ⚠️ Behavior Changes
14
15
16
+
#### **⏱️ `TOKEN_EXPIRY` default reduced from 10080 minutes (~7 days) to 20 minutes** ([#4371](https://github.com/IBM/mcp-context-forge/pull/4371), [#4317](https://github.com/IBM/mcp-context-forge/issues/4317))
17
+
18
+
**Impact**: Any deployment that does not set `TOKEN_EXPIRY` explicitly will now issue session tokens that expire after **20 minutes** instead of ~7 days. Existing tokens already in circulation are unaffected (they retain the `exp` claim baked in at issuance), but every newly-issued token after upgrade has the shorter lifetime. Automation that re-uses a single login token for hours or days will start receiving HTTP 401 mid-flight.
19
+
20
+
**Why**: Short-lived tokens are the primary mitigation for stolen-token replay, per the X-Force Red security audit (#4317). 7-day session tokens were previously called out as a finding. The new default brings the gateway in line with industry guidance (5–20 minutes for session tokens).
21
+
22
+
**Migration**:
23
+
-**Interactive sessions** — no action needed; the new `/auth/logout` endpoint and idle-timeout enforcement (60 min default) work transparently.
24
+
-**CI/automation that needs longer-lived tokens** — set `TOKEN_EXPIRY` explicitly in `.env` (range: 5–1440 minutes), e.g. `TOKEN_EXPIRY=480` for an 8-hour shift, and pair it with `TOKEN_IDLE_TIMEOUT=0` if the workload bursts after long quiet periods.
25
+
-**Long-running scripts using `mcpgateway.utils.create_jwt_token --exp <minutes>`** — the `--exp` flag is unaffected (it overrides the default).
26
+
27
+
**Rollback**: Set `TOKEN_EXPIRY=10080` to restore the previous 7-day default.
28
+
15
29
#### **🧪 Prompt templates are now rendered in a Jinja2 sandbox** ([#4072](https://github.com/IBM/mcp-context-forge/pull/4072))
16
30
17
31
**Impact**: `prompt_service` now uses `jinja2.sandbox.SandboxedEnvironment` instead of plain `jinja2.Environment`. Templates that previously reached Python internals at render time will raise `PromptError: sandbox rejected unsafe operation`.
# Refresh token configuration (longer-lived but revocable)
346
-
refresh_token_expiry: int=Field(default=10080, ge=60, le=43200, description="Refresh token expiry in minutes (1 hour to 30 days). Used to obtain new access tokens.") # 7 days
347
-
348
345
# Idle timeout configuration
349
346
token_idle_timeout: int=Field(default=60, ge=5, le=1440, description="Maximum idle time in minutes before token requires refresh (5-1440).") # 60 minutes
0 commit comments