Closed Dreampie closed 8 years ago
I want use feign for eureka client,but i don't know how can i use zuul +oauth2 for feign.RestTemplate need more and more coding.feign easier than RestTemplate
N.B. we have a feign interceptor for oauth2 now (https://github.com/spring-cloud/spring-cloud-security/issues/56), but it isn't autoconfigured so you need to add a bean in a custom @FeignClient
configuration.
Thank you!
Hi, I'm also trying to set FeignClient with OAuth2 to implement "Relay Token". I just want FeignClient to relay / propagate the OAuth2 Token that comes from ZuulProxy (SSO Enabled). I use Spring 1.3.1-RELEASE and Spring Cloud Brixton.M4.
According to @dsyer previous comment and posts by @joaoevangelista in other posts, I have added an interceptor in a custom @FeignClient configuration:
import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.OAuth2ClientContext; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import feign.RequestInterceptor;
@Configuration public class FeignClientConfiguration {
@Value("${security.oauth2.client.userAuthorizationUri}")
private String authorizeUrl;
@Value("${security.oauth2.client.accessTokenUri}")
private String tokenUrl;
@Value("${security.oauth2.client.client-id}")
private String clientId;
// See https://github.com/spring-cloud/spring-cloud-netflix/issues/675
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oauth2ClientContext){
return new OAuth2FeignRequestInterceptor(oauth2ClientContext, resource());
}
@Bean
protected OAuth2ProtectedResourceDetails resource() {
AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
resource.setAccessTokenUri(tokenUrl);
resource.setUserAuthorizationUri(authorizeUrl);
resource.setClientId(clientId);
// TODO: Remove this harcode
resource.setClientSecret("secret");
return resource;
}
}
And I add the configuration to my @FeignClient like that:
@FeignClient(name = "car-service", configuration = FeignClientConfiguration.class)
interface CarClient {
@RequestMapping(value = "car-service/api/car", method = GET)
List<CarVO> getAllCars();
}
The application starts but when I use the Feign Client from my service I get:
2016-01-08 13:14:29.757 ERROR 3308 --- [nio-9081-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/user-service] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: getAllCars failed and no fallback available.] with root cause
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] ......
I want my application / microservice (the one that uses the @FeingClient to call the other application / microservice) to be STATELESS. However, I have tried both, with security.sessions=STATELESS (SpringBoot default) and security.sessions=ALWAYS (just to try). In both cases I got the same exception.
Having a look at the code I have seen that the OAuth2ClientContext is saved in Session (Session scoped bean). How does it work when you want to implement a STATELESS OAuth2 enabled application / microservice? Precisely this is one of the big advantages of using OAuth2 in my current scenario. However, as I said, the result was the same enabling sessions.
Can someone help with this, please?
Thanks so much! :-)
If you are using Feign with Ribbon it will execute requests in a background thread by default, so the security context and the current http request (and session) are not available. There are 2 separate questions here: whether to background the remote call, and whether to use sessions to store tokens. Try not to obsess over state and sessions and accept the advice of the Spring team (use sessions for security in a browser based app). If your app is not browser based you have to do more work (but nothing you said leads me to believe that yet). The background thread thing is a ribbon/Hystrix feature which you can work around by setting the isolation level to SEMAPHORE, but potentially we could maybe provide a bridge for the context in Spring Cloud (assuming it isn't already there because I did see some changes recently and haven't caught up yet).
Hi @dsyer,
Thanks so much for your answer and help.
Thanks again!
Hi @dsyer,
Do you know if the "bridge" you made reference above when you say "potentially we could maybe provide a bridge for the context in Spring Cloud (assuming it isn't already there because I did see some changes recently and haven't caught up yet)." is available? (even if it is in a snapshot)
I have not been able to identify the code belonging to this "bridge". If so, could you provide me with the name of the class to find it? This bridge will come in very handy from my point of view.
Once again, thanks for your help
If you didn't find it my guess is it doesn't exist yet. You can implement something using the async support in Spring Security.
This just bit me and i was having trouble using this provided solution. I think what is not clear here is that this solution will not work when using @EnableOAuth2Sso
. The reason for this is having this annotation triggers the use of @EnableOAuth2Client
which initiates OAuth2ClientConfiguration
. This then causes OAuth2RestOperationsConfiguration#RequestScopedConfiguration
to not be used which is the configuration that creates the DefaultOAuth2ClientContext
based off the current Principal
in the SecurityContextHolder
. Seems a bit counter intuitive as the purpose of using @EnableOAuth2Sso
is to forward on the received bearer token and the documentation says that it can be used with OAuth resource servers.
Closing this due to inactivity. Please re-open if there's more to discuss.
I am also using this with the EnableOAuth2Sso annotation from a Client to a Resource. Resource to Resource seems to work fine with Feign. My client throws the
java.lang.IllegalStateException: No thread-bound request found
exception using Feign though.
@spencergibb @dsyer Enabled HTTPS in OAuth2 encounter some problems, can you help me look at it?http://stackoverflow.com/questions/44060566/when-i-switch-from-http-to-https-auth2-client-can-get-the-token-but-can-not-ac/44060595#44060595
I need your help, thanks!!!
You need to provide more information. Are you having a problem? If so describe it.