fix(security): bearer token hardening follow-ups — nbf skew, TTL-0 path, cache docs, extra rejection tests (review 2026-10-21 05/U1, 05/P1 L1/L5/L6)

- JwtTokenService back-dates nbf by the 30 s validation skew so a peer central whose
  clock lags the issuer accepts a fresh token after failover.
- RoleMappingCacheSeconds = 0 routes RoleMapper to the matched-rows loader (old cost)
  instead of loading every Deployer mapping's scope rules per call.
- RoleMappingCache / SecurityOptions / Component-Security.md describe Invalidate() by
  its contract plus the TTL, not by a call site.
- Tests: HS512 with the same key, issuer/audience mismatch, lagging-peer nbf, TTL-0
  matched-only reads, refresh-vs-Invalidate generation race.
This commit is contained in:
Joseph Doherty
2026-10-22 08:25:20 -04:00
parent 1b3928a0a2
commit ea172edebc
7 changed files with 158 additions and 16 deletions
@@ -67,9 +67,9 @@ public class SecurityOptions
/// How long, in seconds, <see cref="RoleMapper"/> may serve the LDAP-group→role mapping
/// table and its site-scope rules from memory before re-reading the configuration
/// database. Default: <b>30</b>. <b>0</b> disables the cache (every mapping reads the
/// database). A mapping change is visible on every node within this window; the node
/// that served the change sees it immediately once <see cref="RoleMappingCache.Invalidate"/>
/// is called.
/// database, matched scope rules only). Without an explicit invalidation a mapping change
/// is visible on every node within this window; <see cref="RoleMappingCache.Invalidate"/>
/// discards the calling node's snapshot so its next mapping re-reads the database.
/// </summary>
public int RoleMappingCacheSeconds { get; set; } = 30;