uaa-behind-zuul-sample
uaa-behind-zuul-sample copied to clipboard
A question about using curl to access resource server?
Hi kakawait Thanks for the awesome sample. It helps me a lot about understanding zuul with security.
Now I have one problem about the sample, could you help me? thank you very much.
a). I can get token from zuul server by using curl, that is result expected.
curl --insecure -H "Authorization: Basic $(echo -n 'acme:acmesecret' | base64)" http://localhost:8765/uaa/oauth/token -d grant_type=password -d username=user -d password=password -v
the token is
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc4NzEwMDAsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIiwiUk9MRV9VU0VSIl0sImp0aSI6IjhiODdhNTNhLWU0MmEtNDkyYS05ZWMxLTY2YWE4NmU4ZDkxOCIsImNsaWVudF9pZCI6ImFjbWUiLCJzY29wZSI6WyJvcGVuaWQiXX0.TWef-agKnnKaWDiW44ROxIseL0tVG7TXZWYTiMIV4RoKVLXXCFsFb5l24gRjxRCZAhmyB-5N6l-axLflgvKEbLrPHYJj054nEE9bi_I5mi9b2y4Z2mII6sfMkjeTAlrlyGKN-s-oU-nO2tws-vKCAYtycKmTL_xsNMH3Qmm1-4haG9SZIFq4YJkC93RvBDCGxit7jV62XrEyDj1atPWQ8QJeJmp0I8z04sVKlxulzRYpkkFMKjvWAx5lgnx5B6m-0jhXgi8g4kejUpZK9yojDTNRKMkYJuhPyTVCLsakpTl3vwOBZ5xpO-o2mgd9yn-zvjo7P1TK1rFys9xvREu2mw
b). then, when I request zuul server by the command
curl -v -H 'Content-type: application/json' -H 'Authorization: Bearer ACCESS_TOKEN' http://localhost:8765/dummy
the result always show
" X-Frame-Options: DENY
< Location: http://localhost:8765/login"
for the case, how can I access the http://localhost:8765/dummy by curl with token rather than using browser? suppose that I have a client which can send api request to zuul server.

@wldandan good point. By using @EnableOauth2Sso
on Zuul
(here api-gateway) you transform api-gateway as token relay but not as resource server.
So when fetching microservices using Authorization
header api-gateway will not try to read this header, so it will consider you as not auth.
You should transform your api-gateway as ResourceServer
(@EnableResourceServer
) in order to add OAuth2AuthenticationProcessingFilter
(in addition to OAuth2ClientAuthenticationProcessingFilter
used by SSO) that will handle Authorization
header.
I just created a branch to POC your needs. I have to polish it before merging on master
so be careful if you choose to copy past.
In addition you could up-vote http://stackoverflow.com/questions/37059128/spring-1-3-3-enableresourceserver-and-enableoauth2sso-at-the-same-time (not my question) and up-vote https://github.com/spring-projects/spring-security-oauth/issues/683 because there is a trick to do for combining @EnableResourceServer
and @EnableOauth2Sso
@wldandan does the solution works for you ?
@kakawait Hey kakawait, thanks for your solution. I did not get chance to verify it. I will give it a try and respond you as soon as possible. :) Thanks a lot.
@kakawait Hey kakawait, I have verified the solution in 'resource-server' branch. It does work, thanks for your work, it is awesome :)
Cool, I will keep issue open until I polish the code
@kakawait first of all: awesome work! It helps me a lot.
Problem
It have the same issue like wldadan with adding a client who uses the zuul proxy, but I'd like to have multiple users accessing the resourced by the grand_type=password
- I removed the user and password property from
application.yml
of theuaa-service
- I added more users for authentication
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("admin").roles("ADMIN");
// auth.parentAuthenticationManager(authenticationManager);
}
- It works fine in the browser with
admin
anduser
credentials. So authorization is fine there.
But a call from another client like
curl --insecure -H "Authorization: Basic $(echo -n 'acme:acmesecret' | base64)" http://localhost:8765/uaa/oauth/token -d grant_type=password -d username=admin -d password=admin -v
results in
* Trying ::1...
* Connected to localhost (::1) port 8765 (#0)
> POST /uaa/oauth/token HTTP/1.1
> Host: localhost:8765
> User-Agent: curl/7.43.0
> Accept: */*
> Authorization: Basic YWNtZTphY21lc2VjcmV0
> Content-Length: 49
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 49 out of 49 bytes
< HTTP/1.1 400
< Set-Cookie: JSESSIONID=85A5C7AD4F55891EF9F0EA56BCF4087A;path=/;HttpOnly
< Set-Cookie: XSRF-TOKEN=2b264f92-1cb6-4a1c-9f99-6fc25f66546c;path=/;Secure
< X-Application-Context: api-gateway:docker:8765
< Date: Mon, 09 Jan 2017 12:12:13 GMT
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: close
<
* Closing connection 0
{"error":"invalid_grant","error_description":"Bad credentials"}
With the log message:
o.s.s.a.dao.DaoAuthenticationProvider : User 'admin' not found
The same happens with user
and password
.
Possible idea to solve:
My idea now (which I didn't manage to implement) to share the authentication manager of the WebSecurityAdapter
with the AuthorizationServerConfigurerAdapter
.
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// TODO here: use the authenticationManager from the other class
.authenticationManager(authenticationManager)
.accessTokenConverter(jwtAccessTokenConverter());
}
I made a branch for it in my fork.
UPDATE: Added a question on stackoverflow as well.
=> Do you know how to do that? Or is there another (better) way? Thanks in advance! (maybe it's a easy task, but I'm new to the Spring/Cloud world :) )
UPDATE2: Got it working on my fork =) I'll send you a PR later
The solution was
- Exposing the AuthenticationManager from
LoginConfiguration
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
- Injecting it in the
AuthorizationServerConfiguration
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
- I also added a protected resource only accessible for the
ROLE_ADMIN
in theDummyServiceApplication
which gets anACCESS_DENIED
for theuser
:
@PreAuthorize("#oauth2.hasScope('openid') and hasRole('ROLE_ADMIN')")
@RequestMapping(value = "secret", method = RequestMethod.GET)
@ResponseBody
public String helloSecret(Principal principal) {
return principal == null ? "Hello anonymous" : "S3CR3T - Hello " + principal.getName();
}
Props to PiggyMetrics who brought me up to the solution and you guys for this awesome work!
Sorry I didn't find time to read your question. I will check your question and solution
But thank you for the solution
This solution in the resource-server branch worked for me also. Is there a reason it wouldn't be merged to master? I will submit a PR for this if it is wanted in master.
Yep @kakawait, I think you could merge it into the master branch because the resource-server
branch is an enhancement of the master atm.
@mavogel He accepted my PR: https://github.com/kakawait/uaa-behind-zuul-sample/pull/23