spring-cloud / spring-cloud-netflix

Integration with Netflix OSS components
http://cloud.spring.io/spring-cloud-netflix/
Apache License 2.0
4.87k stars 2.44k forks source link

Security: Spring Security vs Zuul Filter #162

Closed aivans closed 8 years ago

aivans commented 9 years ago

Hi,

How is it appropriate, from the conceptual perspective, to wire in Security? Spring Security or Zuul Pre filter?

aivans commented 9 years ago

I found this in the rc1 december press release:

Several improvements to the Zuul proxy, including automatic updates when the Eureka catalog changes, support for form-encoded POSTs, external configuration of the routes and authentication scheme for each client.

Declarative configuration of which routes require OAuth2 authentication in Spring Cloud Security.

Please explain a bit

dsyer commented 9 years ago

Docs are here: http://projects.spring.io/spring-cloud/spring-cloud.html#_token_relay

Generally speaking you could add Spring Security to a Zuul proxy, and it might be appropriate, e.g. to apply a global access rule to all requests. The proxy also can pass authentication headers downstream to the backend resources, so usually I would expect if the backends are independently secure there would be a way to make Zuul generate the right header. We handle some special cases out of the box.

aivans commented 9 years ago

I will read the docs carefully.

My goal is to authenticate all calls in the Zuul proxy and pass authenticated user info to the downstream services. The downstream services will not perform authentication.

dsyer commented 9 years ago

Why would you pass the user info downstream if they are not going to use it?

aivans commented 9 years ago

They are going to use user information, for ex userId, the entire security principal object or the SCIM info. My idea is to authenticate at the edge of the ecosystem and leave the services perform their business functions and not worry about other aspects. The services will use the info for authorization purposes (acl, etc) and for retrieving additional info from other services.

dsyer commented 9 years ago

OK so they are going to have to perform some sort of authentication (decoding the token). That's the pattern you get out of the box with @EnableZuulProxy and @EnabIeOAuth2Sso in the gateway and @EnableOAuth2Resource in the backends. (The backend features are a very thin layer over @EnableResourceServer but that does include an authentication filter.)

aivans commented 9 years ago

My understanding of what you say is to relay the JWT toke to the services from Zuul. Next the services will perform their own JWT manipulation. Please correct me if I am wrong.

What I want to do is to limit this to the Zuul Gateway. Basically authenticate the user here, extract the user info from SCIM server, LDAP, etc and then forward relevant user info (userid, account, etc) to the services as header attributes. The services will not authenticate anything anymore, they have plain user info available.

I choose this approach to simplify things for the backend services and basically they will talk to eachother by trusting eachother. Everything happens in our own data center.

I hope I am right with this approach.

So, I understand that I should use Spring Security for this and not use Zuul pre-filters. I am a bit confused right now regarding how are the Zuul filters different from the traditional servlet filters.

dsyer commented 9 years ago

You have an API Gateway, so I think a ZuulFilter to prepare your custom headers is probably a fine idea. You could also consider just sharing session state amongst all your apps using Spring Session (I'm just about to publish my blog on that), and then the existing Zuul features in Spring Cloud would work with passthru authentication (the cookie from the Gateway is valid in the backends as well).

aivans commented 9 years ago

Exactly, I am trying to use Zuul as API Gateway.

svanscho commented 9 years ago

I am working on a similar use case as aivans. We are also using zuul filters for the security demarcation point and then handle the other traffic internally.

aivans commented 9 years ago

@svanscho How do you perform authentication? Using Spring Security filter chain before Zuul or part of Zuul pre-..post chain?

aivans commented 9 years ago

@dsyer I read the examples you presented in the Angular + Spring Cloud series.

My thoughts are longer term for a project that involve multiple teams, where governance is important.

In your examples there is a 2 tier approach, Spring Security and Zuul for routing. I see a few disadvantages:

But for now I still don't see how you could do security from a Zuul pre-filter and configure routing and security in the same location. Also, the filter chain implementation of Zuul is quite rudimentary compared to Spring Security.

I also wonder how Netflix uses Zuul for security as they claim in the presentations.

andrewserff commented 9 years ago

@dsyer The link provided to the documentation no longer works and I see no mention of the token relay in the docs any more. I'm trying to find out how I can forward client certificate information downstream to the services that are protected by Spring Security x509 authentication. Is there a way to do this similar to how mod_jk does with the +ExportCertData directives? I posted a question on SO about this as well, but hoping you might know how to accomplish this. It's fine if the zuul proxy just does the ssl verification and then passes the cert info on for authorization on the backend.

dsyer commented 9 years ago

The link was for access token relay not X.509, and it is still there I think, but maybe the fragment id is wrong. Certificate-based authentication isn't any different than any other if you follow the suggestion about Spring Session though, so it might still be worth looking at. If you want explicit support for something certificate based in the Zuul proxy then that might be interesting. Contributions more than welcome.

michaeltecourt commented 9 years ago

@aivans have you found a way to wire together your Zuul proxy and spring-security-oauth as an authentication pre-filter ? we're considering the same kind of "authentication proxy"

aivans commented 9 years ago

@michaeltecourt unfortunately our architecture focus turned to other topics and we left the public API for a later stage Probably what @dsyer suggests is that they are independent main filters, as in his examples (Security Filter + Zuul Filter) as part of this series: https://spring.io/guides/tutorials/spring-security-and-angular-js/

michaeltecourt commented 9 years ago

@aivans thanks a lot for the link, I came accross that article once but didn't read it because the title made it look like a UI tutorial :)

michaeltecourt commented 9 years ago

@dsyer little question : Is it safe to use SpringCloud+Zuul as a standalone proxy ? can it handle heavy traffic based on your experience/tests ? does it comply with HTTP specs/recommendations for proxies (headers management, etc) ?
Looking at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter it seems to derive from a Netflix sample, I'd like to know if we can use it for more than an embedded proxy safely or if we need to do some analysis/contributions first.

rozhok commented 9 years ago

+1 for question here. Our target architecture is several small microservices, Eureka as service registry and Zuul as edge servers. We using JWT-based auth mechanism. The question is - how to organize auth? Use custom-written Zuul Filters on Edge or auth and pass plain requests to downstream servers or use Spring Security on the front-door and use Zuul only for routing? Or pass JWT token to downstream servers and write some custom stuff for each service?

aivans commented 9 years ago

+1 :)

