Spring boot Oauth2 SSO with Zuul proxy and multiple clients (native, mobile, web) - spring

I'm currently working on a project that uses Zuul to proxy requests to both API endpoints as well as client resources. There is an angular app that is being served from the same endpoint as the Zuul proxy as outlined in this guide. I have the need for additional clients, specifically a desktop application.
I'm not sure I understand how Zuul proxy handles requests and I think there are several paths to get to where I want to go, I'm just not sure what the correct one is.
Here is what I have surmised thus far:
Option 1: Extract the Zuul proxy and SSO capabilities to it's own server. Then create a new UI server which is behind the gateway server. Follow this up with creating a new client application server which handles the authentication of the desktop client.
Option 2: Extract the Zuul proxy and SSO capabilities to it's own server. Serve the current angular app from its own server NOT behind the proxy and change the authorization flow to something different (implicit). Alter Zuul proxy and SSO configuration to ignore requests that already have a bearer token in the header.
If I go with option 2 then I don't understand how to register with the Zuul gateway client that I already am providing the authorization header with my requests so all it should be doing then is proxying my requests to the correct microservices.
Final Questions:
Which option is the most optimal one?
If an access token is already acquired (directly from the auth server using implicit flow) then how does Zuul need to be configured to not try and acquire the access token using the jsessionid?

Related

How to secure Spring Cloud microservices using Spring Security?

Here is the authorization service. It has endpoints to login and receive a JWT using either a custom username/password or social OAuth (Facebook, GitHub etc.).
I have a Eureka server setup and Zuul gateway service. From what I understand, there are two ways to go about implementing secure microservices. You either proxy requests through the auth service, or you send requests to the requested service (Ex. Service A) and service A authorizes using the auth service.
I would like to use the second way, however I'm having trouble implementing it. Is my understanding correct? Is there a way to setup service A somehow so that certain paths (configured using Ant matchers) will have to authorize using the auth service, which will set the SecurityContext appropriately and inject a UserPrincipal into the request. If anyone can point me to a good guide for this that would be much appreciated.

Keycloak authentication flow in a microservices based environment

I want to use Keycloak in a microservices based environment, where authentication is based on OpenID endpoints REST calls ("/token", no redirection to keycloak login page), a flow that I thought of would be something like this:
1. Front-end SPA retrieves the tokens from the "/token" endpoint and stores in browser's localStorage, then sends it with every request.
2. Gateway-level authentication: Acess Token is passed from the front end to the gateway, gateway consults Keycloak server to check if the token is still valid (not invalidated by a logout end-point call).
3. Micro-service based authorization: Acess Token is passed from the Gateway to the microservices, using Spring Boot adapter the microservices check the signature of the token offline (bearer-only client?) then based on the role in the token do the authorization.
My questions are: Does this flow make sense or can you suggest another flow? What type of Keycloak clients to use? What's an ideal way to pass Tokens using Spring Boot Adapter, and should it be done like that in the first place? Please keep in mind that I am not a Keycloak expert, I've done my research but I still have doubts.
Your Front-end SPA should be public-client and springboot micro service should be Bearer only Client and Gateway could be Confidential Client.
You can check the Keycloak provided oidc adapters. For springboot you use the keycloak provided adapter
Similar solution using api gateway is discussed here

Spring cloud oauth 2 with ingress kubernetes

