39

I want to introduce Zuul through Spring Cloud as an API Gateway in front of a few services.

I have some design doubts around Authentication. The Authentication would be handled by Spring Security, which comes before Zuul in the servlet filter chain.

My concern:

  • the Gateway would sit in front of many services

  • some services may expose endpoints which do not require authentication

  • some services may expose endpoints which need a Session Id and some with a token", an arbitrary opaque value (for example downloading a file if you know a "hard to guess" url) In the API Gateway/Spring Security you can configure all the endpoints with their specific authentication requirements.

In terms of managing the API Gateway:

  • how do you enforce the actual Service Teams to provide the required settings per downstream service?
  • how do you allow frequent Authentication settings changes in the Gateway (as per service needs) without having to stop the entire Gateway?

Thanks, Adrian

Adrian Ivan
  • 545
  • 1
  • 5
  • 11

2 Answers2

28

We are using Spring Session to replicate the session across all of our services that sit behind a Zuul Edge Server. Zuul will authenticate the user which populates the users credentials and inserts the authenticated user into the session. This is then replicated across all the services and each service is responsible for their own security rules and settings. So really, all Zuul is doing is looking the user up in spring security and the services on the backend are enforcing the security rules as they apply to their needs. This way, you can change each service independently making the Gateway just a dumb proxy.

A good example of this is in Dave Syers tutorial about Spring Security and an Angular JS app. I also posted another question related to this which contained a sample of how we are doing this as well which might help.

Community
  • 1
  • 1
Andrew Serff
  • 2,117
  • 4
  • 21
  • 32
  • 1
    Thank you. Ok, So Zuul will lookup the user and populate the Session and route to Services. The Services themselves will specify which endpoints require authentication and what type of authentication. So this responsibility will sit with the Service team. This is good. My thinking was that I could free the Services from this task. – Adrian Ivan Nov 25 '15 at 19:17
  • 3
    The thing that bothers me here is that you _have_ to get calls going through the gateway for a downstream application to work. The gateway isn't that dumb, session creation is still business logic. Sharing that session through a datastore is sneaky high coupling, I still don't understand why the Spring guys recommend it in a microservice architecture. – Michael Técourt Jul 19 '16 at 12:57
  • 1
    Do you have a suggestion for a better solution @MichaelTecourt? I don't really like the session replication as a solution either, but haven't found a better way. – Andrew Serff Jul 19 '16 at 17:16
  • 4
    I don't know if it is _better_, just a different compromise. Some guy from Pivotal made a demo last week using the same kind of approach as you, saying that it was an optimization over mine :) I chose to secure each app with OAuth 2.0. Applications validate access tokens they received by making an HTTP call to the authorization server, which returns user info in exchange. Caches (not shared) are added on both sides to speed up the process. Applications are clearly decoupled and can be tested independently, at the cost of making the authorization server a bottle neck / single point of failure. – Michael Técourt Jul 19 '16 at 20:07
  • 2
    The only difference between your approach and the pivotal guy, is that he secured each application (using JWTs without HTTP call to validate tokens), only the user info lookup relied on a shared cache. – Michael Técourt Jul 19 '16 at 20:13
6
  • the Gateway would sit in front of many services

What is the concern here ?

  • some services may expose endpoints which do not require authentication

Spring Security has a permitAll()access rule

  • some services may expose endpoints which need a Session Id and some with a token", an arbitrary opaque value (for example downloading a file if you know a "hard to guess" url) In the API Gateway/Spring Security you can configure all the endpoints with their specific authentication requirements.

Your Zuul proxy can have sessions. If you are using Spring Security OAuth 2.0 you can use ResourceServerSecurityConfigurer#stateless(false) and activate sessions with HttpSecurity#sessionManagement().sessionCreationPolicy(...) to create sessions everytime you receive a valid access token. A JSESSIONID Cookie will be placed in the HTTP Response.

  • how do you enforce the actual Service Teams to provide the required settings per downstream service?

I'm not sure I understand the question here, don't you want to enforce security constraints at the API Gateway (zuul proxy) level ? or are you trying to have "security double checks" both on the proxy AND target application ?

  • how do you allow frequent Authentication settings changes in the Gateway (as per service needs) without having to stop the entire Gateway?

Zuul allows you to add ZuulRoutes dynamically at runtime, if you use it as a standalone library that is. Wrapped in Spring Security, whose context is initialized once at startup time... I doubt you can easily alter the security config at runtime.

EDIT following precisions by the OP in the comments : If your teams should be responsible for their security rules, having a centralized gateway is a contradiction by design.

My interpretation of the microservice philosophy is that each application is standalone, and in charge of its full functional scope, and security / access control is part of it. You can easily verify tokens at the application level (by either making a call to the authorization server or using JWTs), with each application defining which scope is required for each resource. Spring Cloud already has an OAuth 2.0 starter, or you could easily create one if you use "plain" Spring Boot.

That way you can deploy individual apps wherever you want (public cloud or on premise servers), without having to rely on upstream components for security or synchronize your gateway configuration deployments with other teams.

The API Gateway thing is an easy temptation, but don't overlook the risks and constraints :

  • You won't be able to secure internal calls
  • You will have to rely on upstream network components, and take your applications' input for granted
  • Advanced access control rules may become a headache : how do you get the user's individual permissions, etc
  • You will have to synchronize configuration changes with other teams
Michael Técourt
  • 3,457
  • 1
  • 28
  • 45
  • Ok. I need to explain better. My main concern is that I would like to give service teams to opportunity and the responsibility to edit the authentication settings belonging to their services in the gateway. I don't want the gateway to become an organizational bottleneck. In terms of Routing things look better since as you said you can add Routing filter dynamically, so each team could provide these filters somehow. – Adrian Ivan Nov 25 '15 at 19:09
  • The idea was to handle Authentication in Gateway, and at Service level to have the Principal ready to use and only authenticate service-to-service (request was received from a Service I trust) – Adrian Ivan Nov 25 '15 at 19:22
  • "Request was received from a Service I trust" is impossible to verify without application level security. About having your security relying on some shared state populated by the Gateway : it introduces a lot invisible coupling between components, and an upstream dependency on "what the gateway has done or not", but it may be a fair enough compromise for your need. – Michael Técourt Jul 19 '16 at 12:47
  • Thanks Michael, I will come back soon with my views at this moment. – Adrian Ivan Jul 19 '16 at 21:15