UAA (AuthorizationServer
) load balanced behind API-GATEWAY (Edge service Zuul
) with remote authentication
This is a fork from kakawait's excelent POC, Most of the code is exactly the same as in his POC but for the uaa-service that I have changed to remote the authentication to google (have also a facebook configuration).
see CHANGELOG.md
See kakawait's POC for basic instructions.
First, state that sorry for any mistakes. English is not my native language.
I have tested this using kakawait's maven's way, if somebody else wants check if it works using the docker's way, feel free to report your findings.
Before starting, you will need to setup a Google Oauth2 app using Google API Console. Once that is done, upload your local copy of '/uaa-service/src/main/resources/application.yml' replacing the entries for google.client.clientID and google.client.clientSecret with the correct values generated in the Google API Console.
Once this is setup, on each service folder run following command:
mvn spring-boot:run
Kakawait's POC used plain user/password user management using a basic spring OAuth2 server. I have replaced that with a modified version of the authorization server as presented in Spring's Spring boot and OAuth2 guide. Replacing such a piece piecemeal worked, but it exposed local OAuth2 endpoints instead of using the Zuul proxied endpoints. While this works localy, it has a couple of problems:
- it broke Kakawait's goal #3: Do not expose AuthorizationServer
- while it works locally, it will not work if you deploy in Kubernettes or any other architecture that hides internal microservices endpoints.
To fix this I have extended Spring's LoginUrlAuthenticationEntryPoint and RequestCache
LoginUrlAuthenticationEntryPoint is one of the AuthenticationEntryPoint provided by the spring security project to forward user to a login form. This class provides a buildRedirectUrlToLoginPage method that allows subclasses to change the way the URL to the login page is generated. I have extended that method in the ProxyAwareLogingAuthenticationEntryPoint so that it detects if there is a 'x-forwarded-host' proxy header and, if it is present, it generates a URL that honors those headers ('x-Forwarded-Proto', 'x-forwarded-host' and 'x-forwarded-prefix').
Spring Security also uses the 'HttpSessionRequestCache' mechanism to redirect the user to the original petition once it has completed the authentication process. This classes also do not honor proxy headers, so the redirection was done to the internal URL of the authentication service instead of the proxied URL exposed by Zuul. To honor those headers I have:
- Created a 'ProxyAwareSavedRequest' that extends Spring's 'DefaultSavedRequest' to check if there are proxy headers on the original request and honors them. The original implementation already had all the header information, but UrlUtils.buildFullRequestUrl() does not check for proxy headers.
- Created a 'ProxyAwareRequestCache that extends Spring Security's 'HttpSessionRequestCache' to use 'ProxyAwareSavedRequest' instead of the original 'DefaultSavedRequest'