简体   繁体   中英

Obtain IsPersistent setting from IdentityServer4 openIdConnect

I have a asp.net MVC/angular app (not .net core) using OpenIdConnect to authenticate against our IdentityServer4 server. The login page on the identity server has a "Remember Me" checkbox which sets the Identity Server cookie expiration. If the checkbox is not set the cookie expiration is set to expired so the cookie is flushed when the browser closes. The client MVC app also builds a client application cookie. I'd like that cookie's expiration to match the identity server cookie expiration. I can set the cookie expiration values to be the same on the identity server and client, but this case only works when the peristence state matches.

ex. If the user doesn't choose remember me on the identity server login and the client app uses the expiration as it normally would, the identity server cookie is flushed when the browser closes where the client app cookie does not get deleted. The next time the user navigates to the site it looks to the user as if they are logged in. Once they try to access a page secured by identity server (we use the ResourceAuthorization) they are then redirected to the identity server login page. I would rather have the client cookie deleted so when the user returns it doesn't look like they are still logged in.

I was looking through OpenIdConnectAuthenticationNotifications at the SecurityTokenValidated event. This is where the OpenIdConnect successful auth returns to. In here we build up the client app authenticationTicket. When creating this ticket it would be nice to know at the very least if the identity server's cookie was persistent or what that cookie's expiration is. the protocolMessage in here only seems to contain information about the token. the token expiration doesn't match the cookie expiration. Is there a way to get these cookies in sync? Am I missing something?

Old post. Answering so that any other dev's can use the approach.

This is how I solved it

right after the signin is done in identity, we can set a cookie that holds the persistance value.

var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
    _logger.LogInformation("User logged in.");
     this.SetPersistanceCookie(model.RememberMe);
     return RedirectToLocal(returnUrl);
}

private void SetPersistanceCookie(bool rememberMe)
{
        // setting persistant cookie, so that client app can set persistance of the application cookie in accordance with identity cookie
        var persistanceCookieOptions = new CookieOptions
        {
            HttpOnly = true,
            Secure = true,
        };
        HttpContext.Response.Cookies.Append("IsPersistant", rememberMe.ToString(), persistanceCookieOptions);
}

And now that this cookie is set, you can use this cookie value to set persistance of application cookie in OnTicketReceived event.

options.Events.OnTicketReceived = async context =>
{
// if for any reason we don't get IsPersistant Cookie (Which is used to set persistance of application cookie from identity cookie)
// we will set Application Cookie to non persistant (i.e. session life time)
       bool rememberMe = context.Request.Cookies.ContainsKey("IsPersistant")
             ? context.Request.Cookies["IsPersistant"].Contains("True")
             : false;
       var authenticationProperties = new AuthenticationProperties()
       {
            IsPersistent = rememberMe,
            ExpiresUtc = DateTime.UtcNow.AddDays(6),
            IssuedUtc = DateTime.UtcNow
       };

       context.Properties = authenticationProperties;
       await Task.FromResult(0);
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM