Manually set authentication with ReactiveSecurityContextHolder
Asked Answered
H

2

8

I'm trying to setup Spring Security with Spring Web Flux. I don't understand how to manually set the SecurityContext with ReactiveSecurityContextHolder. Do you have any resource or hint? Take for example this filter I've written that reads a JWT token and needs to set the authentication manually:

@Slf4j
public class JwtTokenAuthenticationFilter implements WebFilter {

    private final JwtAuthenticationConfig config;

    private final JwtParser jwtParser = Jwts.parser();

    public JwtTokenAuthenticationFilter(JwtAuthenticationConfig config) {
        this.config = config;
        jwtParser.setSigningKey(config.getSecret().getBytes());
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        String token = exchange.getRequest().getHeaders().getFirst(config.getHeader());
        if (token != null && token.startsWith(config.getPrefix() + " ")) {
            token = token.replace(config.getPrefix() + " ", "");
            try {
                Claims claims = jwtParser.parseClaimsJws(token).getBody();
                String username = claims.getSubject();
                @SuppressWarnings("unchecked")
                List<String> authorities = claims.get("authorities", List.class);
                if (username != null) {
                    UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null,
                            authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

                    // TODO set authentication into ReactiveSecurityContextHolder 
                }
            } catch (Exception ex) {
                log.warn(ex.toString(), ex);
                ReactiveSecurityContextHolder.clearContext();
            }
        }
        return chain.filter(exchange);
    }
}
Highline answered 3/4, 2019 at 15:26 Comment(0)
H
9

I managed to update the SecurityContext by calling:

return chain.filter(exchange).subscriberContext(ReactiveSecurityContextHolder.withAuthentication(auth));

Correct me if I'm wrong or if there is a better way to manage it.

Highline answered 4/4, 2019 at 7:7 Comment(4)
hi! Can you share the complete code excerpt? Thanks :)Stanchion
That's posted in the question!Highline
@AlessandroDionisi How did you figure this out? Is there any good source, besides wondering through the code?Cloakanddagger
subscriberContext is deprecated in Springboot 3.0Hame
M
3

I searched a lot about this issue and get this thing worked. You can try setting the context while passing the filter chain like below.

return chain.filter(exchange).contextWrite(ReactiveSecurityContextHolder.withAuthentication(authentication));
Mashburn answered 8/12, 2022 at 10:59 Comment(2)
What if you are getting your Authentication object in a reactive way? Like in a Mono<Authentication>Sawyer
@HatemMohamed Then map itTiruchirapalli

© 2022 - 2024 — McMap. All rights reserved.