Reputation: 295
I was finally able to protect a rest api with Okta as OAuth2.0 security provider (basic with defaults). Also able to get the bearer token using curl, to call rest api via postman and get back results.
curl --location --request POST 'https://dev-XXXXXX.okta.com/oauth2/default/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=XXXXXXXXXXXXX' \
--data-urlencode 'client_secret=XXXXXXXXXXXXXXXXXXXXXXXXXXX' \
--data-urlencode 'grant_type=client_credentials
Now i am trying to implement FeignClient (Rest client) in Spring Boot 2.X app to call the protected api, but facing difficulty in finding right documentation/samples as guide. Appreciate any directions/suggestions?
Upvotes: 0
Views: 853
Reputation: 5365
To collect the token with Feign you need the following:
import java.util.Map;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.cloud.netflix.feign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
@FeignClient(name = "oauth2", url = "https://dev-XXXXXX.okta.com/oauth2/default/v1")
public interface TokenFetcher {
@PostMapping(value = "/token", consumes = APPLICATION_FORM_URLENCODED_VALUE)
String token(@RequestBody Map<String, ?> form);
class Configuration {
@Bean
Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
return new SpringFormEncoder(new SpringEncoder(converters));
}
}
}
Use the client like this:
@Autowired
TokenFetcher tokenFetcher;
public void test() {
Map<String, Object> form = new HashMap<>();
form.put("client_id", "xxxxxx");
form.put("client_secret", "xxxxxx");
form.put("grant_type", "client_credentials");
String jwt = tokenFetcher.token(form);
}
Dependencies are:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
In order to use the token you must to add it token as the 'authorization' header with a prefix of 'Bearer ' (note the space) on each call. The easiest way to do this is be adding a RequestInterceptor to your FeignClient as follows:
public class FeignConfiguration {
@Bean
public RequestInterceptor requestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
String jwtTokenStoredSomewhere = null;
if (requestTemplate.request().url().startsWith("https://site1")) {
jwtTokenStoredSomewhere = site1JwtTokenStoredSomewhere;
} else if (requestTemplate.request().url().startsWith("https://site2")) {
jwtTokenStoredSomewhere = site2JwtTokenStoredSomewhere;
} else {
jwtTokenStoredSomewhere = site3JwtTokenStoredSomewhere;
}
requestTemplate.header("Authorization", "Bearer " + jwtTokenStoredSomewhere);
}
}
}
Upvotes: 1