Files
kawa c4a1775d7d Harden auth, headers, and container per OWASP review
- Add per-account lockout + IP rate limiter on local sign-in (A07)
- Emit CSP and security headers on every response (A05)
- Run container as non-root `app`, /data 0700 (A05/A02)
- Stop reflecting raw token-endpoint body into redirect URL (A09)
- Handle missing refresh_token in connect callback without a 500

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 14:30:19 +02:00

32 lines
1.6 KiB
C#

namespace SharepointToolbox.Web.Core.Models;
public class AppUser
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Email { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public UserRole Role { get; set; } = UserRole.TechN0;
/// <summary>Identity source. Entra = OIDC-provisioned, Local = password-based account.</summary>
public AuthProvider Provider { get; set; } = AuthProvider.Entra;
/// <summary>PasswordHasher output. Only set for <see cref="AuthProvider.Local"/> users.</summary>
public string? PasswordHash { get; set; }
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset? LastLogin { get; set; }
// ── Local-account brute-force lockout ───────────────────────────────────────
// Consecutive failed password attempts and, once the threshold is hit, the UTC
// instant the account unlocks again. Only meaningful for AuthProvider.Local.
// A per-account counter (not just an IP rate limiter) is the control that holds
// up here: forwarded headers are trusted from any source, so an attacker who can
// rotate X-Forwarded-For would evade IP-based throttling but not this.
/// <summary>Consecutive failed local-login attempts since the last success.</summary>
public int FailedLoginCount { get; set; }
/// <summary>UTC instant the account unlocks; null when not locked.</summary>
public DateTimeOffset? LockoutEndUtc { get; set; }
}