Commit ddd4260b authored by Eric Dieckman's avatar Eric Dieckman
Browse files

Add internal ID claim for App User

parent 645aa86d
Loading
Loading
Loading
Loading
+32 −7
Original line number Diff line number Diff line
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Principal;
using System.Text.Json;
using Cals.Authentication;
using Cals.Visor.Infrastructure.Contexts;
using Cals.Visor.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
@@ -109,7 +113,7 @@ public static class AuthenticationServiceExtensions
            }
        }

        AttachUserInfoClaims(context, userInfo!);
        await AttachUserInfoClaims(context, userInfo!);
    }

    private static async Task<Dictionary<string, object>?> FetchAndCacheUserInfoAsync(
@@ -168,15 +172,36 @@ public static class AuthenticationServiceExtensions
        }
    }

    private static void AttachUserInfoClaims(
    private static async Task AttachUserInfoClaims(
        TokenValidatedContext context,
        Dictionary<string, object> userInfo)
    {
        var identity = (ClaimsIdentity)context.Principal!.Identity!;
        foreach (var kvp in userInfo)
        {
            identity.AddClaim(new Claim(kvp.Key, kvp.Value?.ToString() ?? ""));
        }
        if (context.Principal == null || context.Principal.Identity == null)
            throw new Exception("No principal in request");

        IIdentity? identity = context.Principal.Identity;

        WiscEduUser oidcIdentity = new WiscEduOidcUser(context.Principal);

        // Extract the unique ID from the OIDC identity
        if (oidcIdentity.Pvi == null)
           throw new Exception($"OIDC unique identifier not found (expected pvi).");

        // Resolve your application user service
        ApplicationDbContext dbContext = context.HttpContext.RequestServices
            .GetRequiredService<ApplicationDbContext>();

        // Look up the internal user
        AppUser? user = await dbContext.Users.FirstOrDefaultAsync(u => u.UniqueID == oidcIdentity.Pvi);

        // If user does not exist, create it
        user ??= oidcIdentity.ToAppUser();
        dbContext.Add(user);
        await dbContext.SaveChangesAsync();

        // Add the app-specific internal user id claim
        if (user.AppUserId.HasValue)
            ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(VisorClaimTypes.Id, user.AppUserId.Value.ToString()));
    }

    private static List<Claim> GetDevClaimsForUser(string? username)
+6 −0
Original line number Diff line number Diff line
namespace Cals.Visor.Api.Identity;

public class VisorClaimTypes
{
    public const string Id = "app_user_id";
}
+8 −0
Original line number Diff line number Diff line
using System.Security.Claims;
using Cals.Authentication;
using Cals.Visor.Api.Identity;

namespace Cals.Visor.Identity;

@@ -13,10 +14,17 @@ public class VisorUser : WiscEduOidcUser, IWiscEduUser
    public VisorUser(ClaimsIdentity? identity)
        : base(identity)
    {
        if (identity == null)
            return;

        Claim? idClaim = identity.FindFirst(VisorClaimTypes.Id);
        if (idClaim != null && long.TryParse(idClaim.Value, out long id)) Id = id;
    }

    public VisorUser(ClaimsPrincipal principal)
        : this((ClaimsIdentity?)principal.Identity)
    {
    }

    public long? Id { get; protected set; }
}
+20 −0
Original line number Diff line number Diff line
using Cals.Authentication;
using Cals.Visor.Models;

namespace Cals.Visor.Api;

public static class WiscEduUserExtensions
{
    public static AppUser ToAppUser(this WiscEduUser wiscEduUser)
    {
        return new AppUser()
        {
            DisplayName = wiscEduUser.Name,
            FirstName = wiscEduUser.FirstName,
            LastName = wiscEduUser.LastName,
            Email = wiscEduUser.Email,
            UniqueID = wiscEduUser.Pvi,
            Username = wiscEduUser.NetId
        };
    }
}