I have a few microservices that validate and identify the user using Keycloak as below
I now want to place the Apache APISIX API Gateway before the microservices.
Apache APISIX has a plugin for Keycloak. Can the plugin do the following such that the validation is removed from all the microservices?
Validate the access_token from the user
If valid, forward the request to the microservice
Note
This article gives details on how to integrate the Keycloak plugin such that the user will have to authenticate using Keycloak (using a single Keycloak client_id and client_secret). In my case, however, each user will have a different client_id and client_secret.
Can the plugin do the following such that the validation is removed from all the microservices?
Yes, it can. The Apache APISIX can validate the access_token, also can add the user_info, id_token to the upstream.
For more details, you can refer to the plugin docs of Apache APISIX. https://apisix.apache.org/docs/apisix/plugins/openid-connect.
In my case, however, each user will have a different client_id and client_secret.
Now, Apache APISIX doesn't support setting more than one client id of openid-connect in a route.Maybe you can create more routes, each route for each client? And use Host to distinguish them.
Related
One can define an OAUTH2 server easily based on the quarkus documentation.
quarkus.oauth2.client-id=XXXX
quarkus.oauth2.client-secret=YYYY
quarkus.oauth2.introspection-url=https://example.com/oauth2/...
How should I configure quarkus if I have to give the option to the users to choose their own OAUTH2 provider (github, gitlab, whatever)?
One solution can be running separate Quarkus instances for each OAuth2 provider.
If you need to have all requests to be sent to same path and port, a mediator instance can be created for handling requests and sending them to appropriate instance with chosen OAuth2 provider.
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
Our stack includes the following services, each service runs in a docker container:
Front-end in React
Backend service based on Spring boot "resource-service"
Keycloak
Other backend service (consumer)
Both the front-end and the consumer services communicate with the backend using REST API.
We use Keycloak as our user management and authentication service.
We would like to integrate our Spring based service "resource-service" with Keycloak by serving both web application and a service flows:
Web application - React based front-send that should get a redirect 302 from the "resource-service" and send the user / browser to login in the Keycloak site and then return to get the requested resource.
Server 2 Server coomunication - A server that need to use the "resource-service" API's should get 401 in case of authentication issues and not a redirection / login page.
There are few options to integrate Spring with Keycloak:
Keycloak Spring Boot Adapter
Keycloak Spring Security Adapter
Spring Security and OAuth2
I noticed that there is a "autodetect-bearer-only" in Keycloak documentation, that seems to support exactly that case. But -
There are a lot of integration options and I'm not sure what is the best way to go, for a new Spring boot service.
In addition, I didn't find where to configure that property.
I've used approaches one and two and in my opinion, if you are using Spring Boot, use the corresponding adapter, use the Spring Security adapter if you're still using plain Spring MVC. I've never seen the necessity for the third approach as you basically have to do everything on your own, why would anyone not use the first two methods?
As for using the Spring Bood adapter, the only configuration necessary is the following:
keycloak:
bearer-only: true
auth-server-url: your-url
realm: your-realm
resource: your-resource
And you're done. The bearer-only is so that you return 401 if a client arrives without a bearer token and isn't redirected to a login page, as you wanted. At least that's what's working for us :-)
After that, you can either use the configuration for securing endpoints but it's a bit more flexible to either use httpSecurity or #EnableGlobalMethodSecurity which we're doing with e. g. #Secured({"ROLE_whatever_role"}).
If you're using the newest Spring Boot version combined with Spring Cloud, you might run into this issue.
I configure my resource-servers to always return 401 when Authorization header is missing or invalid (and never 302), whatever the client.
The client handles authentication when it is required, token refreshing, etc.: Some of certified OpenID client libs even propose features to ensure user has a valid access-token before issuing requests to protected resources. My favorite for Angular is angular-auth-oidc-client, but I don't know which React lib has same features.
Keycloak adapters for Spring are now deprecated. You can refer to this tutorials for various resource-server security configuration options. It covers uses cases from most simple RBAC to building DSL like: #PreAuthorize("is(#username) or isNice() or onBehalfOf(#username).can('greet')")
I have a legacy desktop application that communicates with a Spring Boot server (latest version 2.2.2.RELEASE). I'm using OAuth2 for authentication (provided by spring-boot-starter-oauth2-client). I want to avoid changing the client because is a legacy application. It is capable of collecting the credentials and start the session via HTTP Basic Authentication, and then keep the cookies for the session in the following requests.
Given this scenario, I think best option is to make use the OAuth2 Resource Owner Password Credentials grant. With this, we can exchange the collected credentials by the OAuth2 Tokens. We have two options:
Option 1:
Modify the client application to use the access tokens via the Authorization header. This will require to make an initial call to the Authorization Provider to exchange the collected credentials by the tokens.
Option 2:
Keep using the Spring session and store the information about the OAuth client in the server.
I found this project ALMOST does that: https://github.com/jgrandja/spring-security-oauth-5-2-migrate. It has a client (messaging-client-password) defined with authorization-grant-type: password which will activate the OAuth2 Resource Owner Password Credentials grant in Spring Boot.
It creates an OAuth2 client and stores its information in the session, then Spring is able to use that client in further requests. The problem with this project is it seems to only work as when the OAuth client is used to make HTTP requests (e. g. an endpoint that makes a call to another service) and not provide authentication to the controller. You can find more information about this in here:
Spring Security 5.2 Password Flow
Github related issues: link1, link2, link3
Exception thrown when we try to use the password client as authentication
The natural idea to overcome this is to implement a proxy and use the OAuth2 client in the requests. Well, Spring already offers a proxy solution, the Spring Cloud Gateway. But I don't know to accomplish that with this setup.
Any insights? Am I thinking correctly or should I follow a different approach?
I have a spring cloud oauth #EnableAuthorizationServer that uses a jpa backend to store the accounts. I also have a couple of different clients, a website, an intranet and a ionic mobile app.
all the clients have separate client credentials inline in the oauth config block.
i have then tried to use the spring cloud sso to not have to login again.
my problem is that I want to remove the authorize step since all my clients are known to me and i simply want the user to be logged in across all my apps.
is this possible with spring cloud sso?
The authorization happens on the authorization server (so nothing to do with Spring Cloud). A UserApprovalHandler would do what you need, but the default one should work if you just set autoapprove=true (or a pattern matching te scopes you want to auto approve) in the client details. (Assuming your auth server is Spring OAuth.)