0
votes

I'm having issues with updating claims on ASP.Net Identity 2.2.1 in .Net 4.6.2 / MVC5. After updating a claim it will normally send an updated cookie to the browser and everything works fine but sometimes no set cookie header is sent to the browser.

I've not been able to identify any pattern as to when it happens other than when it is failing, the server is sending a

Persistent-Auth: true

http header value for every response in the session. I don't know what causes this header value to get set and it sometimes appears mid-session and once it starts sending it, it will be sent for the rest of the session and trying to update the claims will never work again for that session.

As far as I can see, I have hard-coded the isPersistent parameter to be false in every call into ASP.Net identity and I can't see anything else that could be related to this header.

The code I'm using for updating claims is

public static void UpdateClaims(List<Claim> claims)
{
    var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
    var newIdentity = new ClaimsIdentity(HttpContext.Current.User.Identity);

    foreach (Claim claim in claims)
    {
        Claim oldClaim = newIdentity.FindFirst(claim.Type);
        if (oldClaim != null && oldClaim.Type != "")
        {
            newIdentity.RemoveClaim(oldClaim);
        }
        newIdentity.AddClaim(claim);
    }
    authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant
          (new ClaimsPrincipal(newIdentity), new AuthenticationProperties { IsPersistent = false });
}

This is being called from an MVC action method.

Does anyone have any suggestions what might be going wrong or even just a starting point of where to look? I don't know what causes that persistent-auth header but it looks to be related to the problem; whether it is the cause or a symptom of the problem, I don't know.

I'm using ASP.Net Identity 2.2.1 with .Net 4.6.2. I'm running on Windows Server 2012R2 and the problem seems to occur with IE11, Chrome and Firefox. I'm using Fiddler 4.6.3 to view the http headers / responses.

Update: I have noticed that it seems to go wrong only when Windows authentication is enabled. My server has a setting that allows username/password, windows auth or both (user can choose to sign in as a different user using username/password). When windows auth is used, I initially authenticate the user using windows and then set a cookie, which I then use for all future requests in the session. If windows auth is disabled, updating the claims like this always works. If windows auth is enabled, updating the claims usually works.

4
I think you have to sign out and sign in to update claims in cookieSaravanan

4 Answers

16
votes

First, you're conflating two different things, although it's understandable since they're named similarly. The IsPeristent setting determines whether the cookie is a session-cookie or persistent cookie. In other words: it determines whether or not the cookie will expire when the browser is closed or at some predetermined time, whether or not the browser is closed.

The Persistent-Auth header is an optimization header that informs the client that it doesn't necessarily need to authorize each request. It has nothing to do with the IsPersistent flag.

Claims are set at login. Period. If you need to update the claims, you must sign the user out and sign them back in. This can be done programmatically (i.e. without user intervention), but it must be done. In other words, if you need to alter a claim, and you need that alteration to be available in the next request, then you follow it with:

Identity 2.0

AuthenticationManager.SignOut();
await SignInManager.SignInAsync(user);

Identity 3.0

await SignInManager.RefreshSignInAsync(user);
5
votes

Instead of

authenticationManager.AuthenticationResponseGrant = 
    new AuthenticationResponseGrant(new ClaimsPrincipal(newIdentity), 
    new AuthenticationProperties { IsPersistent = false });

you should use

authenticationManager.SignIn(
    new AuthenticationProperties { IsPersistent = false }, 
    new ClaimsPrincipal(newIdentity));
2
votes

I found the problem. It was using the wrong identity when it tried to update the claims. In my scenario there were two identity objects, one for windows authentication and one for cookie authentication. In most cases HttpContext.Current.User.Identity gets the cookie authentication object (which is the one with the claims) but occasionally it was giving me the windows authentication object, so when I tried to update the claims on that, it didn't do anything.

The problem was solved by replacing

var newIdentity = new ClaimsIdentity(HttpContext.Current.User.Identity);

with

ClaimsIdentity oldIdentity = claimsPrincipal.Identities.FirstOrDefault(i => i.AuthenticationType == "ApplicationCookie");
var newIdentity = new ClaimsIdentity(oldIdentity);

It now seems to work solidly without needing to sign out / back in again.

I guess the Persistent-Auth: true http header was being sent when OWin considered the Windows auth to be the primary identity so that is why its presence correlated with the inability to update claims.

0
votes

I believe in our case it was the wrong/long-term IoC lifetime/'scope' of the ApplicationUserManager & possibly the same for the role manager too.