2
I have an application that needs to control the access of users who are according to the profile of each one. Empresa
, Filial
.
In the User entity I added the fields referring to these other two entities and in them will be the information representing 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 method GenerateUserIdentityAsync
.
And then I created a class IdentityManager
to help obtain such information and update it when needed.
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 values of Claims in Iprincipal I run authenticationManager.SignIn
.
And this works perfectly throughout the application until the time for cookie validation, as set in Identity, Zera and validation is remade:
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))
}
});
So every 30 minutes cookies are revalidated/rebuilt as a method GenerateUserIdentityAsync
of the User class, as also configured in the above code, losing the data that were previously included.
The issue is that users with company profile can choose to change to the profile Filial
, choosing the subsidiary, in order to be able to carry out operations for it.
For not having access to current information of the Claims within the method GenerateUserIdentityAsync
, I can’t get them back in Claims.
My question is:
How could I avoid losing the current information of Claims in the revalidations of cookies made at 30 minute intervals (as per configuration)?
I’m using Visualstudio 2015 Community with . Net 4.6.
Grateful!
I was curious about the table
AspNetUserClaims
if you can’t store in it. Honestly, I haven’t seen it being used yet. Thank you for the answer!– JamesTK