Cookie Authentication Handler session key is re-used even when sign out is called before signing in
Is there an existing issue for this?
- [X] I have searched the existing issues
It's related to #47503 but slightly different
Describe the bug
CookieAuthenticationHandler.HandleSignInAsync re-uses the session key from the session store when a user signs in again.
This was fixed because of #22135, but if HttpContext.SignOutAsync is called prior to signing in, the session ID is re-used even though it's been removed from the store. ITicketStore.RenewAsync does not return whether the ticket was successfully renewed so the authentication handler expects the session to be present in the store.
Our application has use cases where the users may share devices (e.g. education, in schools), and the users may log in via IDP-initiated methods or directly from our application. We need to be able to sign them out and avoid re-using the session key between different users if a different user logs in.
Expected Behavior
The condition on line 339 should be changed to if (_sessionKey != null && !_signOutCalled) to avoid re-using the session key if a sign out request is made.
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
8.0.204
Anything else?
No response
We've reviewed this in the past and determined that it doesn't matter, the session key is not a unique id. Once the user object is removed from the session cache then the user is signed out and re-using the session key will not be able to retrieve any of that users creds. Have you found otherwise?
Note you also can't rely on the client to stop sending the original cookie, even if you ask nicely for it to be deleted. That's entirely up to them. That's why we remove the user object from the cache instead.
Limiting cookie turnover has other advantages for page caching, etc..
We sign out the previous users' session prior to signing in the current user. The re-used session key by the second user now references an invalidated session because the sign in doesn't generate a new session ID. The cookie authentication handler returns a valid cookie pointing to an invalid session, and subsequent requests to the server fail with the error Identity missing in session store.
We aren't relying on the session ID being unique, but an invalidated session ID is being assigned to a newly signed in user which is causing issues.
e.g.
- User A signs in, Session ID 1 is assigned to them
- User B tries to sign in on the same browser
- Application code calls
HttpContext.SignOutAsync(...);,ITicketStore.RemoveAsyncis called to invalidate Session ID 1 - Application code calls
HttpContext.SignInAsync(...)for User B inside the same request - Instead of calling
ITicketStore.StoreAsync,CookieAuthenticationHandleris callingITicketStore.RenewAsync, with Session ID 1 - That renewal does nothing because the session is invalid, but
SignInAsynccontinues to use Session ID 1 - User B receives a cookie with Session ID 1
- User B tries to do an authenticated action,
ITicketStore.RetrieveAsyncis called with Session ID 1, but fails because it's not valid
With the suggestion to generate a new session ID if _signOutCalled, step 5 would have a new session ID, and this issue wouldn't occur.
Instead of calling ITicketStore.StoreAsync, CookieAuthenticationHandler is calling ITicketStore.RenewAsync, with Session ID 1
While it may be counter-intuitive, renew can re-create the session with arbitrary content.
Practically speaking, it will be a lot quicker to change your ITicketStore to handle this case than to wait for .NET 9 (Nov?). And since it is easy to change locally it's unlikely to be a priority to change here.