How to enable sliding expiration in IdentityServer
Asked Answered
H

2

6

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)

Holytide answered 12/10, 2017 at 20:33 Comment(1)
Did you ever find the answer to this?Ellary
S
9

@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.

Saransarangi answered 12/4, 2019 at 19:30 Comment(2)
learn.microsoft.com/en-us/dotnet/api/… says that on their side it's false by default. Maybe that's why I noticed that my IdentityTokenLifetime of the IdentityServer client settings is ignored? Also, one more caveat was that cookie expiration is always set to Session; it's only the ticket that is affected by those ExpireTimeSpan, SlidingExpiration and UseTokenLifetime settings.Confraternity
Also, the latest IdentityServer4 examples do not have UseOpenIdConnectAuthentication at all - it's enough to call `app.UseIdentityServer(). And UseOpenIdConnectAuthentication is marked as obsolete by Microsoft.Confraternity
Y
1

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.

Yarmouth answered 9/5, 2018 at 8:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.