88 lines
4.3 KiB
C#
88 lines
4.3 KiB
C#
using Tiku.Domain.Identity;
|
|
using Tiku.Domain.Tenancy;
|
|
using Tiku.Application.Auth;
|
|
|
|
namespace Tiku.Application.Security;
|
|
|
|
public enum AuthorizationCacheMode { Disabled, Shadow, Active }
|
|
|
|
public sealed class AuthorizationCacheOptions
|
|
{
|
|
public const string SectionName = "Security:AuthorizationCache";
|
|
public AuthorizationCacheMode Mode { get; set; } = AuthorizationCacheMode.Disabled;
|
|
public int LocalSnapshotSeconds { get; set; } = 60;
|
|
public int DistributedStateSeconds { get; set; } = 60;
|
|
public int DistributedSnapshotSeconds { get; set; } = 300;
|
|
public int JitterPercent { get; set; } = 20;
|
|
}
|
|
|
|
public sealed record CachedSessionSecurityState(
|
|
Guid SessionId, Guid UserId, AuthRealm Realm, Guid? TenantId,
|
|
string SecurityStamp, DateTimeOffset ExpiresAt, bool Revoked);
|
|
public sealed record CachedUserSecurityState(Guid UserId, UserStatus Status, string SecurityStamp);
|
|
public sealed record CachedTenantSecurityState(Guid TenantId, TenantStatus Status);
|
|
public sealed record CachedMembershipSecurityState(Guid TenantId, Guid UserId, MembershipStatus Status);
|
|
public sealed record CachedPlatformAccessState(Guid UserId, long AuthorizationVersion, bool Allowed);
|
|
public sealed record CachedAuthorizationVersion(AuthRealm Realm, Guid? TenantId, long Version);
|
|
|
|
public sealed record AccessSecurityCacheLookup(Guid SessionId, Guid UserId, AuthRealm Realm, Guid? TenantId);
|
|
public sealed record AccessSecurityCacheState(
|
|
CachedSessionSecurityState? Session,
|
|
CachedUserSecurityState? User,
|
|
CachedTenantSecurityState? Tenant,
|
|
CachedMembershipSecurityState? Membership,
|
|
CachedPlatformAccessState? PlatformAccess,
|
|
CachedAuthorizationVersion? AuthorizationVersion)
|
|
{
|
|
public bool Complete => Session is not null && User is not null && AuthorizationVersion is not null &&
|
|
(Session.Realm == AuthRealm.Platform && PlatformAccess is not null ||
|
|
Session.Realm == AuthRealm.Tenant && Tenant is not null && Membership is not null);
|
|
}
|
|
|
|
public sealed record CachedAuthorizationSnapshot(long Version, CurrentAccessSnapshot Snapshot);
|
|
|
|
public interface IAccessSecurityCache
|
|
{
|
|
bool IsConfigured { get; }
|
|
Task<AccessSecurityCacheState?> GetAsync(AccessSecurityCacheLookup lookup, CancellationToken cancellationToken = default);
|
|
Task SetAsync(AccessSecurityCacheState state, CancellationToken cancellationToken = default);
|
|
Task InvalidateSessionAsync(Guid sessionId, CancellationToken cancellationToken = default);
|
|
Task InvalidateUserAsync(Guid userId, CancellationToken cancellationToken = default);
|
|
Task InvalidateTenantAsync(Guid tenantId, CancellationToken cancellationToken = default);
|
|
Task InvalidateMembershipAsync(Guid tenantId, Guid userId, CancellationToken cancellationToken = default);
|
|
Task SetAuthorizationVersionAsync(AuthRealm realm, Guid? tenantId, long version, CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public interface IAuthorizationSnapshotCache
|
|
{
|
|
Task<CachedAuthorizationSnapshot?> GetAsync(AuthRealm realm, Guid? tenantId, Guid userId, CancellationToken cancellationToken = default);
|
|
Task SetAsync(AuthRealm realm, Guid? tenantId, Guid userId, CachedAuthorizationSnapshot snapshot, CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public interface IAuthorizationStateInvalidator
|
|
{
|
|
Task InvalidateSessionAsync(Guid sessionId, CancellationToken cancellationToken = default);
|
|
Task InvalidateUserAsync(Guid userId, CancellationToken cancellationToken = default);
|
|
Task InvalidateTenantAsync(Guid tenantId, CancellationToken cancellationToken = default);
|
|
Task InvalidateMembershipAsync(Guid tenantId, Guid userId, CancellationToken cancellationToken = default);
|
|
Task<long> BumpScopeAsync(AuthRealm realm, Guid? tenantId, CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public interface IAuthorizationCacheInvalidationProcessor
|
|
{
|
|
Task<int> ProcessPendingAsync(int batchSize = 100, CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public interface IRequestAccessValidator
|
|
{
|
|
Task<AuthSessionValidationResult?> ValidateAsync(
|
|
Guid sessionId,
|
|
Guid userId,
|
|
AuthRealm realm,
|
|
Guid? tenantId,
|
|
CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public sealed class AuthorizationSecurityUnavailableException(Exception innerException)
|
|
: Exception("Authentication security dependencies are unavailable.", innerException);
|