# Lab 3: Call another Microservice

In the first lab we extended an existing Microservice to an OAuth 2.0 and OpenID Connect 1.0 compliant Resource Server. Target of this lab is to add another Microservice from the Microservice we extended in lab 1.

As already seen in the architecture introduction, there ia also a further Microservice in the picture that is called by the already existing Microservice of lab 1.

![Workshop Architecture](https://2242854493-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fvw4V8ijb79wpP5H79unz%2Fuploads%2Fgit-blob-782b32784e93b04937bdd345bccfb71773415b67%2Fdemo-architecture.png?alt=media)

## Learning Targets

In this lab we will add functionality to call another Microservice (resource server) with propagating the JWT.

In this lab you will learn how to:

1. How to call other Microservices using the WebClient.
2. How to authenticate at the other Microservice by propagating the existing JWT.

## Folder Contents

In the folder of lab 2 you find 2 applications:

* **initial**: This is the application we will use as starting point for this lab
* **final**: This application is the completed reference for this lab
* **other**: This application is the other Microservice to be called from the ToDo Microservice with the propagated access token.

## Start the Lab

In this lab we will implement:

* Calling another JWT protected Microservice by propagating the original JWT access token the ToDo application has got.

Please start this lab with project located in *lab3/initial*.

As you can see the call to the other Microservice (to suggest ToDo's) is already implemented in the *ToDoService* and there is already a corresponding api endpoint provided for this (*/api/todos/suggest*). What's missing is the corresponding token, so currently the ToDo Microservice would report an 401 http status if you try to call the endpoint */api/todos/suggest*.

Here is the provided ToDoService with the call to the other Microservice

```java
package com.example.todo.service;

import com.example.todo.entity.ToDoItemEntityRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Transactional(readOnly = true)
public class ToDoService {

    @Value("${suggest.uri}")
    private String suggestServerUri;
    private final WebClient webClient;

    // ...

    public Mono<SuggestedToDoItem> suggestToDoItem() {
        return webClient
                .get()
                .uri(suggestServerUri + "/api/suggest")
                .retrieve()
                .onStatus(
                        s -> s.equals(HttpStatus.UNAUTHORIZED),
                        cr -> Mono.just(new BadCredentialsException("Not authenticated")))
                .onStatus(
                        HttpStatus::is4xxClientError,
                        cr -> Mono.just(new IllegalArgumentException(cr.statusCode().getReasonPhrase())))
                .onStatus(
                        HttpStatus::is5xxServerError,
                        cr -> Mono.just(new Exception(cr.statusCode().getReasonPhrase())))
                .bodyToMono(SuggestedToDoItem.class);
    }

    // ...
}
```

To enable propagating the already available access token to the other Microservice Spring please extend the bean definition of the *WebClient* with the servlet filter *org.springframework.security.oauth2.server.resource.web.reactive.function.client.ServletBearerExchangeFilterFunction*. This filter gets the existing access token from the current authentication context and adds it to the *WebClient* request.

So to enable the *WebClient* for token propagation add the filter to the already existing class *com.example.todo.config.WebClientConfiguration*. After changing this your final code should look like this:

```
package com.example.todo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.server.resource.web.reactive.function.client.ServletBearerExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfiguration {

    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .filter(new ServletBearerExchangeFilterFunction())
                .build();
    }

}
```

No it is time to test again and check if the additional endpoint */api/suggest* now is getting random suggestions from the other microservice. For this start the Microservice located in the *other* folder and your adapted version of the Microservice in the *initial* folder or just use the provided solution in the *final* folder.

To trigger the request please use postman (the request is already part of the provided postman collection), curl or httpie.

***

This is the end of this lab and of the workshop.

Please don't hesitate to provide feedback to this workshop or just send me a notice if you find error or typos.
