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:
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user