0

There is a rest api secured using keycloak(OAUTH) as below:

@PreAuthorize("hasRole('user')")
@GetMapping(value = "/employees", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<List<Employee>> findAll(java.security.Principal principal,
            @RequestParam(name = "filterationCriteria", required = false) String fields) {
        if(Objects.nonNull(principal)){
           return employeeManagementService.findAll(fields);
        }
        return null;
    }

i want to consume this api using webclient as below:

public <T> T get(URI url, Class<T> responseType, Principal principal) {
        return  WebClient.builder().build().get().uri(url)
                   .header("Authorization", "Basic " + principal)
                   .retrieve().bodyToMono(responseType).block();
    }

above method is throwing below exception from findAll() method, which generally happens if the principal is not found:

org.springframework.web.reactive.function.client.WebClientResponseException$Unauthorized: 401 Unauthorized from GET

Am i doing something wrong, is that the correct way to send principal with the request?

Any suggestion is appreciated.

Thanks in advance.

UPDATE

I am sending request to the secured rest-api using webclient from a different service and i need to pass the principal manually(may be including it into the header).

if i simply do below: WebClient.builder().build().get().uri(url).retrieve().bodyToMono(responseType).block() then the principal is coming null in the findAll method

Security config

protected void configure(HttpSecurity http) throws Exception {
       super.configure(http);
       http.authorizeRequests()
               .anyRequest().permitAll().and()
               .csrf().disable();
   }

NOTE: i have put Authorize constraint at method level.

Rohit Singh
  • 145
  • 1
  • 2
  • 7
  • `Principal` is passed automatically if there is an authenticated `user`.Please share code of spring-security configs and refer this https://www.marcobehler.com/guides/spring-security to get better understanding of how spring security works – Codemaster May 01 '21 at 12:47
  • Hi @Codemaster Your response is much appreciated. what you are saying is absolutely right. if we send a request the `Principal` is passed automatically if there is an authenticated `user`. but in my case I am sending request to the secured rest-api using `webclient` from a different service and i need to pass the principal manually(may be including it into the header). if i simply do below: ``` WebClient.builder().build().get().uri(url) .retrieve().bodyToMono(responseType).block() ``` then the principal is coming null in the `findAll` method – Rohit Singh May 01 '21 at 13:17

1 Answers1

1
I have found a solution. the principal has to be sent like this:

public <T> T get(URI url, Class<T> responseType, Principal principal) {
        RequestHeadersSpec uri = webClient.get().uri(url);
        if (Objects.nonNull(principal)) {
            uri = uri.header("Authorization", "Bearer "
                    + ((KeycloakAuthenticationToken) principal).getAccount().getKeycloakSecurityContext().getTokenString());
        }
        ResponseSpec response = uri.retrieve();
        Mono<T> bodyToMono = response.bodyToMono(responseType);
        return bodyToMono.block();
    }
Rohit Singh
  • 145
  • 1
  • 2
  • 7