constellation-api/CH.Authority/Services/UserIdentityService.cs

111 lines
3.0 KiB
C#

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<User?> 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<bool> IsAuthorizedAsync(CancellationToken cancellationToken)
{
var user = await GetUserOrDefaultAsync(cancellationToken);
return null != user;
}
private async Task<User> 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;
}
}