29

I am currently developing a application based on a micro service architecture. We use a API-Gateway implemented using Spring Cloud Netfix's Zuul Server to route the requests to our micro services.

To realize single sign on for all our services I am currently working on an OAuth2 server set up using Spring Cloud Security. The server is basically just copy and past of the implementation in Dave Syer's Repo: https://github.com/dsyer/spring-security-angular/tree/master/oauth2/authserver

The main difference is that I want to route the requests to my OAuth server through the Zuul Proxy. This way I will not have to directly expose my OAuth Server and can add and remove Login Server dynamically.

The problem is I do not seam to understand how to correctly configure this setup. When I try to access a protected resource on the OAuth server I am forwarded to the login page. This of course is as expected. But I can not figure out how to set the hostname and port used when forwarding. What I want to happen is the server to forward to an endpoint on the Zuul server that will get proxied back to the OAuth server. (The Zuul API-Gateway should be the only server the client ever talks to. Everything else will be hidden.)

As it is the host and port are read from the HttpServletRequest in LoginUrlAuthenticationEntryPoint. But the request the server sees is the request send by the Zuul proxy. So I am forwarded to an internal IP not an endpoint on the proxy.

I tried to set the URL of the login page in WebSecurityConfigurerAdapter.configure(HttpSecurity) to the absolut URL of my Zuul Proxy. But this just caused my application to complain about too many redirects. (Might have caused a loop there.)

What would be the best way to set this up?

  • Do I have to implement some kind of own forwarding strategy by overriding a bean?
  • Is there a configuration option I am missing?
  • Is my idea itself wrong? (In his answer to How to avoid redirect to another host with Zuul? Dave Syer says you would not normally proxy this but does not explain why.)
fap
  • 663
  • 1
  • 5
  • 14
Tobias Kremer
  • 1,531
  • 2
  • 15
  • 21

2 Answers2

20

Update: POC can be found here https://github.com/kakawait/uaa-behind-zuul-sample


Did you try following setup (on zuul server):

zuul:
  routes:
    uaa-service:
      path: /uaa/**
      stripPrefix: false

security:
  # Disable Spring Boot basic authentication
  basic:
    enabled: false
  oauth2:
    sso:
      loginPath: /login
    client:
      accessTokenUri: https://<zuul hostname>/uaa/oauth/token
      userAuthorizationUri: https://<zuul hostname>/uaa/oauth/authorize
      ...

Basically it works on my project only thing I have to do is to disable CSRF protection on /uaa/oauth/token route.

Auth server should be on

server:
  # Use different context-path to avoid session cookie overlapping
  context-path: /uaa

Tested using Spring-Cloud.Brixton.M3


Thank to @thomas-letsch, you should tweak you security like following (sample)

public void configure(HttpSecurity http) throws Exception { 
    http.logout().and()
        .antMatcher("/**").authorizeRequests() 
        .antMatchers("/index.html", "/home.html", "/", "/uaa/oauth/**").permitAll() 
        .anyRequest().authenticated().and() 
        .csrf().csrfTokenRepository(getCSRFTokenRepository()).ignoringAntMatchers("/uaa/‌​oauth/token").and() 
        .addFilterAfter(createCSRFHeaderFilter(), CsrfFilter.class); 
} 
barfuin
  • 16,865
  • 10
  • 85
  • 132
Kakawait
  • 3,929
  • 6
  • 33
  • 60
  • This works for me as well. I had to exclude the /uaa/oauth path from security. See this part from my WebSecurityConfigurerAdapter: – Thomas Letsch Feb 11 '16 at 14:37
  • public void configure(HttpSecurity http) throws Exception { http.logout().and() .antMatcher("/**").authorizeRequests() .antMatchers("/index.html", "/home.html", "/", "/uaa/oauth/**").permitAll() .anyRequest().authenticated().and() .csrf().csrfTokenRepository(getCSRFTokenRepository()).ignoringAntMatchers("/uaa/oauth/token").and() .addFilterAfter(createCSRFHeaderFilter(), CsrfFilter.class); } – Thomas Letsch Feb 11 '16 at 14:37
  • In my personal case I rewrite `OAuth2ClientContextFilter` to support `URI` (and not only `URL`) thus I can use `accessTokenUri: /uaa/oauth/token`. And for `userAuthorizationUri` I use `localhost` like following `userAuthorizationUri: http://localhost/uaa/oauth/authorize`. Thus configuration is portable (I don't need to know where UAA is located). I opened an issue for that https://github.com/spring-projects/spring-security-oauth/issues/671 – Kakawait Feb 12 '16 at 09:08
  • Interesting approach. As I see, it's meant to provide an authorization point in the zuul server itself. However, where do you tell zuul where the real OAuth Server lies? I mean, you've provided `` in the zuul configuration to enable it authorizing over himself, but how does it know the real authorization endpoint? – Aritz May 20 '16 at 09:30
  • I created a poc with extended doc that should answer your previous question https://github.com/kakawait/uaa-behind-zuul-sample – Kakawait May 20 '16 at 09:33
  • I cannot tell you how long it took for me to find this! And you are using JWT! Amazing! Keep up the good work! – Kent Bull Apr 11 '17 at 03:35
4

As far as I understand your question, spring-cloud-security (for the EnableOauth2Sso part) and spring-cloud (for zuul), this is not possible to proxy the calls to the authorization server using zuul. The main reason being that spring-cloud-security secures the Gateway independently (and before accounting for) Zuul routing's logic.

Which means that the (sample configuration from Dave Syer's OAuth2 example) spring.oauth2.client.* configuration

spring:
  oauth2:
    client:
      accessTokenUri: http://localhost:9999/uaa/oauth/token
      userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
      clientId: acme
      clientSecret: acmesecret

is considered before allowing any access to the Zuul's routes zuul.routes.*

Moreover this setup enables the client agent to store two Cookies: one for the Gateway and one for the Authorization Server.

I hope this helps.

Jérémie
  • 557
  • 4
  • 15