I'm learning about securing microservices with Basic Authentication and OAuth2 JWT Token Authentication. I implemented it using Basic Authentication and now I want to transform it in OAuth2 Authentication.
This is the implementation for securing the communication between these 2 microservices using Basic Auth.
Microservice 1 - REST API
@Configuration
@Getter
public class DemoApiConfiguration {
@Value("${demo.api.credentials.username}")
private String username;
@Value("${demo.api.credentials.password}")
private String password;
}
SecurityConfigurer class:
@Configuration
@RequiredArgsConstructor
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
private final DemoApiConfiguration apiConfig;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails theUser = User.withUsername(apiConfig.getUsername())
.password(passwordEncoder.encode(apiConfig.getPassword())).roles("USER").build();
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
userDetailsManager.createUser(theUser);
return userDetailsManager;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Controller class:
@RestController
@RequestMapping("/rest/api/v1")
public class HomeController {
@GetMapping("/products")
public String home() {
return "These are products!";
}
}
application.yml:
demo:
api:
credentials:
username: ${demo_api_username:john}
password: ${demo_api_password:test}
Microservice 2 - REST Consumer
@Configuration
@Getter
public class DemoApiConfiguration {
@Value("${demo.api.credentials.username}")
private String username;
@Value("${demo.api.credentials.password}")
private String password;
@Value("${demo.api.credentials.basePath}")
private String basePath;
}
WebConfigurer class:
@Configuration
@RequiredArgsConstructor
public class WebConfigurer {
private final DemoApiConfiguration apiConfig;
@Bean
public ApiClient restTemplate() {
RestTemplate restTemplate = new RestTemplate();
ApiClient apiClient = new ApiClient(restTemplate);
apiClient.setBasePath(apiConfig.getBasePath());
return apiClient;
}
public String getAuthorization() {
return (!StringUtils.isEmpty(apiConfig.getUsername()) &&
!StringUtils.isEmpty(apiConfig.getPassword())) ?
"Basic " + Base64Utils.encodeToString((
apiConfig.getUsername() + ":" + apiConfig.getPassword())
.getBytes()) :
null;
}
}
ApiClient class:
@Getter
@RequiredArgsConstructor
@Slf4j
public class ApiClient {
private static final String AUTHORIZATION_HEADER = "Authorization";
private final RestTemplate restTemplate;
private String basePath;
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
return this;
}
public String invokeApi(String path, String credentials) {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);
RequestEntity.BodyBuilder requestBuilder =
RequestEntity.method(HttpMethod.GET, builder.build().toUri());
requestBuilder.contentType(MediaType.APPLICATION_JSON);
requestBuilder.header(AUTHORIZATION_HEADER, credentials);
RequestEntity<Object> requestEntity = requestBuilder.body(null);
return restTemplate
.exchange(requestEntity, String.class).getBody();
}
}
ConsumeController class:
@RestController
@RequiredArgsConstructor
public class ConsumeController {
private static final String PATH = "/rest/api/v1/products";
private final WebConfigurer webConfigurer;
private final ApiClient apiClient;
@GetMapping(value = "/products-client")
public String getProductList() {
return apiClient.invokeApi(PATH, webConfigurer.getAuthorization());
}
}
application.yml:
server:
port: 8090
demo:
api:
credentials:
username: ${demo_api_username:john}
password: ${demo_api_password:test}
basePath: ${demo_api_path:http://localhost:8080}
So the first microservice is a REST API and the second microservice is a REST consumer and the communication is secured using Basic Auth.
Now I want to implement using OAuth2, and I want to ask you how can I secure the communication using OAuth2? So I want to add another endpoint like "/access-token", and the client first will do a request at this endpoint with username and password and will get a jwt token. After that will do a request for "/products" endpoint with Authorization header using this jwt token. Can you help me to do this kind of implementation? Thank you!


