Files
Shogi/Shogi.Api/ShogiUserClaimsTransformer.cs
Lucas Morgan 26fd955aa4 Fix claims.
Use OID instead of email for microsoft identifier.
Fix PlayerCount route.
Add created date to user table.
Create spectator icon.
2023-01-20 20:48:38 -06:00

104 lines
3.3 KiB
C#

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using Shogi.Api.Models;
using Shogi.Api.Repositories;
using System.Security.Claims;
namespace Shogi.Api;
/// <summary>
/// Standardizes the claims from third party issuers. Also registers new msal users in the database.
/// </summary>
public class ShogiUserClaimsTransformer : IShogiUserClaimsTransformer
{
private readonly IUserRepository userRepository;
public ShogiUserClaimsTransformer(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var newPrincipal = IsMicrosoft(principal)
? await CreateClaimsFromMicrosoftPrincipal(principal)
: await CreateClaimsFromGuestPrincipal(principal);
return newPrincipal;
}
public async Task<ClaimsPrincipal> CreateClaimsFromGuestPrincipal(ClaimsPrincipal principal)
{
var id = GetGuestUserId(principal);
if (string.IsNullOrWhiteSpace(id))
{
var newUser = User.CreateGuestUser(Guid.NewGuid().ToString());
await this.userRepository.CreateUser(newUser);
return new ClaimsPrincipal(CreateClaimsIdentity(newUser));
}
var user = await this.userRepository.ReadUser(id);
if (user == null) throw new UnauthorizedAccessException("Guest account does not exist.");
return new ClaimsPrincipal(CreateClaimsIdentity(user));
}
private async Task<ClaimsPrincipal> CreateClaimsFromMicrosoftPrincipal(ClaimsPrincipal principal)
{
var id = GetMicrosoftUserId(principal);
var displayname = principal.GetDisplayName();
if (string.IsNullOrWhiteSpace(id) || string.IsNullOrWhiteSpace(displayname))
{
throw new UnauthorizedAccessException("Unknown claim set.");
}
var user = await this.userRepository.ReadUser(id);
if (user == null)
{
user = User.CreateMsalUser(id, displayname);
await this.userRepository.CreateUser(user);
}
return new ClaimsPrincipal(CreateClaimsIdentity(user));
}
private static bool IsMicrosoft(ClaimsPrincipal self)
{
return self.GetObjectId() != null;
}
private static string? GetMicrosoftUserId(ClaimsPrincipal self)
{
return self.GetObjectId();
}
private static string? GetGuestUserId(ClaimsPrincipal self)
{
return self.GetNameIdentifierId();
}
private static ClaimsIdentity CreateClaimsIdentity(User user)
{
var claims = new List<Claim>(4)
{
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Name, user.DisplayName),
};
if (user.LoginPlatform == WhichLoginPlatform.Guest)
{
claims.Add(new Claim(ClaimTypes.Role, "Guest"));
return new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
}
else
{
return new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
}
}
}
public interface IShogiUserClaimsTransformer : IClaimsTransformation
{
Task<ClaimsPrincipal> CreateClaimsFromGuestPrincipal(ClaimsPrincipal principal);
}