Open jobannon opened 1 year ago
Using the account jwt side-load isn't a proper workaround for this. It is going to cause confusion over what it is in the fusionauth.sso cookie which can lead the browser getting into a bad state.
Added surrogate application workaround steps
It should be noted that the current behaviour can pose a security issue, since the self-service account feature can potentially provide a way to set a new user password without further authentication (i.e. subject to whether or not the 'Require current password' option added via https://github.com/FusionAuth/fusionauth-issues/issues/1578 is enabled or not).
There is also potential to change email address (e.g. which could enable authentication via magic link) without further authentication (as far as I can tell, the only "defence" against this aspect is to enable the Email update
email template which sends a notification old + new email on change, but it doesn't prevent the attack: just notifies someone that it happened).
If a public/shared computer is used, an attacker can gain access to a previously "logged out" session (i.e. applications/SSO was logged out, but not the self-service account management session), and then take over the affected account!
Added surrogate application workaround steps
@lyleschemmerling please can you clarify
Attempting to follow your surrogate application workaround steps verbatim:
Real application: 5f921ed5-1700-4f25-8ec4-7db9b267c96a
Surrogate logout application: 59e7200e-47c4-49ff-8f53-d4b461dbfbe6
My test user is registered to real application, and has an existing self-service account session. I set the logout URL of surrogate logout application to https://<MY_FUSIONAUTH_HOST>/account/logout/5f921ed5-1700-4f25-8ec4-7db9b267c96a
(replacing MY_FUSIONAUTH_HOST
- obviously).
Then I point my (test user) browser at the logout URL of the surrogate logout application: https://<MY_FUSIONAUTH_HOST/oauth2/logout?client_id=59e7200e-47c4-49ff-8f53-d4b461dbfbe6
I got a HTTP 500, with this in the logs:
2023-09-22 12:02:13.693 PM ERROR io.fusionauth.app.primeframework.error.ExceptionExceptionHandler - An unhandled exception was thrown
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) [Guice/ErrorInjectingConstructor]: NullPointerException: Cannot read field "oauthConfiguration" because "<parameter1>" is null
at LogoutAction.<init>(LogoutAction.java:23)
while locating LogoutAction
...
2023-09-22 12:02:13.714 PM ERROR org.primeframework.mvc.PrimeMVCRequestHandler - Error encountered
java.lang.NullPointerException: Cannot read field "actionURI" because "actionInvocation" is null
I thought maybe you had a typo and the Logout URL
was supposed to be set to https://<MY_FUSIONAUTH_HOST>/account/logout?client_id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
(rather than /account/logout/377e77a7-e066-4896-b3b4-5c2bbaec96e0
) but that variant also led to a HTTP 500:
2023-09-22 12:06:07.062 PM ERROR io.fusionauth.app.primeframework.error.ExceptionExceptionHandler - An unhandled exception was thrown
com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) [Guice/ErrorInjectingConstructor]: NullPointerException: Cannot read field "oauthConfiguration" because "<parameter1>" is null
at LogoutAction.<init>(LogoutAction.java:23)
while locating LogoutAction
...
2023-09-22 12:06:07.064 PM ERROR org.primeframework.mvc.PrimeMVCRequestHandler - Error encountered
java.lang.NullPointerException: Cannot read field "actionURI" because "actionInvocation" is null
Am I doing something wrong with my steps, or is the proposed workaround faulty?
For the record, the following workaround seems to be viable for my use case:
Assuming a single (real) application with ID: 5f921ed5-1700-4f25-8ec4-7db9b267c96a
https://<MY_FUSIONAUTH_HOST>/account/logout?client_id=5f921ed5-1700-4f25-8ec4-7db9b267c96a
<a href="${request.contextPath}/account/logout?client_id=${client_id}">
5f921ed5-1700-4f25-8ec4-7db9b267c96a
) configuration:
Hope this helps someone else facing the same.
@dransome apologies in the delayed response. I'm glad you got this working. The intent of the workaround was for the main application to call its logout endpoint like normal, and this action would trigger the side effect of invoking logout of "all applications" including the surrogate and self-service account applications.
We do have work in progress with a proper fix for this issue but I do not have an ETA for its delivery at the moment.
@lyleschemmerling seems that my workaround creates its own problem.
We noticed intermittent HTTP 500 errors from the logout URL. (https://<MY_FUSIONAUTH_HOST>/account/logout?client_id=5f921ed5-1700-4f25-8ec4-7db9b267c96a
).
My working theory is this happens if the user has not visited the FusionAuth self-service pages, and as a result, maybe FusionAuth doesn't find a session for that user?
When searching for logs, I found that it was the same error that I posted earlier. Is this just a result of what I'm doing with the workaround attempt(s), or a separate FusionAuth bug in its own right?
It seems that FusionAuth ought not to explode (HTTP 500) if you attempt to log out on a non-existent(?) session?
Another option is to listen for refresh token revocation events and if a token for application 377e77a7-e066-4896-b3b4-5c2bbaec96e0is revoked, revoke the refresh token held for /account as well.
I don't believe the refresh token for account is visible. I tried to find it but was unable to see it on either the admin screen or the API. When I deleted all the sessions for a user using the 'delete all sessions' button in the admin UI, my account session remains alive.
It seems like front channel logout to https://<MY_FUSIONAUTH_HOST>/account/logout?client_id=...
is the best option.
Self-service account session revocation
Problem
In FusionAuth version
1.45.0
the self-service themed pages no longer use the SSO session, and instead have a discrete session.Logging out of SSO, or your own application will not necessarily log you out of the session held for the
/account
pages which is essentially an extension of your own application.For example, if you are logged into application A with a
client_id
of377e77a7-e066-4896-b3b4-5c2bbaec96e0
and then navigate to/account/?client_id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
you will now have a new access token and refresh token for this application. This session is held in http only secure cookies.If you then log out of SSO or your own application, the state for the
/account
pages is still valid.In order to logout of the
/account
session, you need to make aGET
request to/account/logout?client_id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
.Solution
One option would be to use single logout and then when logging out of an app w/ self-service enabled, we add another URL to the list of other application logout URLs for
/account/logout?client_Id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
.Another option is to listen for refresh token revocation events and if a token for
application
377e77a7-e066-4896-b3b4-5c2bbaec96e0is revoked, revoke the refresh token held for
/account` as well.Needs more investigation.
Observed in version
1.45.3
Affects versions
>= 1.45.0
Workarounds
GET /account/logout?client_id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
Only side load the account with an existing access token using theAuthorization
header.This has limited use because you will need to be able to set the request header. This is generally done from a mobile app opening a web view.377e77a7-e066-4896-b3b4-5c2bbaec96e0
and you are using the/account/?client_id=377e77a7-e066-4896-b3b4-5c2bbaec96e0
route for self-service create a NEW application in FusionAuth under the same tenanthttps://<YOUR_FUSIONAUTH_HOST>/account/logout/377e77a7-e066-4896-b3b4-5c2bbaec96e0
All applications
Related
Additional context
Internal:
Community guidelines
All issues filed in this repository must abide by the FusionAuth community guidelines.
How to vote
Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.