We are considering using Keycloak for our public REST APIs (mostly Spring boot apps) to authorize and authenticate our users.
In order not to make the admin UI publicly available we want to restrict it.
Our idea is to create two instances but access the same database.
the public Keycloak instance, which only publishes what is necessary e.g. the admin path is not accessible. In this instance only paths should be accessible like these recommended here: https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations.
a private Keycloak instance, which is only accessible from the internal network, but offers the admin UI (console). With which one can then manage the users/permissions.
Is this a valid solution to have two different instances but with the same database or are there other best practices here to not publish the admin ui/paths?
Yes, this is definitely a common setup. Depending on your requirements, it is always recommended to have more than one instance of Keycloak on the same database, for availability reasons. Keycloak shares some in memory data (like sessions) in an Infinispan Cache, which is shared between one or more instances of Keycloak (generally referred to as a cluster)
You would then use a load balancer (like haproxy, nginx, apache, the choices are practically endless) and configure it to send requests to the actual Keycloak instances.
A possible setup could be the following: Using 4 Keycloak instances on 4 servers:
public-keycloak-1.internal.example.com
public-keycloak-2.internal.example.com
private-keycloak-1.internal.example.com
private-keycloak-2.internal.example.com
You can then add 2 load balancers:
keycloak.example.com (sending requests to public-keycloak-*)
keycloak.internal.example.com (sending requests to private-keycloak-*)
In this example, keycloak.internal.example.com would be the instance you connect to, in order to perform administrative tasks in Keycloak via the Admin Console, or the Admin API, and keycloak.example.com would be the host that you use for Auth{n,z} for your applications.
Restricting access to the Admin API and Admin Console can be done at the load balancer level (restricting requests to those paths), but since Keycloak 20, it is also possible to completely disable the Admin API and Admin console. This is done through the disabling the respective features seen in the documentation. That way, you can disable the features "admin-api", "admin" and "admin2". If you do this on the public-keycloak-* instances, then requests to the public load balancer can never end up touching the Admin API or Console, because Keycloak is configured to simply not serve those requests in the first place.
Related
I am currently working with spring boot micro services. To access those services I am using api gateway with Eureka client but I have one question to secure my service.
Consider I have below 4 microservice project hosted locally.
User :- hosted on http://localhost:8080/user
owner :- hosted on http://localhost:8081/owner
security :- hosted on http://localhost:8082/security
and api gateway :- hosted on http://localhost:9090/
so now to access services of owner I am first calling api gateway than security project after authenticating it is allowing me to access service of owner project .I am calling owner project from security project using feign client.
api gateway ---> security ---> owner
using url http://localhost:9090/security/owner
I am able to access owner project using that flow but now my question is I am also able to call directly owner project using it's own port. As shown below:-
http://localhost:8081/owner
How can I restrict that direct access to owner project?
The simplest solution would be for owner service to expect some kind of access token within the request. Such a token should be provided by security service (i.e. it could inject it within Authorization header), when it forwards request.
In more complex environment, in which multiple services may required different level of access to other services, more sophisticated solution would be required, i.e. involving mutual TLS where each service has its own certificate. But that would require much more setup. However that's worth doing on complex production systems.
One more element that could be used to control such access is the service mesh. You can read up on the topic - example: Istio.
Spring Cloud Zuul is most commonly used with JWT to authorize/decide if a user has access or not to a particular service. But this seems to be quite high level.
What I mean is, if there are services to which users can have full or part access, how to go about it. As an example, if there is PhotoAlubum service - which allows
certain users to view photos/albums,
certain users to edit tags/albums etc,
certain users to create new alubums and
certain users to add photos
Now from my understanding, Zuul, will either allow or deny a users access to a service. If the user has no access to the service then denying is fine. But what about above situation, if the user has access to the service but has limited authorisation, the user can still perform any of the above actions. How to handle this situation using ZUUL or Spring Security.
Edit - as a related Q - Does zuul allow url and method based access apart from service based access.
I have a request to restrict the access (access control) to a small user community in GCP.
Let me explain the question.
This is the current set up:
A valid GCP Organization: MyOrganization.com (under which the GCP project is deployed / provisioned)
Cloud DNS (To configure domain names, A & TXT records, zones and subdomains to build the URL for the application).
Oauth client set up (tokens, authorized redirects URIs, etc.).
HTTPS load balancer (GKE -managed k8s service- with ingress service), SSL certificate and keys issued by a trusted CA.
The application was built using python + Django framework.
I have already deployed the application (GCP resources) and it is working smooth.
The thing is that, since we are working in GCP, all IAM users who has a valid userID#MyOrgnization.com can access the application (https://URL-for-my-Appl.com).
Now, I have a new request, which consists in restricting access (access control) to the application only for a small user community within that GCP organization.
For example, I need to ensure that only specific IAM users can access the application (https://URL-for-my-Appl.com), such as:
user1#MyOrganization.com
user2#MyOrganization.com
user3#MyOrganization.com
user4#MyOrganization.com
How could I do that, taking into account the info I sent earlier ?
thanks!
You can use Cloud IAP (Identity Aware Proxy) in order to do that.
Identity-Aware Proxy (IAP) lets you manage access to applications
running in App Engine standard environment, App Engine flexible
environment, Compute Engine, and GKE. IAP establishes a central
authorization layer for applications accessed by HTTPS, so you can
adopt an application-level access control model instead of using
network-level firewalls. When you turn on IAP, you must also use
signed headers or the App Engine standard environment Users API to
secure your app.
Note: you can configure it on your load balancer.
It's not clear in your question if your application uses google auth (but considering that you talk about org-restricted login I think so) - if that's the case you should be able to enable it without virtually touching anything in your application if you are using the Users API.
The best and easiest solution is to deploy IAP (Identity Aware Proxy) on your HTTPS Loadbalancer
Then, grant only the user that you want (or create a gsuite user group and grant it, it's often easier to manage)
This is what I want to happen.
Current Setup: Two wars deployed in Websphere v8 (App1 and App2). Both have a login feature where users enter username and password to get in the app. This is not using LDAP or JAAS, its just plain query from the db to check if username and password is correct.
Problem: There had been a move to "combine" the two apps where authenticated users in App1 can now access App2 directly without logging in and having the same session. If user accesses a module in App2 without logging, user will be directed to login page of App1 to login.
Other factors:
App1 and App2 are in the same websphere instance in the same box and in the same cell.
Question:
Is it possible to implement SSO and shared session between App1 and App2 in websphere?
From what I read you are either performing the authentication on your own with App1 and App2, meaning without using WebSphere Security or you have both applications inside two different WebSphere Cells where no SSO is setup.
If it is option 1 I strongly recommend you to take a look at WebSphere Security and what the container provides you there.
Which brings me to option two cells without SSO
WebSphere Application server builds out by default a Cell wide SSO model. A cell means a collection of servers which are controlled together. By default WebSphere uses a token named LTPA_Token or since 6.1 LTPA_Token2. At the cell level the security is configuired which includes the SSO domain, which is in fact "just" the cookie domain. WebSphere persists the authentication state inside of the token as a cookie and the browser will submit this to the server matching to the cookie domain.
Having said that. If you have two cells you can exchange the security keys between these two and so they can both understand the security Token created by both of them. You need to ensure some additional information like realm, security domain, attached user repository.
As you mentioned App2 should send all users to App1 you probably need to define the End point to handle the Authentication within your web.xml and have it point direct to App2 or write a TAI (Trust Association Interceptor) on App2 to send all not authenticated requests to App1
In addition you could as well put an authentication proxy in front of the two applications which will only ensure the authentication state and establish the security state as the request is passed to the backend.
For reference
WebSphere Application Server Infocenter Topic
I have developed a web app that does its own user authentication and session management. I keep some data in Elasticsearch and now want to access it with Kibana.
Elasticsearch offers a RESTful web API without any authentication and Kibana is a purely browser side Javascript application that accesses Elasticsearch by direct AJAX calls. That is, there is no "Kibana server", just static HTML and Javascript.
My question is: How do I best implement common user sign on between the existing web app and Elasticsearch?
I am interested in specific Elasticsearch/Kibana solutions, but also in generic designs for single sign on to web apps and the external web APIs they use.
It seems the recommended way to secure Elasticsearch/Kibana is to have an Apache or Nginx reverse proxy in front that does SSL termination and user authentication (Basic auth). However, this doesn't play too well with the HTML form user authentication in my existing web app. Ideally I would like the user to sign on using the web app, and then be allowed direct access to the Elasticsearch API as well.
Solutions I've thought of so far:
Proxy everything in the web app: Have all calls go to the web app (server) which does the authentication, and have the web app issue the same request to the Elasticsearch web API and forward the response back to the browser.
Have the web app (server) store session info that Apache or Nginx somehow can look up and use to authorize access to the reverse proxy.
Ditch web app sign on and use basic auth for everything.
Note that this is a single installation, so I don't really need any federated SSO solutions.
My feeling is that the proxy within web app (#1) is a common generic solution, but it seems a bit heavyweight to have everything pass through the possibly slow web app, considering that Kibana uses the Elasticsearch API directly.
I haven't found an out of the box solution designed for the proxy authentication setup (#2). My idea is to have the web app store session info in memcache or the like and use some facility in the web server (Apache or Nginx) to look up the session based on a cookie and allow proxy access if authenticated.
The issue seems similar to serving static files directly using the web server (Apache or Nginx) while authenticating using a slow web app. Recommendations I've found for that are however very specific to that issue, like X-Sendfile.
You could use a sessionToken. This is a quite generic solution. Let me explain this. When the user logs in, you store a random string an pass him back to him. Each time the user tries to interact with your api you ask for the session Token you gave him. If it matches, you provide the service he is asking for, else, you just ignore his call. You should make session token expire in a certain interval of time and make a new one each time the user logs back in.
Hope this helps you.