DuendeSoftware / Support

Support for Duende Software products
21 stars 0 forks source link

Logout from iOS app without cookies #1405

Open bednart opened 1 month ago

bednart commented 1 month ago

Which version of Duende IdentityServer are you using? 7.0.6

Which version of .NET are you using? .NET 8

Hi, I have implemented AspNetIdentity together with OIDC and it works great for desktop browsers and Android app where cookies work well. Problem is with iOS where cookies are not sent with requests. Main problem is with logout requests and ticket store.

I have configured ITicketStore for default Identity.Application scheme

services.AddSingleton<ITicketStore, SqlTicketStore>();
        services.AddOptions<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme)
            .Configure<ITicketStore>((options, store) =>
            {
                options.SessionStore = store;
                options.ExpireTimeSpan = TimeSpan.FromDays(14);
                options.SlidingExpiration = true;
            });

If there is a logout request using connect/endsession endpoint than CookieAuthenticationHandler.HandleSignOutAsync() method is called internally which, if threre is a cookie sent with request, successfully deletes ticket from session store.

Problem is with iOS mobile app. By default no cookie is send together with logout request so no ticket is deleted from session store and sessions remains there forever (if there is no automatic deletion of expired tickets).

So my questions are. What is the best practice using OIDC and iOS? Should we make sure than cookies are also sent on iOS or is there another way how to delete ticket from session store without cookie?

What I tried was to add [Authorize] attribute on account/logout endpoint which is internally called after connect/endsession endpoint is processed. Than iOS app sends accessToken together with connect/endsession request and ticket from session store was deleted manualy using sid (session ID) claim from HttpContext.User. But I am not sure if this is right way.

Thanks for your help.

Tomáš

RolandGuijt commented 4 weeks ago

Is there a reason you want the iOS app to actively participate in the management of the session?

I'm asking because normally native applications will just abandon the session and IdentityServer will automatically clean it up after a while. The settings around that can be found here.

bednart commented 3 weeks ago

Hi, that's a really good question :) Honestly I lived with that connect/endsession should always be called on logout. From confidential and also public clients. Main concern is about security. What if attacker steal refresh token? Even if client logged out from mobile app the ticket is still active on server.

We are using ITicketStore and also IPersistedGrantStore using AddPersistedGrantStore extension. And if there are records in both tables after logout for given user than attacker can still get new access token using connect/token endpoint.

Or I am too cautious and thinking about non realistics scenarios? :)

RolandGuijt commented 1 week ago

Important to keep in mind here is that session and refresh token are separate. When the session expires, tokens may still be refreshed and when the refresh token expires there might still be a session. As a sidenote: IdentityServer offers a way to synchronize the two with the CoordinateClientLifetimesWithUserSession option. But that's not really relevant for your case.

With a native application like your iOS app the session itself isn't the main thing. It can be kept very short. The refresh token mechanism is important because that enables the application to continuously use the APIs it depends on. The refresh token is a valuable target for attackers but in a native applications the likelihood of it getting stolen is not nearly as high as in an application that involves the browser. Because browser applications are susceptible to all kinds of attacks such as XSS that are not possible with a native application. The risk isn't zero but it is often seen as an acceptable risk.

So without knowing the exact nature of your application in general it's OK to let the session expire without actively closing it. When the user actively want to "log out" instead you could consider revoking the refresh token using the revocation endpoint.

RolandGuijt commented 4 days ago

@bednart Are your questions answered regarding this issue? If so I'd like to close it.

bednart commented 3 days ago

@RolandGuijt More or less yes :) Thanks for different perspective into this. I will try to use revocation endpoint instead of connect/endsession for mobile clients. It makes sense to ignore cookies at all for mobile. One more thing before closing. Is it possible to set different cookie lifetime for mobile and desktop clients?