Is it possible to use spring cloud oauth 2 server with kubernetes api gateway ingress.
I have used it with zuul to authenticate user before making a call. Can I do similar with ingress?
Edit 1:
To explain it more clearly, what I am trying to achieve
I am using token based oAuth2 implementation given by the spring cloud.
oauth is running as one of the service behind the zuul.
zuul has routes mapped for the oauth server and resource server
client call the auth server via zuul and gets the token.
client call resource server via zuul with token passed
zuul is configured to validate the token before making a call to resource server.
In this way we can stop any downstream traffic to go without a valid token.
can we do token validation in ingress with auth server running with in a cluster?
I have not used Spring Cloud OAuth 2 but as OAuth is a standard I believe you can set it up if you are using Nginx Ingress as the ingress controller, you can specify and external Oauth Provider (As OAuth generally has the same flow) like this on your ingress:
...
metadata:
name: application
annotations:
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
...
You can find more information here with an example of using GitHub as an OAuth provider
There are currently three different nginx-ingress-controllers (see here), which differ in functionality. I believe that none of these ingress controllers themselves can perform an oauth token introspection. However, requests can be routed to the authorization server's introspection interface using the auth_request module.
Specifically for your case, you can use the auth-url annotation (see) in the ingress controller to direct the requests to the introspection interface of the spring cloud oauth2 server (see). The introspection interface is available under /oaut/check_token by default when #EnableAuthorizationServer is used. If the introspection interface returns a 2XX, the ingress will forward the request. This functionality is based on the auth_request module, which expects a 2xx response code from the external service if the access is allowed and 401 or 403 if denied.
If you use JWTs and want to validate the request by only checking the signature, this can in some cases actually be done by the ingress itself. To my knowledge, only the nginx plus ingress controller (paid) can validate JWTs. But there is also the nginx-based kong-ingress controller, which you can equip with pulgins (see here). There is e.g. promoted with oauth2 integration and JWT validation.
Did you find out more than me?

What to do with original API when using a API-Gateway

I'm wondering what to do with an API Endpoint when using a API Gateway. For example when you following the tutorial here: https://wiredcraft.com/blog/securing-components-in-a-microservice-context
You are using keycloak and kong (api-gateway) to secure the api. With kong you're getting an new Endpoint under http://localhost:8000/data. But the "original" express Server is still listening on http://localhost:3001/data.
That means that when a user/attacker knows the url of the "orignal" service and doesn't use the kong url (port 8000) he/she can still work with the api.
So my question is about the strategy and what to do with the original api? How could that be secured. Shall we implement the keycloak request on the api as well? But where are the benefits of kong then?
Your API gateway gives you a single entrypoint that simplifies how client applications access your services. You could add keycloak security on the gateway and not on the services behind - perhaps if you've a setup where you can block network access for clients to any services except the gateway. But even then you might still want the gateway and keycloak on the services behind.
The reason you might put keycloak on the services behind is because they are likely to need to know the identity of the user making the request. If they are going to read the token anyway then it might be most straightforward to add keycloak to them. And you'd still want the gateway to simplify life for clients. You'd then also want the gateway to forward the token to the services behind the gateway. (We're using keycloak and spring cloud gateway on the Activiti Cloud project and this is essentially how we decided to secure the services themselves with keycloak and have the gateway forward the token to them.)

How API gateway is correctly used in Microservice?

Suppose there are 2 backend services:
A product service (to get the product info),
An inventory service (to get the available quantity).
Additionally to that, there is a frontend web application to display product details.
All the examples I see on the internet are about the frontend and the API gateway being the same application and using Zuul just as a reverse proxy.
My understanding is API gateway should be a separate application (layer) and frontend application should use it to call backend services.
In that case what is the benefits of Zuul? why not just use feign to create a client for both services and provide an endpoint for the frontend application ?
Feign client and Zuul are two entirely different components in Spring Cloud Netflix.
Feign Client is a glorified REST Template with additions such as Retry, Fallbacks etc. You can think along the lines of Apache HttpClient
Zuul on the other hand is a proxy / reverse - proxy / gateway. Typically Gateway should be a common entry point to your backend services. It should be a separate layer which allows you to add common functionalities like Authentication, Auditing, Logging etc. As #ootero mentioned, you can easily add Filters in Zuul to achieve this functionality.
Zuul as a Proxy server not only route requests but Zuul filters could also be used for handling crosscutting concerns like:
geolocation
token decryption
authentication
request / response manipulation
Traffic shaping
You mention Feign clients and that would work (to the best of my knowledge) with Java-based front-end apps, what if the front-end app is developed with Angular or React?

Resources