Custom Principal set by SessionToken reverting to ClaimsPrincipal in Application PostAuthenticateRequest

392 Views Asked by At

I am developing an intranet Web App using windows auth. I am using Claims Transformation using custom ClaimsAuthenticationManager.

public class ClaimsTransformer : ClaimsAuthenticationManager
    {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            if (!incomingPrincipal.Identity.IsAuthenticated)
            {
                return base.Authenticate(resourceName, incomingPrincipal);
            }

        var newPrinciPal = CreateApplicationPrincipal(incomingPrincipal.Identity.Name);

        EstablishSession(newPrinciPal);

        return newPrinciPal;
    }

    private void EstablishSession(ClaimsPrincipal newPrinciPal)
    {
        var sessionToken = new SessionSecurityToken(newPrinciPal, TimeSpan.FromHours(8))
        {
            IsPersistent = false,
            IsReferenceMode = true
        };

        FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
    }

    private ClaimsPrincipal CreateApplicationPrincipal(string userName)
    {
        new SecurityManager().LoginUser(userName);

        var claims = new List<Claim>();

        claims.Add(new Claim(ClaimTypes.Name, userName));

        RPSUser originalIdentity = Thread.CurrentPrincipal.Identity as RPSUser;

        if (originalIdentity != null)
        {
            RPSUserInformation userDetails = originalIdentity.UserDetails;

            int splitIndex = userDetails.FullName.IndexOf(' ');
            claims.Add(new Claim(ClaimTypes.GivenName, userDetails.FullName.Substring(0, splitIndex)));
            claims.Add(new Claim(ClaimTypes.Surname, userDetails.FullName.Substring(splitIndex + 1)));
            claims.Add(new Claim(ClaimTypes.Email, userDetails.Email));
            claims.Add(new Claim(ClaimTypes.WindowsAccountName, userDetails.LanId));
        }

        RPSUser transformedIdentity = new RPSUser(new ClaimsIdentity(claims, "Custom"));
        transformedIdentity.UserDetails = originalIdentity.UserDetails;

        return new RPSPrincipal(transformedIdentity, null);
    }
}

In Global.ascx I have this code

protected void Application_PostAuthenticateRequest()
        {
            try
            {
                var newPrincipal = FederatedAuthentication.FederationConfiguration
                                            .IdentityConfiguration
                                            .ClaimsAuthenticationManager.Authenticate(string.Empty, ClaimsPrincipal.Current);

            SecurityManager.SetIdentityToThread(newPrincipal as RPSPrincipal);
        }
        catch
        {

        }
    }

Also I am able to retrieve/deserialize the Cookie from this piece of code in Global.asax

void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e) { var extendSession = true;

        if (Request.UrlReferrer.AbsolutePath.Equals("/"))
        {
            var principal = e.SessionToken.ClaimsPrincipal as RPSPrincipal;
            SecurityManager.SetIdentityToThread(principal);

            if (extendSession)
            {
                e.SessionToken = new SessionSecurityToken(
                    e.SessionToken.ClaimsPrincipal,
                    TimeSpan.FromHours(8))
                {
                    IsPersistent = false,
                    IsReferenceMode = true
                };

                e.ReissueCookie = extendSession;
            }
        }
    }

But the problem is even though I am able to deserialize the cookie to the custom Principal (RPSPrincipal) in this event and able to set it to thread, subsequently in the Application_PostAuthenticateRequest (for the same request) we are losing the Custom Principal. We are just getting ClaimsPrincipal there.

What am I doing wrong here? How could I ensure that windows authentication does not overwrite principal when there is a custom principal is already set and IsAuthenticated property of Identity is already set to true?

Or is there anyway to access the sessionSecurityToken at Application_PostAuthenticateRequest event?

0

There are 0 best solutions below