Search code examples
c#asp.netasp.net-mvcazure-active-directoryclaims-based-identity

New Identity Claims Disappear


I have an ASP.NET Core 7 application in which I use Azure authentication. Once the user is authenticated, I want to add a new claim based on data I retrieved from the database.

I am using the following code to do this:

var userID = await GetId(User.Identity?.Name.ToString());

if (userID != 0)
{
    var claims = new List<Claim>
            {
                new Claim("MyClaim", userID.ToString())
            };

    var appIdentity = new ClaimsIdentity(claims);

    User.AddIdentity(appIdentity);

    return RedirectToAction(nameof(Index));
}

This seems to work:

enter image description here

You can see both the ClaimsIdentity from the Azure and the one I created to store the claim. I can drill down and see the value:

enter image description here

However, as soon as I'm redirected to the next page, the ClaimIdentity is not longer accessible:

enter image description here

What am I missing for the claims to persist and how would I retrieve it?

Thanks!


Solution

  • Solution:

        public class MyClaimsTransformation : IClaimsTransformation
    {
        private readonly IServiceScopeFactory scopeFactory;
    
        public MyClaimsTransformation(IServiceScopeFactory scopeFactory)
        {
            this.scopeFactory = scopeFactory;
        }
    
        public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
        {
            ClaimsIdentity claimsIdentity = new ClaimsIdentity();
            var claimType = "IdContact";
    
            if (principal.Identity.Name != null)
            {
                int idContact;
    
                using (var scope = scopeFactory.CreateScope())
                {
                    var _context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                    idContact = await _context.Contacts
                        .Where(u => u.Email == principal.Identity.Name)
                        .Select(u => u.IdContact)
                        .SingleOrDefaultAsync();
                }
    
                if (idContact != 0)
                {
                    if (!principal.HasClaim(claim => claim.Type == claimType))
                    {
                        claimsIdentity.AddClaim(new Claim(claimType, idContact.ToString()));
                    }
                }
            }
    
            principal.AddIdentity(claimsIdentity);
    
            return await Task.FromResult(principal).ConfigureAwait(false);
        }
    

    Using IClaimsTransformation to make the claim persist and using IServiceScopeFactory to access DbContext to pull info for the claim from the database.

    Also, need to add the following line in program.cs:

      Builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();