From 295bf661f31b0f6450a183472c9cda812e6c47c6 Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:48:53 +0330 Subject: [PATCH 1/7] BAEL-5300: add required dependency --- spring-cloud/spring-cloud-openfeign/pom.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 From d1ef70e63dde6b85494d455d5d40c520361a336b Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:49:16 +0330 Subject: [PATCH 2/7] BAEL-5300: add oauth2 client info --- .../src/main/resources/application.properties | 7 +++++++ 1 file changed, 7 insertions(+) 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 From e459737a66622ae0242e7d4b8f356ad46acefe18 Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:49:51 +0330 Subject: [PATCH 3/7] BAEL-5300: add payment resources code --- .../cloud/openfeign/client/PaymentClient.java | 16 +++++++++++++ .../controller/PaymentController.java | 24 +++++++++++++++++++ .../cloud/openfeign/model/Payment.java | 23 ++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/PaymentClient.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/controller/PaymentController.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Payment.java 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; + } +} From 10dd6acd33f6bd2db32ef22387f18e0f21fa9f39 Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:50:19 +0330 Subject: [PATCH 4/7] BAEL-5300: add openfeign config --- .../OAuthClientCredentialsFeignManager.java | 85 +++++++++++++++++++ .../oauthfeign/OAuthFeignConfig.java | 46 ++++++++++ 2 files changed, 131 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthClientCredentialsFeignManager.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuthFeignConfig.java 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 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 From 1a70e89e1edb6244aae122148cedba9d132bcbca Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:50:37 +0330 Subject: [PATCH 5/7] BAEL-5300: add security config --- .../OAuth2WebSecurityConfigurerAdapter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/oauthfeign/OAuth2WebSecurityConfigurerAdapter.java 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(); + } +} From 6c2d5a66d92e5ed2c5d36310dad3ce2d72f9d0d8 Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:50:50 +0330 Subject: [PATCH 6/7] BAEL-5300: add test class --- .../openfeign/PaymentClientUnitTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java 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..3e53ba0d97 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/PaymentClientUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.cloud.openfeign; + +import com.baeldung.cloud.openfeign.client.PaymentClient; +import com.baeldung.cloud.openfeign.model.Payment; +import com.baeldung.cloud.openfeign.model.Post; +import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService; +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()); + } + +} From ff2fe54750cd024c36cd5fe8282378ff2edef830 Mon Sep 17 00:00:00 2001 From: sharifi Date: Mon, 31 Jan 2022 10:53:06 +0330 Subject: [PATCH 7/7] BAEL-5300: improve test class --- .../com/baeldung/cloud/openfeign/PaymentClientUnitTest.java | 2 -- 1 file changed, 2 deletions(-) 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 index 3e53ba0d97..0372728515 100644 --- 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 @@ -2,8 +2,6 @@ package com.baeldung.cloud.openfeign; import com.baeldung.cloud.openfeign.client.PaymentClient; import com.baeldung.cloud.openfeign.model.Payment; -import com.baeldung.cloud.openfeign.model.Post; -import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired;