Enter additional data, from the bank, into the user’s Claims. What is the best time or the right way to do it?

Asked

Viewed 390 times

3

I have some extra information that I need to add to the user’s Claims that are from other tables and classes.

Considering the method generated by the ASP.NET MVC template with Identity in the class ApplicationUser:

public class ApplicationUser : IdentityUser
{       
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
        UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(
            this, DefaultAuthenticationTypes.ApplicationCookie);            

        userIdentity.AddClaim(new Claim(ClaimsKey.ClaimA, "ClaimA"));
        userIdentity.AddClaim(new Claim(ClaimsKey.ClaimB, "ClaimB"));
        userIdentity.AddClaim(new Claim(ClaimsKey.ClaimC, "ClaimC"));

        return userIdentity;
    }
}

The one that does not have an EF Context available and that, also, this method is generated at times that there is no context yet created in the request, as in:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = SecurityStampValidator
            .OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                TimeSpan.FromMinutes(30), 
                // aqui, principalmente ao efetuar login.
                // tentei obter o contexto de 
                // HttpContext.Current.GetOwinContext...
                // e obtive um erro por conta de HttpContext.Current 
                // que ainda estava null
                (manager, user) => user.GenerateUserIdentityAsync(manager)) 
    }
});

In the CreateUserIdentityAsync, of ApplicationSignInManager may even have, taking into account the time, which is usually requested after user login:

public override Task<ClaimsIdentity> CreateUserIdentityAsync(Usuario user)
{
    return user.GenerateUserIdentityAsync((AppUserManager)UserManager);
}

Taking these issues into consideration, what is the best time or a good way to add extra data to the Aims, loaded by context?

1 answer

2


In the creation or editing of the user. Claims are portions of information that uniquely identify a user. A great example is in this answer, which I will format for your case.

Notice that GenerateUserIdentityAsync does not necessarily update information on persistence. The method only mounts the object with Claims passed by you. I actually find this example quite bad, because all that is added as Claim in this example is lost when the Cookie user expires.

A more interesting way would be to use the extension method AddOrUpdateClaim:

As follows:

    public ActionResult AtualizarUsuarioCorrente()
    {
        User.AddOrUpdateClaim("CPF", "123.456.789-01");
        User.AddOrUpdateClaim("RG", "321.654-85");
        User.AddOrUpdateClaim("CNH", "7132654978");
    }

The methods of extension are:

    namespace SeuProjeto.Extensions
    {
        public static class ClaimsExtensions
        {
            public static void AddOrUpdateClaim(this IPrincipal principalDoUsuario, string chave, string valor)
            {
                var identity = principalDoUsuario.Identity as ClaimsIdentity;
                if (identity == null)
                    return;

                // Se a Claim já existe, remove. 
                // Claims não são "atualizáveis". É preciso remover uma
                // Claim antiga para inserir uma nova com o mesmo nome.
                var claimExistente = identity.FindFirst(key);
                if (claimExistente != null)
                    identity.RemoveClaim(claimExistente);

                // Aqui adicionamos uma Claim em banco.
                identity.AddClaim(new Claim(key, value));
                var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
                authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });
            }

            public static string GetClaimValue(this IPrincipal principalDoUsuario, string chave)
            {
                var identity = principalDoUsuario.Identity as ClaimsIdentity;
                if (identity == null)
                    return null;

                var claim = identity.Claims.First(c => c.Type == chave);
                return claim.Value;
            }
        }
    }

After updating the user, the Claims can be obtained like this:

var identity = (ClaimsIdentity)User.Identity;
IEnumerable<Claim> claims = identity.Claims;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.