DuendeSoftware / Support

Support for Duende Software products
20 stars 0 forks source link

Revoking grants doesn't log user out at Identity Server #1332

Closed stumckeenz closed 3 weeks ago

stumckeenz commented 2 months ago

Which version of Duende IdentityServer are you using?

7.0.4

Which version of .NET are you using?

8.0.3

Describe the bug

delete all persisted grants for a user directly from the database. User remains logged in to the identity server via the browser. I would expect that deleting all grants would invalidate all refresh tokens, effectively logging the user out. However it seems the identity server itself doesn't use a client or explicit grants.

Additional Context

I am trying to implement a feature where the user can see all/revoke any sessions(refresh token grants) they are logged into.

I found the IPersistedGrantService/DefaultPersistedGrantService, which seems to aggregate grants per consented client.

I don't use client consents so the DefaultPersistedGrantService was showing no grants for me. Instead, I made an adaptation of this service, to fetch and revoke grants of types authorization_code and refresh_token. These are the only grants in the database that I can see, and the only ones I would expect based on my implementation.

However, when I revoke all grants - the user remains logged in at id.myDomain.com. Because the identity server itself doesn't seem to be considered a client. Therefore, when the client application in that same browser performs an OIDC redirect, it automatically gets granted because the user is still logged in to the server. In this way, I am unable to revoke the session's access.

When I revoke the grants for my native application, surely enough the refresh fails and says the refresh token is no longer valid. However, then I prompt the user to log in via browser OIDC, which succeeds because they remain logged in at id.myDomain.com.

The scenario I'm trying to achieve is this:

User is logged in to myIdentityServer.com in Browser1, and visits reactApp.myDomain.com in a different tab in the same browser.

Attack gains access to user's computer.

User logs in to myIdentityServer.com in Browser2 and revokes all grants for all clients. This should cause Browser1 to be logged out from id.myDomain.com and reactApp.myDomain.com.

However, browser1 is not being logged out, and I don't see any grants issued for myIDS.com when the user logs in.

How do I fix this? How is the IDS remaining logged in? Presumably it's using refresh tokens, but I don't see them as grants. Is there some way to use explicit grants for the identityServer client?

What am I doing wrong?

Thanks in advance

RolandGuijt commented 1 month ago

The session cookie set by IdentityServer after a successful login with web clients is self-contained by default. That means that as long as the cookie lives IdentityServer will assume a valid user without any questions asked.

With the Server-Side Sessions you can deviate from that default. With that enabled, only the session state is kept in a store and the cookie only refers to that. Each time the cookie is received the store is queried. This could be a solution to your problem since Server-Side Sessions give you the option to revoke. And the revocation will be effective during the next request to the identity provider.

RolandGuijt commented 1 month ago

@stumckeenz Did my comment help you out? If so I'd like to close this issue.

stumckeenz commented 1 month ago

Yes, upon reading about Server-Side Sessions it certainly seems like that addresses the issue.

It's a business-licence feature though, so I'm not sure if we'll proceed with that strategy yet. I'll try it out in a dev environment first to ensure it works.

Thanks for your help

stumckeenz commented 1 month ago

Hi @RolandGuijt, Once using Server-Side Sessions - how do you revoke the user's session? Have you got any code samples / examples that demonstrate this?

RolandGuijt commented 1 month ago

Yes, here is an example.

RolandGuijt commented 3 weeks ago

@stumckeenz I you've something to add to this issue please do so. Else I'd like to close it.