Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable sliding expiration in IdentityServer

I am using IdentityServer3 for authentication and I have ASP.NET MVC application as Client. I want to setup sliding expiration of authentication cookie.

So as long as user is actively doing something in client application he should be logged in. If he remains inactive (with browser open) for more than 120 mins and then try to use client application then he should get redirected to log in page.

There are bunch of settings related to sliding expiration In IdentityServer3's IdentityServerOptions and also in client application's CookieAuthenticationOptions and OpenIdConnectAuthenticationOptions

On Identity Server i have the following configuration

app.Map("/identity", idsrvApp =>
            {
                idsrvApp.UseIdentityServer(new IdentityServerOptions
                {
                    SiteName = "Login",
                    SigningCertificate = LoadCertificate(),
                    RequireSsl = true,
                    Factory = new IdentityServerServiceFactory()
                        .Configure(),
                    AuthenticationOptions = new AuthenticationOptions()
                    {
                        CookieOptions = new CookieOptions()
                        {
                            AllowRememberMe = false,
                            SlidingExpiration = true                            
                        }
                    }
                    .Configure(ConfigureIdentityProviders),
                    EventsOptions = new EventsOptions().Configure(),
                    EnableWelcomePage = ApplicationConfig.EnableWelcomePage                    
                });
            });
        }

I have set the Client.IdentityTokenLifetime to 7200 seconds

In client application i have the following configuration

var cookieOptions = new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies",
                LoginPath = new Microsoft.Owin.PathString("/Home"),
                SlidingExpiration = true                
            };

var openIdOptions = new OpenIdConnectAuthenticationOptions
            {
                Authority = ConfigurationManager.AppSettings["id:Authority"],
                Scope = "openid email profile",
                ClientId = "XXXXXXXXX",
                RedirectUri = "http://localhost/Home",
                ResponseType = "id_token",
                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime = true,                
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = (context) =>
                    {
                         // do something
                    },

                    RedirectToIdentityProvider = (context) =>
                    {
                            // do something
                    },

                    AuthenticationFailed = context =>
                    {
                        // do something
                    }
                }
            };

            app.UseCookieAuthentication(cookieOptions);
            app.UseOpenIdConnectAuthentication(openIdOptions);

Note that i have set UseTokenLifetime to true so the cookie timeout will aligned with Client.IdentityTokenLifetime

ISSUE Even if the user is active for 120 mins, He gets logged out exactly after 120 mins.

What else i need to do enable sliding expiration?

(I have already gone through several post on SO and also IdentityServer's forum but no one has concrete answer)

like image 905
LP13 Avatar asked Oct 12 '17 20:10

LP13


People also ask

What is Cookie sliding expiration in identityserver?

o.Authentication.CookieSlidingExpiration is configuring the settings on the cookie authentication handler that IdentityServer automatically registers, but if you're using ASP.NET Identity then you're likely using theirs and not the one from IdentityServer. Sorry, something went wrong.

What happens when a session expires in identityserver?

Frequency expired sessions will be removed. Number of expired sessions records to be removed at a time. If enabled, when server-side sessions are removed due to expiration, will back-channel logout notifications be sent. This will, in effect, tie a user’s session lifetime at a client to their session lifetime at IdentityServer.

How do I configure Duende identityserver options?

The IdentityServerOptions is the central place to configure fundamental settings in Duende IdentityServer. You set the options at startup time in your ConfigureServices method: var builder = services.AddIdentityServer (options => { // configure options here.. }) Top-level settings.

Is the expiration time of the cookie set correctly?

The expiration time of the cookie is set correctly, however, the sliding expiration does not seem to work.


2 Answers

@thunk got me kind of on the right track here, and his answer is essentially what solved this issue for me and let me know what to search for to get an understanding. I just wanted to "add to it" in hopes that it will help someone else out.

I spent a considerable amount of time trying to figure this out, and it was compounded by lack of explanation in the samples and documentation. If you go through the MVC Getting Started for IdentityServer3, they sneak this UseTokenLifetime setting in on you (halfway through the example code) without mentioning that they added it or what its for. At first, they use this code (in the Startup.cs of your MVC app):

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://localhost:44319/identity",
    ClientId = "mvc",
    RedirectUri = "https://localhost:44319/",
    ResponseType = "id_token",

    SignInAsAuthenticationType = "Cookies"
});

Then later on they sneak in UseTokenLifetime:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://localhost:44319/identity",

    ClientId = "mvc",
    Scope = "openid profile roles",
    RedirectUri = "https://localhost:44319/",
    ResponseType = "id_token",

    SignInAsAuthenticationType = "Cookies",
    UseTokenLifetime = false,

    // other stuff continues...
});

As I was going through the tutorial and typing in my own code as I went, I missed the UseTokenLifetime = false being snuck in, and they didn't mention that it was done, or WHY it was done.

Here is a nice bit of info I found that confirms I'm not the only one with this confusion, and explains what is going on a little better

For posterity, what I found most confusing about this was that I can set a cookie lifetime in my cookie options:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
   ...
    ExpireTimeSpan = new TimeSpan(4, 0, 0),
    SlidingExpiration = true,
}); 

But if I don't know to override the OIDC defaults, that ExpireTimeSpan is ignored/overwritten.

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions    
{
    ...
    UseTokenLifetime = false, // have to know to do this for ExpireTimeSpan to be respected
    ...    
}); 

That behavior seems incredibly opaque to me. Not sure if it could be helped by different naming, or what, but it seems like it will be a common misunderstanding in practice, though I don't profess to understand the majority of use cases.

As a side note, the MSDN on the UseTokeLifetime property (the only place I can even find any documentation on this property!!!) is horrible:

Indicates that the authentication session lifetime (e.g. cookies) should match that of the authentication token. If the token does not provide lifetime information then normal session lifetimes will be used. This is enabled by default.

Not sure why they just don't come out and say that token lifetime information WILL overwrite the normal session times.

And all of that comes full circle back to what I still don't understand... From what I've read, the cookie lifetimes don't have anything to do with the validity or expiration of the authentication ticket that is inside the cookie. In other words, you can't just look at the expiration time on the cookie to know when your authentication expires. And I failed to understand that the settings in the CookieAuthenticationOptions don't actually control the cookie expiration time, they control the embedded authentication ticket expire time. From this blog post:

.AddCookie(options =>
{
    // Configure the client application to use sliding sessions
    options.SlidingExpiration = true;
    // Expire the session of 15 minutes of inactivity
    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
})

When I first configured this, I wrongly assumed that this would set the expiration of the cookie itself, as reflected in the browsers development tools. However, this is in fact a setting of the ticket that is stored inside the cookie, not of the cookie itself. It is this ticket that is evaluated by the MVC client whenever a request is handled. This ticket determines the validity of the users authentication session.

TL;DR

If UseTokenLifetime is not set or set to true, then your authentication ticket will be valid as long as your id_token is valid for (default 5 minutes).

If UseTokenLifetime is set to false, then your CookieAuthenticationOptions settings take over, namely ExpireTimeSpan and SlidingExpiration.

Anyway, hope this answer helps someone else gain enlightenment.

like image 94
Scuzzlebutt Avatar answered Sep 21 '22 16:09

Scuzzlebutt


SlidingExpiration is on your Cookie middleware only. As you are using the Token Lifetime, any setting you have here is overriden/ignored.

For it to become active UseTokenLifetime must be set to false. My experience so far is that UseTokenLifetime = false; must be set on both your openIdOptions on client and within the CookieOptions on IdentityServer.

like image 35
thunk Avatar answered Sep 21 '22 16:09

thunk