SpringBoot Injected Principal not null but SecurityContextHolder.getContext().getAuthentication() always null - Websocket

46 Views Asked by At

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????

        ...
    }
0

There are 0 best solutions below