How not to lose the data included in the Claims in the revalidations of Cookies?

2

I have an application that I need to control the access of the users that are according to the profile of each one. Empresa , Filial .

In the User entity I have added the fields referring to these two other entities and in them will be the information that represents each one and its access profile.

public class Usuario : IdentityUser
{
    public int EmpresaId { get; set; }
    public int? FilialId { get; set; }

    public virtual Empresa Empresa { get; set; }
    public virtual Filial Filial { get; set; }

    public Perfil Perfil { get; set; }

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

        userIdentity.AddClaim(new Claim(CustomClaimTypes.EMPRESA_ID, EmpresaId.ToString()));
        userIdentity.AddClaim(new Claim(CustomClaimTypes.FILIAL_ID, FilialId?.ToString() ?? ""));
        userIdentity.AddClaim(new Claim(CustomClaimTypes.PERFIL, Perfil.ToString());

        return userIdentity;
    }
}

To control the profile within the application I load and get the information in the User's Claims, as shown in the GenerateUserIdentityAsync method.

And then I created a IdentityManager class to help get this information and update it when I need it.

public class IdentityManager
{
    public IdentityManager(IIdentity identity)
    {
        Identity = identity as ClaimsIdentity;
    }

    protected ClaimsIdentity Identity { get; set; }

    public int EmpresaId
    {
        get { return GetClaimValue(CustomClaimTypes.EMPRESA_ID); }
        set { SetClaim(CustomClaimTypes.EMPRESA_ID, value.ToString()); }
    }        

    public int? FilialId
    {
        get { return GetClaimValue(CustomClaimTypes.FILIAL_ID); }
        set { SetClaim(CustomClaimTypes.FILIAL_ID, value.ToString()); }
    }

    public Perfil Perfil
    {
        get { return (Perfil)Enum.Parse(typeof(Perfil), GetClaimValue(CustomClaimTypes.PERFIL)); }
        set { SetClaim(CustomClaimTypes.PERFIL, value.ToString()); }
    }

    public void Update()
    {
        var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, Identity);
    }

    private int GetClaimValue(string claimType)
    {
        int id;
        int.TryParse(Identity.FindFirstValue(claimType), out id);
        return id;
    }

    private void SetClaim(string claimType, string value)
    {
        var claim = Identity.FindFirst(claimType);
        if (claim != null) Identity.TryRemoveClaim(claim);
        Identity.AddClaim(new Claim(claimType, value ?? ""));
    }
}

To update the new Claims values in IPrincipal I execute authenticationManager.SignIn .

And this works perfectly throughout the application until the time for validating the cookie, as configured in Identity, is zeroed and validation is redone:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity =
            SecurityStampValidator.OnValidateIdentity<AppUserManager, Usuario>(

                TimeSpan.FromMinutes(30), // <-- Revalida os cookies de 30 em 30 minutos

                (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});

Then every 30 minutes cookies are revalidated / rebuilt as the GenerateUserIdentityAsync method of the User class, as also configured in the above code, losing the data that was previously included.

The issue is that users with a company profile can choose to switch to the% profile of%, choosing the affiliate, to be able to perform operations for it.

Because I do not have access to the current claims information within the Filial method, I can not re-place them in Claims.

My question is:
How can I do not to lose the current Claims information on cookie revalidations made at 30-minute intervals (as configured)?

I'm using VisualStudio 2015 Community with .Net 4.6. Thanks!

    
asked by anonymous 29.09.2015 / 15:32

1 answer

1

The problem with this revalidation is that you do not save session information anywhere. It is important to understand that Claims are different from session data.

There are two things you can do:

  • Serialize the list of Claims and store it within Session ;
  • Use a key-value server such as Redis and bring this user preference data there (also serializing the data and saving as a string ).
  • possible. Otherwise, you simply populate the Claims list as already done.

        
    29.09.2015 / 16:13