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.
Related
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.
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.
In my project, there is a mobile app, an angular web app, 4 micro services and one api gateway. The users with role 'agent' can enroll customers using the mobile app. The web app is for users with role 'manager' to see the customer data and finalize on the customer enrollment.
Here, if I want to set up Keycloak for authentication, should I add
every micro service as a separate client ?
Should I add mobile app and web app as separate clients in keycloak ?
CLIENTS
The web and mobile app must be registered as separate OAuth clients. They will have a client ID but no client secret since they are public clients. They will use PKCE and have different redirect URIs, eg:
Web: https://www.example.com/callback
Mobile: com.example.app:/callback
APIs
By default APIs do not need to be registered as clients. In most setups related microservices can just forward JWT access tokens to each other, as explained in the scopes article. This is a secure way to maintain the user identity.
APIs sometimes act as clients though, eg if they need to do something like create users in Keycloak programmatically. Identity systems provide User Management Endpoints to enable this.
So one of your APIs, eg a Users Microservice, may need to be registered as a client. It would use the client credentials flow to get an access token with a SCIM related scope.
GATEWAY
It is common, and recommended, for a gateway to act as an introspection client. This enables data in access tokens returned to internet clients to be kept confidential. Read more about this in the phantom token pattern.
I'm planning to make a microservices architecture using Laravel as the backend and VueJs or maybe ReactJs as the frontend. The microservices will consist of
User authentication service (For authenticating user)
User management service (To manage organization member database)
Event management service (For creating organization event)
Etc.
All of the services will require user request to be authenticated, but using central user database, which is located on User authentication service. Eventually, on each web application, it will use at least 2 of the services.
How am I able to authenticate the user before making the request to the specified services? Thanks in advance!
Think carefully about your reasoning for developing a distributed system with a microservice architecure. Developing such a system can be complicated and might introduce more problems than it solves for you. You should consider things like code base management, data synchronisation and service availability for example. A standard monolithic architecture with the frontend (Vue/React) and backend (API) as separate projects will be simpler and may provide the flexability you need. Should the need arise in the future to develop a service orientated architecture arise, worry about it then.
That said, typically you wouldn't allow direct access to your services. There would be an API gateway which users access and it proxies requests to the relevant service. So your users would make a request to api.domain.tld/auth/login which would then be forwarded by the gateway to your auth service, process the request and then provide a failure response, or a success response which would include some sort of auth token which would be used to authorise subsequent requests to your other services. Sometimes services are aware of each other and can communicate directly if require, other times they use the API gateway for service communication.
I am currently building a microservices based application in spring boot with the following services
Auth server (Distributes access tokens)
User service (User info like username, password, email, etc.)
Various other unrelated services
When a user sends their credentials to the auth server, the auth server should verify that they are correct and then return an access token.
My question is, should I combine the auth server with the user service so looking up credentials is a simple database call, or should I keep them as separate applications and have them both point to the same shared database? Is there a better alternative?
What I usually do is keep them separate. Account information (first name, last name, contact data, affiliation, sex etc) is not related to authentication/authorization. Also, an account can have multiple authentication methods (i.e. OAuth, uname-pass, private key), which isn't really related to account data. So, I take them as separate entities. I know auth and account data seem the same, but they represent two very different things, with very different responsibilities, so I keep them separate. If one user should have to see some other user's first and last name, I wouldn't like to get other user's credentials out of the database (a lot can go wrong).
If you are thinking of UserService from Spring Security, it goes with Auth server.
From security stand point, having a single point of truth (auth server) and be able to fix an issue in one place is a huge advantage.
Anyhow, IMHO, account and auth can share some properties, but they are two different things - hence I keep them separate.
Hope this helps.
You should keep them separated, oauth is not related to identity management but to authorization delegation.
In oauth2 there are 4 roles (resource server, resource owner, client and authorization server) you are currently asking if the authorization server must be part of one microservice of the resource server which has absolutely no sense.
If I correctly got your case what you name a user corresponds to the resource owner role in oauth2 terminology, some oauth2 flows (e.g. client_credentials) directly allow a client to get an access to the resource server and there will be no users implied in any way.