using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Dto.Requests; using Mirea.Api.Security.Common.Dto.Responses; using Mirea.Api.Security.Common.Interfaces; using System; using System.Security; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace Mirea.Api.Security.Services; public class AuthService(ICacheService cache, IAccessToken accessTokenService, IRevokedToken revokedToken) { public TimeSpan Lifetime { private get; init; } private static string GenerateRefreshToken() => Guid.NewGuid().ToString().Replace("-", "") + GeneratorKey.GenerateString(32); private (string Token, DateTime ExpireIn) GenerateAccessToken(string userId) => accessTokenService.GenerateToken(userId); private static string GetAuthCacheKey(string fingerprint) => $"{fingerprint}_auth_token"; private Task SetAuthTokenDataToCache(string fingerprint, AuthToken data, CancellationToken cancellation) => cache.SetAsync( GetAuthCacheKey(fingerprint), JsonSerializer.SerializeToUtf8Bytes(data), slidingExpiration: Lifetime, cancellationToken: cancellation); private Task RevokeAccessToken(string token) => revokedToken.AddTokenToRevokedAsync(token, accessTokenService.GetExpireDateTime(token)); public async Task GenerateAuthTokensAsync(TokenRequest request, string preAuthToken, CancellationToken cancellation = default) { string userId = await new PreAuthService(cache).MatchToken(request, preAuthToken, cancellation); var refreshToken = GenerateRefreshToken(); var accessToken = GenerateAccessToken(userId); var authTokenStruct = new AuthToken { CreatedAt = DateTime.UtcNow, Ip = request.Ip, RefreshToken = refreshToken, UserAgent = request.UserAgent, UserId = userId, AccessToken = accessToken.Token }; await SetAuthTokenDataToCache(request.Fingerprint, authTokenStruct, cancellation); return new AuthTokenResponse { AccessToken = accessToken.Token, ExpiresIn = accessToken.ExpireIn, RefreshToken = authTokenStruct.RefreshToken }; } }