Search code examples
c#.netowinclaims-based-identityws-federation

Persisting new claims across requests


How do I add the new claims in such a way that they persist through requests until the cookie expires?

I am using OWIN middle ware, on-premises authentication to authenticate the users logging into the system.

The sign-in part is successful, and I added Roles to the user claims provided by the ws-federation to help authorize the user for certain action methods. At the time of login, in the controller, I have written the following to add the roles:

string[] roles = { "Role1", "Role2" };

var identity = new ClaimsIdentity(User.Identity);
foreach (var role in roles)
{
    identity.AddClaim(new Claim(ClaimTypes.Role, role));
}

var authenticationManager = HttpContext.GetOwinContext().Authentication;

authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant
                             (new ClaimsPrincipal(identity),
                              new AuthenticationProperties { IsPersistent = true });

But when I check the claims at the next request, I don't see the role claims.


Solution

  • After successful authentication I believe you added custom claims (normally to some event handler once successfully authenticated). Now in order to persist that information in subsequent request you need to use CookieAuthentication middle ware before your authentication owin in pipeline.

    How it works :

    Upon successful authentication first time and addition of custom claims, claims will be transformed into sort of auth cookie and sent back to client. Subsequent request will carry this auth cookie. CookieAuthentication middle ware on finding auth cookie will set your Thread.CurrentPriciple with claims obtained from cookie.

    During first time request when cookie middle ware does see any auth cookie, it passes request to next middle ware in pipe line (Authentication owin in your case) to challenge user for login.

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    
    app.UseCookieAuthentication(new CookieAuthenticationOptions()
                {
    
                    AuthenticationType = "Cookies",
                    AuthenticationMode= AuthenticationMode.Active,
                    CookieName="XXXXX",
                    CookieDomain= _cookiedomain,
                    /* you can go with default cookie encryption also */
                    TicketDataFormat = new TicketDataFormat(_x509DataProtector),
                    SlidingExpiration = true,
                    CookieSecure = CookieSecureOption.Always,
                });
    
    
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
                {
    
                    ClientId = _clientID,
                    Authority = _authority,
                    RedirectUri = _redirectUri,
                    UseTokenLifetime = false,
    
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
    
                        SecurityTokenValidated = SecurityTokenValidated,
    
                        AuthenticationFailed = (context) =>
                        {
                            /* your logic to handle failure*/
                        }
                    },
    
                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidIssuers = _validIssuers,
                        ValidateIssuer = _isValidIssuers,
                    }
                });
    

    EDIT: (Additional information)
    Pretty much the exact code as above works for ws federation also, with the same logic and everything.

    SecurityTokenValidated = notification =>
    {
        ClaimsIdentity identity = notification.AuthenticationTicket.Identity;
        string[] roles = { "Role1", "Role2" };
        foreach (var role in roles)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, role));
        }
        return Task.FromResult(0);
    }