'Spring RSocket over WebSocket - Access user information from HTTP session
In my web application, users login using a username/password combination and get a session cookie. When initiating a WebSocket connection, I can easily access the user information in the WebSocketHandler, for example:
@Component
public class MyWebSocketHandler implements WebSocketHandler {
@Override
public Mono<Void> handle(WebSocketSession session) {
// two ways to access security context information, either like this:
Mono<Principal> principal = session.getHandshakeInfo().getPrincipal();
// or like this
Mono<SecurityContext> context = ReactiveSecurityContextHolder.getContext();
//...
return Mono.empty();
}
}
Both reuse the HTTP session from the WebSocket handshake, I don't have to send additional authentication over the WebSocket itself. With STOMP the same thing applies: I can just reuse the information of the HTTP session.
How do I achieve the same thing using RSocket? For example, how would I get information about the user inside a MessageMapping method like this?:
@Controller
public class RSocketController {
@MessageMapping("test-stream")
public Flux<String> streamTest(RSocketRequester requester) {
// this mono completes empty, no security context available :(
Mono<SecurityContext> context = ReactiveSecurityContextHolder.getContext();
return Flux.empty();
}
}
I found many resources how to setup authentication with RSocket, but they all rely on an additional authentication after the WebSocket connection is established, but I specifically want to reuse the web session and don't want to send additional tokens over the websocket.
Solution 1:[1]
Have you tried the following? I found it in the documentation: 2.2 Secure Your RSocket Methods (might have to scroll down a bit) https://spring.io/blog/2020/06/17/getting-started-with-rsocket-spring-security
@PreAuthorize("hasRole('USER')") // (1)
@MessageMapping("fire-and-forget")
public Mono<Void> fireAndForget(final Message request, @AuthenticationPrincipal UserDetails user) { // (2)
log.info("Received fire-and-forget request: {}", request);
log.info("Fire-And-Forget initiated by '{}' in the role '{}'", user.getUsername(), user.getAuthorities());
return Mono.empty();
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tom Cools |
