IdentityServer / IdentityServer4

OpenID Connect and OAuth 2.0 Framework for ASP.NET Core
https://identityserver.io
Apache License 2.0
9.23k stars 4.02k forks source link

Token Expiration / Cookie Expiration issue #1549

Closed rposener closed 7 years ago

rposener commented 7 years ago

This is more of a question than a bug report. hopefully someone can help.

I have 3 apps that all auth now off IdentityServer4. All auth works great, but we are experiencing an issue where users get 403 Forbidden during an Ajax request after some time using the app. A full refresh of page will redirect back to IDSRV and get new access token, resuming operation. Obviously a cookie or token expiration is going on that I'm not handling well. Trying to isolate and understand the issue, I have a couple questions that I'm not clear on, which should help me figure out what is expiring.

IDSRV -> Issues Cookie for it's Local Auth IDSRV -> Sends Access_Token via redirect to the originating app App(MVC4) -> has CookieAuthentication (no automatic challenge or authenticate) App(MVC4) -> has OpenIdConnectAuthentication (/signin-oidc endpoint to receive token)

So the OpenIdConnectAuthentication takes the token, and issues a Cookie of it's own (SignInAsAuthenticationType).

So at the first bit, the App(MVC4) seems to end up with an expired cookie. That much I'm fairly certain of. What I don't know/understand is: Does it automatically set cookie expiration based on the token?
Should I set Cookie Expiration to Sliding?
How is expiration handled with a refresh token? Is that code I need to add, and how do I verify that my IDSRV is sending refresh_token?

Any tips/ thoughts of what I've missed would be greatly appreciated.

mackie1001 commented 7 years ago

So the AJAX calls are secured using the cookie rather than the client sending the access token explicitly? Is the access token (stored in the cookie I assume?) used by the backend to call other services?

rposener commented 7 years ago

@mackie1001 Yes - the cookie seems to be the way the ajax calls are authenticated. There is no access token explicitly provided. So that at the core is what expires. Question is how can/should this get refreshed using the refresh/access token? I assumed it would "just happen" with a normal setup (e.g. Owin with Cookie, then OpenIdConnectAuthentication that auths against the IdentityServer, and SignInAs set to Cookie).

It seems I must need to handle this situation somehow, but not sure how this should occur?

rposener commented 7 years ago

Anyone know how what happens between the OpenIdConnect provider and the Cookie provider? Any way to inspect this code, or trigger an event like 1/2 the OIDC lifetime has elapsed, so trigger a renew of access token, in order to get an updated cookie issued?

muqeet-khan commented 7 years ago

Looks like you need to renew your tokens. Take a look at this.

https://github.com/IdentityServer/IdentityServer4.Samples/blob/2bf6eed7d9d2be5214001d09d5a76f97e4a3c0f7/Clients/src/MvcHybrid/Controllers/HomeController.cs#L44

rposener commented 7 years ago

@muqeet-khan thanks for that tip, but I'm using MVC 5/Owin (asp.net) against ID Server4 (asp.net core) in this case.

This is how I have my configuration, which does not explain how to get the session to renew:

` // Default uses Cookie app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        // Use Cookies to Store JWT Token for Web Browsers
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        });

        // Authenticate to Auth Server
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                ClientId = "pe.app",
                Authority = ConfigurationManager.AppSettings["OpenIdAuthority"],
                ResponseType = "id_token",
                Scope = "openid profile",
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = n =>
                    {
                        n.ProtocolMessage.RedirectUri = n.OwinContext.Request.Uri.GetLeftPart(System.UriPartial.Authority) + "/PE/signin-oidc";
                        n.ProtocolMessage.PostLogoutRedirectUri = n.OwinContext.Request.Uri.GetLeftPart(System.UriPartial.Authority) + "/PE";
                        return System.Threading.Tasks.Task.FromResult(0);
                    }
                },
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },
            });

`

muqeet-khan commented 7 years ago

Ok, so you are using implicit flow. I am not sure how you are authenticating to the back end API (access_token). You should look at the IdSrv samples (may be Hybrid Flow is more suited in your scenario?) and go from there. The reason I cannot get you concrete answers is because I don't know the flow of your system design. I would suggest you make a test app with the IdSrv Hybrid flow sample and see if that works better for your design. All Samples here : https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Clients/src

rposener commented 7 years ago

Yes, it is implicit flow. It's actually really simple - users login to the site, then they are just calling WebApi methods. Our app is like a group of SPA's. Once they load the module - it just sits like a SPA, making calls with the Cookie and everything is happy. There is no further back-end service. The timeout occurs after they sit at a SPA for a while.

I have tried adding the option to use sliding expiration on the cookies Auth in the app, to see if it will refresh during one of the users transitions between the MVC pages. It seems the cookie is just getting expiration set by the expires after claim, but I don't see any means to trigger it to refresh.

At this point, it should refresh the cookie, but I don't know what's expected to happen if the Id Server expires? I guess the user will be fine as long as as the cookie can build a principal for the user, right?

leastprivilege commented 7 years ago

This seems to be a general question about IdentityServer - not a bug report or an issue.

Please use one of the our free or commercial support options

See here for more details.

Thanks!

DiginessForever commented 6 years ago

I found this aspnet issue about OIDC overwriting session cookie expirations: https://github.com/aspnet/Security/issues/147 At the end of that issue, everyone was happy, the ASP.NET Identity team decided to set UseTokenLifetime to false so it wouldn't overwrite. However, later, the issue may have started again when Azure B2C users complained about their B2C settings on token lifetime not being honored by webapps: https://stackoverflow.com/questions/43416837/b2c-web-app-session-lifetime After which, the ASP.NET Identity team again set it to true, meaning session cookies expirations are getting stomped on again (overwritten with the OIDC cookie expiration) if you don't explicitly set UseTokenLifetime (on your client webapp's app.UseCookieAuthentication(new CookieAuthenticationOptions { .... UseTokenLifetime = false, ...

Anyway, hope that helps someone. I haven't finished testing all my expiration settings yet, but thought that give and take was interesting. You can either set the UseTokenLifetime to false or set the cookie expiration again once you get the AuthorizationCodeReceived or SecurityTokenValidated events in the client middleware (after which OIDC won't stomp on it). I also haven't finished checking for anything further IdentityServer itself does to the cookie expiration.

DiginessForever commented 6 years ago

I also put a question up on StackOverflow if anyone wants to help dig at this issue: https://stackoverflow.com/questions/49325793/identityserver4-cookie-expiration

I'm currently more than a little stuck around this.

brockallen commented 6 years ago

After which, the ASP.NET Identity team again set it to true

in which release did they make this change?

DiginessForever commented 6 years ago

I don't know. However, if you set the expiration of the client cookie before it gets back to the client middleware with the SecurityTokenValidated event, it's not set.

For instance, if you do:

app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies",
                //Why does the below not work?
                ExpireTimeSpan = new TimeSpan(365, 0, 0, 0),  
                SlidingExpiration = true 
            });

Then it's not set, but then you can do (within the OpenIdConnectAuthenticationOptions block):

SecurityTokenValidated = (n) =>
{
    n.AuthenticationTicket.Properties.IsPersistent = true;
     n.AuthenticationTicket.Properties.ExpiresUtc = DateTime.Today.AddDays(365);

then the client cookie at least has its expiration set. I'm still stuck though because everything I've tried so far with setting the client/server cookie to be the same has resulted in me not getting claims back from Azure for some reason. I've replaced the nuget package with the source/project from github and will dig further.

DiginessForever commented 6 years ago

OK. Bad assumption on my part, read that wrong on the AspNet Identity: backtracking leads to this - it's actually just an Azure sample:
https://github.com/Azure-Samples/active-directory-b2c-dotnetcore-webapp/issues/19 So that's not the problem then. I am sorry for jumping to conclusions there. I had been reading these forums all day getting nowhere with this issue, was not thinking clearly.

DiginessForever commented 6 years ago

So, a review of the overall issue - here's my understanding so far: If I want to set sessions to expire later, I need to set the cookie expiration on client and server and either set UseTokenLifetime to false or set the individual token lifetimes. Still working on the server cookie flow with Azure.

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.