Coder Social home page Coder Social logo

uaa-behind-zuul-sample's Introduction

UAA (AuthorizationServer) load balanced behind API-GATEWAY (Edge service Zuul)

Twitter Follow

Disclamer

This project is Proof of concept (aka PoC) (and code quality is not perfect), please before using in production review security concerns among other things. (See kakawait#6)

Change Log

see CHANGELOG.md

Overview

Quick&dirty sample to expose how to configure AuthorizationServer (UAA) behind Zuul

This way to do may not work for all kind of configuration (I do not test without JWT and prefer-token-info: true)

Usage

Please deploy every services using docker way or maven way, then simply load http://localhost:8765/dummy on your favorite browser.

Default user/password is user/password

Docker

Start building docker images for every services, simply run following command on root directory

mvn clean package -Pdocker

Launch services using docker-compose

docker-compose up -d

Maven

On each service folder run following command:

mvn spring-boot:run

Run

Open http://localhost:8765/dummy and connect with:

  • user: user
  • password: password

Goals

  1. Avoid any absolute/hardcoded urls for security.oauth2.client.accessTokenUri & security.oauth2.client.userAuthorizationUri in order to improve portability!
  2. AuthorizationServer distribution for HA
  3. Do not expose AuthorizationServer, like other service AuthorizationServer will be behind Zuul

network

Where localhost:8765 is Zuul, as you can see AuthorizationServer is not leaked outside! Only Zuul is targeted.

ATTENTION for 2. you should manage yourself shared storage backend (unlike following sample)! Using database or something els.

Keys points of the sample

[Zuul] Custom OAuth2ClientContextFilter

I had to override OAuth2ClientContextFilter to support URI and not only URL (see DynamicOauth2ClientContextFilter). Indeed URL does not support path like /uaa/oauth/authorize.

Why adding path support on OAuth2ClientContextFilter?

Because I want to use path on security.oauth2.client.userAuthorizationUri in order to redirect user to Zuul itself.

On this case I can't use http://localhost:${server.port}/uaa/oauth/authorize because security.oauth2.client.userAuthorizationUri is use on web redirection (header Location: ).

Flow will look like following

Browser                             Zuul                               UAA
   │        /dummy                   │                                  │
   ├────────────────────────────────>│                                  │
   │  Location:http://ZUUL/login     │                                  │
   │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤                                  │
   │        /login                   │                                  │
   ├────────────────────────────────>│                                  │
   │  Location:/uaa/oauth/authorize  │                                  │
   │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤                                  │
   │     /uaa/oauth/authorize        │                                  │
   ├────────────────────────────────>│                                  │
   │                                 │      /uaa/oauth/authorize        │
   │                                 ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄>│
   │                                 │                                  ├──┐
   │                                 │                                  │  │ Not authorize
   │                                 │                                  │<─┘
   │                                 │  Location:http://ZUUL/uaa/login  │
   │                                 │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
   │                                 │                                  │
   │ Location:http://ZUUL/uaa/login  │                                  │
   │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤                                  │
   │       /uaa/login                │                                  │
   ├────────────────────────────────>│                                  │
   │                                 │            /uaa/login            │
   │                                 ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄>│
   │                                 │           LOGIN FORM             │
   │                                 │<┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
   │           LOGIN FORM            │                                  │
   │<────────────────────────────────┤                                  │

Take attention on second redirection, location is using path (not at browser level).

[Zuul] localhost trick for security.oauth2.client.accessTokenUri

Unlike security.oauth2.client.userAuthorizationUri, security.oauth2.client.accessTokenUri is not used a browser level for redirection but used by RestTemplate. However default RestTemplate used for accessTokenUri is not load balanced thus we can't use url like http://service-name/oauth/token.

We can simply add load balanced feature by adding such Bean

@Bean
UserInfoRestTemplateCustomizer userInfoRestTemplateCustomizer(SpringClientFactory springClientFactory) {
    return template -> {
        AccessTokenProviderChain accessTokenProviderChain = Stream
                .of(new AuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(),
                        new ResourceOwnerPasswordAccessTokenProvider(), new ClientCredentialsAccessTokenProvider())
                .peek(tp -> tp.setRequestFactory(new RibbonClientHttpRequestFactory(springClientFactory)))
                .collect(Collectors.collectingAndThen(Collectors.toList(), AccessTokenProviderChain::new));
        template.setAccessTokenProvider(accessTokenProviderChain);
    };
}

An opened isse exists spring-attic/spring-security-oauth#671

[Zuul] Clear sensitiveHeaders lists for AuthorizationServer route

Since Brixton.RC1, Zuul filters some headers (http://cloud.spring.io/spring-cloud-static/spring-cloud.html#_cookies_and_sensitive_headers).

By default it filters:

  • Cookie
  • Set-Cookie
  • Authorization

But we need that AuthorizationServer could create cookies so we must clear list

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

TODO Check if zuul.routes.uaa-service.sensitiveHeaders: Authorization could work?

[Zuul] Disable XSRF at gateway level for AuthorizationServer

AuthorizationServer has it own XSRF protection so we must disable at Zuul level

private RequestMatcher csrfRequestMatcher() {
    return new RequestMatcher() {
        // Always allow the HTTP GET method
        private final Pattern allowedMethods = Pattern.compile("^(GET|HEAD|OPTIONS|TRACE)$");

        // Disable CSFR protection on the following urls:
        private final AntPathRequestMatcher[] requestMatchers = { new AntPathRequestMatcher("/uaa/**") };

        @Override
        public boolean matches(HttpServletRequest request) {
            if (allowedMethods.matcher(request.getMethod()).matches()) {
                return false;
            }

            for (AntPathRequestMatcher matcher : requestMatchers) {
                if (matcher.matches(request)) {
                    return false;
                }
            }
            return true;
        }
    };
}

[Zuul] Authorize request to AuthorizationServer

Ok should I really need to explain why?

http.authorizeRequests().antMatchers("/uaa/**", "/login").permitAll()

ATTENTION do not use "/uaa/**" authorize only necessary API (I was to lazy)

[UAA] Deploy AuthorizationServer on isolated context-path

Zuul and AuthorizationServer have to manage their own session! So both have to write two JSESSIONID cookies.

You must isolate AuthorizationServer on other context-path server.context-path = /uaa to avoid any cookies collision.

ALTERNATIVE we can check if server.session.cookie.path or server.session.cookie.name is not sufficient, I did not test it.

[UAA] Enable server.use-forward-headers

Does not work without. I will not explain why, please look about X-Forwarded-* headers for more information.

uaa-behind-zuul-sample's People

Contributors

kakawait avatar kentoj avatar bilak avatar

Watchers

DY avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.