using CH.Dal; using CH.Dal.DbEntity; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System.Security.Claims; namespace CH.Authority.Services; public class UserIdentityService { private User? user; private readonly IHttpContextAccessor httpContextAccessor; private readonly IConfiguration configuration; private readonly CHDbContext dbContext; public string? SubjectId { get; } public string? Email { get; } public string? FirstName { get; } public string? LastName { get; } public bool? EmailVerified { get; } public string? AuthIssuer { get; } public UserIdentityService(CHDbContext dbContext, IHttpContextAccessor httpContextAccessor, IConfiguration configuration) { this.dbContext = dbContext; this.httpContextAccessor = httpContextAccessor; this.configuration = configuration; // microsoft you twats! NameIdentifier = Sub SubjectId = ResolveClaim(ClaimTypes.NameIdentifier); Email = ResolveClaim(ClaimTypes.Email); FirstName = ResolveClaim(ClaimTypes.GivenName); LastName = ResolveClaim(ClaimTypes.Surname); var emailVerifiedString = ResolveClaim("email_verified"); if (null != emailVerifiedString && bool.TryParse(emailVerifiedString, out var emailVerified)) { EmailVerified = emailVerified; } AuthIssuer = ResolveClaim("iss"); } public bool IsAuthenticated() { var isAuthenticated = httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false; if (!isAuthenticated || null == EmailVerified) return false; return EmailVerified ?? false; } private string? ResolveClaim(params string[] name) { var isAuthenticated = httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false; if (false == isAuthenticated) return null; var claim = httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(claim => name.Contains(claim.Type)); return claim?.Value; } public async Task GetUserOrDefaultAsync(CancellationToken cancellationToken = default) { if (false == IsAuthenticated()) return null; if (null != user) return user; if (string.IsNullOrWhiteSpace(Email)) return null; user = await dbContext.Users .AsNoTracking() .FirstOrDefaultAsync(user => user.SubjectId == SubjectId, cancellationToken); // create user if it doesn't exist if (null == user) user = await CreateUserAsync(cancellationToken); return user; } public async Task IsAuthorizedAsync(CancellationToken cancellationToken) { var user = await GetUserOrDefaultAsync(cancellationToken); return null != user; } private async Task CreateUserAsync(CancellationToken cancellationToken = default) { var user = new User { FirstName = FirstName, LastName = LastName, Email = Email, SubjectId = SubjectId, Verified = EmailVerified ?? false, }; dbContext.Users.Add(user); await dbContext.SaveChangesAsync(cancellationToken); return user; } }