-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Back-Channel Logout should use localhost for internal logout request #14553
Comments
@ch4mpy, good observation. I think we can change this:
to: String logout = UriComponentsBuilder.fromHttpUrl(url)
+ .host("localhost")
.replacePath(this.logoutEndpointName)
.build()
.toUriString(); to address the issue. |
@jzheaux thank you. |
In the production environment, the logout endpoint is accessed via https. e.g. So it seems like you need to change the schema and port to your own values. Or rewrite hostname to |
Rewriting only the host name to The application context-path is another thing to consider here, see #14181. One could use the internal host name/address and port number of the client in the server backchannel logout configuration, but only if the IDP (e.g. Keycloak) can access these internal hosts at all, which is often not possible. Could we replace the POST request for the local logout resource (LogoutFilter) with something else? |
I think this is a wrong assumption: a server should always be able to call itself with its internal scheme, host and port. The idea here was not to modify the hostname to which the OP sends the requests, just to change what the RP uses to call itself after it received the Back-Channel Logout request. Also, the path used for this additional call(s) is not the one of the Back-Channel Logout endpoint, it is the path of the RP "standard" logout. Note that in the case of a reverse proxy rewriting the path the previous impl could be broken too: if the request goes through the reverse proxy, the Sure that if one finds a way to perform the logout without this second network call, that would eliminate the problem, but I think it was discussed in another ticket already (couldn't remember which one). Updating the scheme, port and context path with the values we see in the logs after startup ( @jzheaux maybe would it be worth to:
Should I propose a PR for that ? |
I just ran into the problem with "localhost". I use a let's encrypt SSL certificate directly in the embedded Tomcat in the local development environment. Due to the host name localhost the handshake fails.
I would also welcome a configuration option. Many thanks and best regards! |
I confirm that the change in 2702a64 broke the use of back-channel logout in my application. As mentioned above, in a situation where the application sits behind a reverse proxy, the connection to, in my case, This is really a blocker for us to be able to upgrade to 3.2.3. |
I just wanted to implement OIDC back channel logout and got to the issue with "localhost" and found this ticket. In my experience, the app is never run on the same host and port as it is seen from the outside, there's always some proxying going on, be it on local nginx/haproxy or external nginx/haproxy/F5/whatever. Changing just the host to localhost may work in a very small minority of production environments. (Also note that the hostname is used for routing on the reverse proxy even in the case of local nginx; it may be used for other apps and relies on the hostname for routing to the correct one.) Let it at least be configurable... But I don't understand why it needs to do such internal requests against itself at all. The backchannel request came to the app via controllers, yes, it's a different session at that point, but we are inside the app and have access to the session registry. We are looking into it in the code to get the session ID for that token anyway, so it's not like it would be required for Spring Gateway or something. Why not just delete it right at that moment, why does it need to do the request? Some of you mentioned it was discussed somewhere, I'd like to read that discussion. |
I'm interested to know more as well. |
The internal logout URI was made configurable back in March: http.oidcLogout(ol -> {
ol.backChannel(bc -> {
bc.logoutUri("http://localhost:8080/logout");
});
}); This will work even behind a reverse proxy having different scheme and port. |
Describe the bug
Given I have:
When I try to visit a path requiring to be authorized on the Spring client, then I am redirected to login.
Once authenticated, I can access the protected resource.
When I visit the
end_session_endpoint
of the authorization server, then I can see aTRACE
log on the Spring client displaying:Found and removed 1 session(s) from mapping of 1 session(s)
However, if I refresh the tab pointing to the protected resource, I can still access it.
There are two log lines after the one stating that the session was removed:
Is the client trying to call its own
/logout
endpoint but using the wrong hostname?host.docker.internal
is the hostname used by the authorization server to initiate the Back-Channel Logout (which is running in Docker), but this hostname is unknown from the Spring client.Expected behavior
If the Spring client needs to call itself to actually destroy the user session, shouldn't it call
localhost
?Sample
https://github.com/ch4mpy/spring-security-14553
run
docker compose up
to create a new Keycloak instance (admin
/admin
to access http://localhost:8080/realms/master)create a new realm by importing
spring-security-realm.json
create a user
start the spring boot app
visit http://localhost:7080/
the
end_session_endpoint
is at http://localhost:8080/realms/spring-security/protocol/openid-connect/logoutThe text was updated successfully, but these errors were encountered: