In any HTTP request, I managed to get the principal from the SecurityContextHolder. But in case of a WS one, I can't. Here is the code
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
String token = request.getURI().getQuery().substring(13);
Base64.Decoder decoder = Base64.getUrlDecoder();
String[] chunks = token.split("\\.");
User user = null;
try {
String payload = new String(decoder.decode(chunks[1]));
user = new ObjectMapper().readValue(payload, User.class);
UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(user, null, user.getGrantedAuthorities());
usernamePasswordAuthentication.setDetails(user);
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthentication);
} catch (Exception ex) {
System.out.println(ex);
}
Principal principal = SecurityContextHolder.getContext().getAuthentication();
System.out.println("PRINCIPAL HANDSHAKE:" + principal); //prints correctly my principal with all the data from the token
return principal;
}
Here is the configureClientInboudChannel. I always start with a null principal but in the end, it's correctly set.
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
System.out.println(++counter);
Principal principal = SecurityContextHolder.getContext().getAuthentication();
System.out.println("PRINCIPAL:" + principal); // null so far
StompHeaderAccessor accessor = MessageHeaderAccessor
.getAccessor(message, StompHeaderAccessor.class);
...
Base64.Decoder decoder = Base64.getUrlDecoder();
String[] chunks = jwt.split("\\.");
try {
String payload = new String(decoder.decode(chunks[1]));
User user = new ObjectMapper().readValue(payload, User.class);
UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(user, null, user.getGrantedAuthorities());
usernamePasswordAuthentication.setDetails(user);
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthentication);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
principal = SecurityContextHolder.getContext().getAuthentication();
System.out.println("PRINCIPAL:" + principal); // shows correct logged in user
accessor.setUser(authentication);
} catch (Exception ex) {
System.out.println(ex);
}
return message;
}
});
But in my Controller
@MessageMapping("/hello")
public Message hello(@Payload Message message, Principal principal) {
System.out.println("PRINCIPAL TEST INJECTED: " + principal); //prints the previous principal
Principal retrievedPrincipal = SecurityContextHolder.getContext().getAuthentication();
System.out.println("PRINCIPAL TEST RETRIEVED: " + retrievedPrincipal); // is null, WHY????
...
}