Reputation: 699
I have set up authentication in a Spring WebFlux application. The authentication mechanism appears to work fine. For example the following code is used to set up security web filter chain:
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/path/to/resource").hasAuthority("A_ROLE")
.anyExchange().authenticated()
.and().httpBasic()
.and().build();
}
This works as expected in conjunction with the UserDetailsRepositoryReactiveAuthenticationManager and MapReactiveUserDetailsService. If a user doesn't have the required authority a forbidden error code is returned and otherwise the request is passed on to the handler.
I have a requirement to apply fine grained permission checks within the handler itself and figured that I should be able to retrieve the authorities from the request as follows:
public Mono<ServerResponse> getMyResource(ServerRequest serverRequest) {
Authentication authentication = (Authentication)serverRequest.principal().block();
...
}
However, I find that the principal is always null. First, is this the correct way to get a handle on the authorities, and if so is there possibly some upstream configuration I'm missing?
Upvotes: 4
Views: 2170
Reputation: 1928
You are blocking the result before is available. You can simply flatmap it so that you don't have to block it.
public Mono<ServerResponse> getMyResource(ServerRequest serverRequest) {
return serverRequest.principal().flatMap((principal) -> ServerResponse.ok()
.body(fromObject("Hello " + principal.getName())));
}
UPDATE: If you want to retrieve the principal and body you could zip them.
public Mono<ServerResponse> getMyResource(ServerRequest serverRequest) {
return Mono.zip(
serverRequest.principal(),
serverRequest.bodyToMono(String.class)
).flatMap(tuple -> {
Principal principal = tuple.getT1();
String body = tuple.getT2();
return ServerResponse.ok().build();
});
}
Upvotes: 5