Using Spring OAuth2 RestTemplate

If you write code in the Java world you definitely would have heard about the Spring framework.
Spring provides this library called RestTemplate which developers rely on to make a HTTP REST API call.
It is rest client which is equivalent to things like axios or isomorphic-fetch in the Javascript ecosystem.

There are many a tutorials on how to use the RestTemplate, this tutorial will focus on a nuanced aspect of RestTemplate which is the OAuth2RestTemplate.

When should OAuth2RestTemplate be used ?

  • When an OAuth2 based api call needs to be made
  • When you find yourself doing the following:
    1. REST API call to obtain the OAuth2 token
    2. Cache the OAuth2 and time it is expected to expire
    3. Check if the OAuth2 token has not expired and use it as the authorization for the actual API call

What does the OAuth2RestTemplate do ?

As a developer it provides an abstraction where you just need to focus on making the REST API call and the authorizatiom, OAuth2 token caching is handled by the OAuth2RestTemplate

How do I configure it ?

Include the spring-security-oauth2 dependency in the pom.xml as:

1
2
3
4
5
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>1.0.5.RELEASE</version>
</dependency>

Now lets say you have the following

  1. Token url: https://<auth-server>/oauth2/token
  2. ClientId
  3. ClientSecret

One would need to configure the OAuth2RestTemplate as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package org.yourapp.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.AuthenticationScheme;


@Configuration
public class OAuth2Config {

@Value("${clientId}")
private String clientId;

@Value("${clientSecret}")
private String clientSecret;

@Value("${tokenUrl}")
private String tokenUrl;

private static final Logger LOGGER = LoggerFactory.getLogger(OAuth2Config.class);

@Bean
protected OAuth2ProtectedResourceDetails oauth2Resource() {
ClientCredentialsResourceDetails clientCredentialsResourceDetails = new ClientCredentialsResourceDetails();
clientCredentialsResourceDetails.setAccessTokenUri(tokenUrl);
clientCredentialsResourceDetails.setClientId(clientId);
clientCredentialsResourceDetails.setClientSecret(clientSecret);
clientCredentialsResourceDetails.setGrantType("client_credentials"); //this depends on your specific OAuth2 server
clientCredentialsResourceDetails.setAuthenticationScheme(AuthenticationScheme.header); //this again depends on the OAuth2 server specifications
return clientCredentialsResourceDetails;
}
@Bean
public OAuth2RestTemplate oauth2RestTemplate() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate oauth2RestTemplate = new OAuth2RestTemplate(oauth2Resource(), new DefaultOAuth2ClientContext(atr));
oauth2RestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
return oauth2RestTemplate;
}
}

In order to inject the properties you would need to have it in your properties file as

1
2
3
tokenUrl=https://<auth-server>/oauth2/token
clientId=apiUser
clientSecret=apiPassword

Finally how does one use it

Since the OAuth2RestTemplate bean has been configured, it can be injected in whichever service needs to make a call to the API that is authorized by the OAuth2 server.

Lets say one needs to make a GET call to https://<oauth2-secured-api>/<resource-path>, an example of that would be

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package org.yourapp.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;

public class Service {

@Autowired
OAuth2RestTemplate oauth2RestTemplate;

public String getResource() {
String apiUrl = "https://<oauth2-secured-api>/<resource-path>";
//the simplicity lies in this line of code
//where a developer make a call like a regular RestTemplate
//and under the hood all the token fetching is handled
return oauth2RestTemplate.getForEntity(apiUrl, String.class);
}
}