svanscho commented 9 years ago

We are using a zuul filter to validate the actual authentication (reach out to a separate authorization-microservice) and once passed, route the request to the downstream servers. The authorization-microservice itself is based on Spring Security.

kakawait commented 9 years ago

@aivans do you find any final solution to our problem. I'm trying to build exact same architecture as you, Zuul like API Gateway managing auth and downstream to backend microservice that just expose open REST API. I really don't want to create stateful microservice using shared session via Spring session using Redis so I thought about transferring JWT token on each downstream request.

Actually our auth is CAS so I can't use Spring Cloud Security I'm using pure Spring Security on Zuul to auth user, but I now want to transfer current user identity to downstream microservice. And I don't really now how to achieve it... Using Spring Security filter or Zuul filter, etc...

rozhok commented 9 years ago

@kakawait sup man, I'm doing auth using following scheme:

  1. Client sends POST /api/login request to Zuul
  2. Zuul sees that this request does not contain JWT token in header
  3. Zuul redirects request to Auth server
  4. Downstream perform auth and in successful case responses with Token
  5. Zuul returns token to client
  6. Client uses this token in following requests
  7. When client sends request with JWT token Zuul figures out this and parsed it. It is able to parse since the secret key is also stored on Zuul.
  8. Zuul parses token and break it into several fields - user id and role.
  9. Zuul sets custom headers
  10. All downstream services use custom filter who takes user id and role from headers and transforms it into Spring Security auth object or whatever.
  11. ...
  12. PROFIT!
kakawait commented 9 years ago

@rozhok really thank

Just to be cleared for

9 Zuul sets custom headers

You're performing that using Zuul Filter?

I think my workflow will be the same, with some specifies.


Off-topic: I'm really not expert of JWT I'm currently reading doc/spec but if you find time to answer that it will help me a lot (else no prob RTFM I know :)). On

5 Zuul returns token to client

I suppose that client app should store/manage/persist JWT to achieve next step

6 Client uses this token in following requests

If yes is there good practices (simplicty and security concerns) to how store? (cookie, localstorage)

rozhok commented 9 years ago

You're performing that using Zuul Filter?

Sure

client app should store/manage/persist JWT

Yes

If yes is there good practices (simplicty and security concerns) to how store? (cookie, localstorage)

There is bunch of articles over the internetz about this. We didin't decided how to store it right now. I suppose to use cookies

bisbos commented 9 years ago

@rozhok I am trying to build a similar architecture..Will you be able to share the code

rozhok commented 9 years ago

@bisbos don't have time to clean up our private stuff to share it. Here is nice tutorial http://callistaenterprise.se/blogg/teknik/2015/05/20/blog-series-building-microservices/ and also here - https://spring.io/team/dsyer Nothing very complicated...Parse header from incoming request, and pass it to downstream if everything is ok.

michaeltecourt commented 8 years ago

We ended up building an API gateway with Spring Cloud + Zuul + Spring Security OAuth 2.0.

I may not be able to open source the exact code at the time but here's the idea :

The application will act as a reverse proxy, letting Zuul forward the requests after verifying the access token.

Beware that it is not the safest solution, for your own good you should implement access control at the application level, instead of relying on external components. See : http://security.stackexchange.com/questions/94439/securing-web-applications-with-only-a-reverse-proxy And the first minutes of this Spring One 2GX video : https://www.youtube.com/watch?v=USMl2GNg2r0

aivans commented 8 years ago

Hi guys,

I also posted a related question on SO: http://stackoverflow.com/questions/33921375/zuul-api-gateway-authentication

Can you please take a look?

Thanks

spencergibb commented 8 years ago

Closing this due to inactivity. Please re-open if there's more to discuss.

samuelj90 commented 5 years ago

Is it possible to execute zuul filter before spring security filter chain ?

spencergibb commented 5 years ago

No