diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml
index 3e59f512db..480663eb1c 100644
--- a/spring-cloud/spring-cloud-openfeign/pom.xml
+++ b/spring-cloud/spring-cloud-openfeign/pom.xml
@@ -48,7 +48,15 @@
io.github.openfeign.form
feign-form-spring
-
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security
+ spring-security-oauth2-client
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java
new file mode 100644
index 0000000000..91932fb7d8
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java
@@ -0,0 +1,16 @@
+package com.baeldung.cloud.openfeign.client;
+
+import com.baeldung.cloud.openfeign.model.Payment;
+import com.baeldung.cloud.openfeign.oauthfeign.OAuthFeignConfig;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+@FeignClient(name = "payment-client", url = "http://localhost:8081/resource-server-jwt", configuration = OAuthFeignConfig.class)
+public interface PaymentClient {
+
+ @RequestMapping(value = "/payments", method = RequestMethod.GET)
+ List getPayments();
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java
new file mode 100644
index 0000000000..97c9437ce1
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java
@@ -0,0 +1,24 @@
+package com.baeldung.cloud.openfeign.controller;
+
+import com.baeldung.cloud.openfeign.client.PaymentClient;
+import com.baeldung.cloud.openfeign.model.Payment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+public class PaymentController {
+
+ private final PaymentClient paymentClient;
+
+ public PaymentController(PaymentClient paymentClient) {
+ this.paymentClient = paymentClient;
+ }
+
+ @GetMapping("/payments")
+ public List getPayments() {
+ List payments = paymentClient.getPayments();
+ return payments;
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java
new file mode 100644
index 0000000000..c6d45bedbd
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java
@@ -0,0 +1,23 @@
+package com.baeldung.cloud.openfeign.model;
+
+public class Payment {
+
+ private String id;
+ private double amount;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java
new file mode 100644
index 0000000000..af60c3849b
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java
@@ -0,0 +1,19 @@
+package com.baeldung.cloud.openfeign.oauthfeign;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+public class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .csrf()
+ .disable()
+ .oauth2Client();
+ http
+ .authorizeRequests().anyRequest().permitAll();
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java
new file mode 100644
index 0000000000..5e958a93de
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java
@@ -0,0 +1,85 @@
+package com.baeldung.cloud.openfeign.oauthfeign;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static java.util.Objects.isNull;
+
+public class OAuthClientCredentialsFeignManager {
+
+ private static final Logger logger = LoggerFactory.getLogger(OAuthClientCredentialsFeignManager.class);
+
+ private final OAuth2AuthorizedClientManager manager;
+ private final Authentication principal;
+ private final ClientRegistration clientRegistration;
+
+ public OAuthClientCredentialsFeignManager(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration) {
+ this.manager = manager;
+ this.clientRegistration = clientRegistration;
+ this.principal = createPrincipal();
+ }
+
+ private Authentication createPrincipal() {
+ return new Authentication() {
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Object getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Object getDetails() {
+ return null;
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return this;
+ }
+
+ @Override
+ public boolean isAuthenticated() {
+ return false;
+ }
+
+ @Override
+ public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
+ }
+
+ @Override
+ public String getName() {
+ return clientRegistration.getClientId();
+ }
+ };
+ }
+
+ public String getAccessToken() {
+ try {
+ OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest
+ .withClientRegistrationId(clientRegistration.getRegistrationId())
+ .principal(principal)
+ .build();
+ OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest);
+ if (isNull(client)) {
+ throw new IllegalStateException("client credentials flow on " + clientRegistration.getRegistrationId() + " failed, client is null");
+ }
+ return client.getAccessToken().getTokenValue();
+ } catch (Exception exp) {
+ logger.error("client credentials error " + exp.getMessage());
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java
new file mode 100644
index 0000000000..70ca45d86e
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java
@@ -0,0 +1,46 @@
+package com.baeldung.cloud.openfeign.oauthfeign;
+
+import feign.RequestInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.client.*;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
+
+@Configuration
+public class OAuthFeignConfig {
+
+ public static final String CLIENT_REGISTRATION_ID = "keycloak";
+
+ private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
+ private final ClientRegistrationRepository clientRegistrationRepository;
+
+ public OAuthFeignConfig(OAuth2AuthorizedClientService oAuth2AuthorizedClientService,
+ ClientRegistrationRepository clientRegistrationRepository) {
+ this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService;
+ this.clientRegistrationRepository = clientRegistrationRepository;
+ }
+
+ @Bean
+ public RequestInterceptor requestInterceptor() {
+ ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(CLIENT_REGISTRATION_ID);
+ OAuthClientCredentialsFeignManager clientCredentialsFeignManager =
+ new OAuthClientCredentialsFeignManager(authorizedClientManager(), clientRegistration);
+ return requestTemplate -> {
+ requestTemplate.header("Authorization", "Bearer " + clientCredentialsFeignManager.getAccessToken());
+ };
+ }
+
+ @Bean
+ OAuth2AuthorizedClientManager authorizedClientManager() {
+ OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
+ .clientCredentials()
+ .build();
+
+ AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
+ new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService);
+ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
+ return authorizedClientManager;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties
index 41bbbde2c3..7188b74c9b 100644
--- a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties
+++ b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties
@@ -1,3 +1,10 @@
+server.port=8085
+spring.main.allow-bean-definition-overriding=true
spring.application.name= openfeign
logging.level.com.baeldung.cloud.openfeign.client: DEBUG
feign.hystrix.enabled=true
+
+spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials
+spring.security.oauth2.client.registration.keycloak.client-id=payment-app
+spring.security.oauth2.client.registration.keycloak.client-secret=863e9de4-33d4-4471-b35e-f8d2434385bb
+spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8083/auth/realms/master/protocol/openid-connect/token
diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java
new file mode 100644
index 0000000000..0372728515
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.cloud.openfeign;
+
+import com.baeldung.cloud.openfeign.client.PaymentClient;
+import com.baeldung.cloud.openfeign.model.Payment;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class PaymentClientUnitTest {
+
+ @Autowired
+ private PaymentClient paymentClient;
+
+ @Test
+ public void whenGetPayment_thenListPayments() {
+
+ List payments = paymentClient.getPayments();
+
+ assertFalse(payments.isEmpty());
+ }
+
+}