fix(security): resolve Security-012..015 — fail login on partial LDAP outage, escape-aware DN parsing, idle check on refresh, username normalization

This commit is contained in:
Joseph Doherty
2026-05-17 03:18:33 -04:00
parent f5199e9da9
commit a58cec5776
4 changed files with 411 additions and 35 deletions
+16
View File
@@ -152,6 +152,14 @@ public class JwtTokenService
/// otherwise the documented 30-minute idle timeout could never fire for a client
/// that polls in the background. Call <see cref="RecordActivity"/> to advance the
/// anchor when handling a genuine user request.
/// <para>
/// A principal that is already past the idle timeout cannot be refreshed: this
/// method returns <c>null</c> (the same "cannot refresh" signal it uses for missing
/// claims). Enforcing the idle check here — rather than relying on the caller to
/// invoke <see cref="IsIdleTimedOut"/> first — guarantees the documented 30-minute
/// idle policy holds regardless of caller discipline; otherwise an idle-expired
/// session could be kept alive indefinitely by background refreshes (Security-014).
/// </para>
/// </summary>
public string? RefreshToken(ClaimsPrincipal currentPrincipal, IReadOnlyList<string> currentRoles, IReadOnlyList<string>? permittedSiteIds)
{
@@ -164,6 +172,14 @@ public class JwtTokenService
return null;
}
// An idle-expired session must not be renewed — the user must re-login.
if (IsIdleTimedOut(currentPrincipal))
{
_logger.LogInformation(
"Cannot refresh token for {Username}: session is past the idle timeout", username);
return null;
}
return GenerateToken(displayName, username, currentRoles, permittedSiteIds,
ReadLastActivity(currentPrincipal));
}