While you have updated the authentication cookie timeout, the openid token inside still expires every 15 minutes. So a new openid token is required. You will then need to re-add the custom role values.
Custom claims are not kept after 15 minutes
is in Hello,
I developed an ASP.NET MVC application which uses ASP.NET Identity 2 and OWIN to provide authentication.
All works perfectly but authentication after I changed cookie duration to 30 days (it was 15 minutes before, the default).
I have this in Startup.Auth.cs file:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
ExpireTimeSpan = TimeSpan.FromDays(30),
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
CookieName = "ExampleName",
CookieDomain = ".example.cl"
});
Just after user was authencated, I add some claims, this way:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
if (manager == null)
return null;
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie).ConfigureAwait(false);
var nombre = string.Concat(this.FirstName, " ", this.LastName).Trim();
if (string.IsNullOrEmpty(nombre))
{
var regexp = new System.Text.RegularExpressions.Regex("([^@]+)");
var matches = regexp.Matches(this.Email);
if (matches.Count > 0)
nombre = matches[0].Value;
else
nombre = "Sin nombre";
}
var email = this.Email;
if (string.IsNullOrEmpty(email))
email = "No definido";
userIdentity.AddClaim(new Claim(ClaimTypes.GivenName, nombre));
userIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
foreach(var roleName in this.RoleNames)
userIdentity.AddClaim(new Claim("Roles", roleName));
userIdentity.AddClaim(new Claim(Helpers.Constantes.ClienteTrabajoNombre, this.CustomerName ?? string.Empty));
userIdentity.AddClaim(new Claim(Helpers.Constantes.ClienteTrabajoId, this.CustomerId.ToString()));
userIdentity.AddClaim(new Claim(Helpers.Constantes.ClienteAsignadoId, this.CustomerId.ToString()));
// Si sólo hay una empresa asociada, debe ser la empresa seleccionada por defecto. -1 indica que no hay selección.
if (this.CompanyIds.Count == 1)
{
userIdentity.AddClaim(new Claim(Helpers.Constantes.EmpresaTrabajoId, this.CompanyIds[0].ToString()));
userIdentity.AddClaim(new Claim(Helpers.Constantes.EmpresaTrabajoNombre, this.CompanyNames[0].ToString()));
}
else
{
userIdentity.AddClaim(new Claim(Helpers.Constantes.EmpresaTrabajoId, "-1"));
userIdentity.AddClaim(new Claim(Helpers.Constantes.EmpresaTrabajoNombre, string.Empty));
}
string userId = userIdentity.GetUserId();
foreach (var claim in userIdentity.Claims)
{
this.Claims.Add(new IdentityUserClaim()
{
ClaimType = claim.Type,
ClaimValue = claim.Value,
UserId = userId
});
}
return userIdentity;
}
}
when debugging, I can see these claims:
identity.Claims.ToList()
Count = 13
[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 2}
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: jperez}
[2]: {http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity}
[3]: {AspNet.Identity.SecurityStamp: b98020c4-f1d6-42d6-9275-ff7975bc75dd}
[4]: {http://schemas.microsoft.com/ws/2008/06/identity/claims/role: 1}
[5]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: Example Name
[6]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: jperez@example.com}
[7]: {Roles: Administrador}
[8]: {ClienteTrabajoNombre: }
[9]: {ClienteTrabajoId: -1}
[10]: {ClienteAsignadoId: -1}
[11]: {EmpresaTrabajoId: -1}
[12]: {EmpresaTrabajoNombre: }
Claims from 8 to 12 are my custom ones.
And later I update the custom claims this way:
public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value)
{
if (currentPrincipal != null)
{
if (!(currentPrincipal.Identity is ClaimsIdentity identity))
return;
// check for existing claim and remove it
var existingClaim = identity.FindFirst(key);
if (existingClaim != null)
identity.RemoveClaim(existingClaim);
// add new claim
identity.AddClaim(new Claim(key, value));
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity, new AuthenticationProperties() { IsPersistent = true });
}
}
The fact is that, after 15 minutes, the custom claims get lost. Only predefined claims are kept.
When debugging, this appears in immediate window:
identity.Claims.ToList()
Count = 13
[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 2}
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: jstuardo}
[2]: {http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity}
[3]: {AspNet.Identity.SecurityStamp: b98020c4-f1d6-42d6-9275-ff7975bc75dd}
[4]: {http://schemas.microsoft.com/ws/2008/06/identity/claims/role: 1}
[5]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: Jaime Stuardo}
[6]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: ******@desytec.com}
[7]: {Roles: Administrador}
[8]: {ClienteTrabajoNombre: }
[9]: {ClienteTrabajoId: -1}
[10]: {ClienteAsignadoId: -1}
[11]: {EmpresaTrabajoId: -1}
[12]: {EmpresaTrabajoNombre: }
As you see, my custom claims get back to the values I set when user just logged in GenerateUserIdentityAsync
method.
How is the correct way to set my custom claims and to persist in the authentication cookie?
Thanks
Jaime
Developer technologies | ASP.NET | Other
1 answer
Sort by: Most helpful
-
Bruce (SqlWork.com) 78,236 Reputation points Volunteer Moderator
2022-06-05T22:37:07.413+00:00