I'm trying to build a web-based SaaS solution in ASP.NET Core 2.0, with the help of micro-services architecture, token based authentication and service will be hosted on Docker. Each client has its own users, product and other details with multiple databases with shared schema. Each micro-service has its own database (Schema-per-service).
I hit a roadblock where I need to locate logged in user’s database credentials (connection string), so that database connection will be passed dynamically to respective micro-service to fetch data from respective client database?
I suppose that you have some sort of microservice to handle client authentication into his SaaS account and generate a token to consume the SaaS microservices (like a "private key") correct?
It's the perfect case for microservices architecture:
Create a microservice that domains resources about the client's environment configuration
This microservice receives requests with the client's private key
Then requests the authentication service to validate the passed private key
Get the response of the authentication service and some sort of client's unique key
Responds with the environment configuration corresponding to that client's unique key (or 404 if the auth token doesn't match with any client)
Now having this microservice (I'll call "environment microservice"), any other microservice of your SaaS just needs request the environment microservice to get client's configurations (database connection string, storage system and etc). From this point, you can implement some caching policy at each service to keep the private keys mapping to a set of configurations (and persistent database connections if your model permits). Just ensure that this cache has an interval to validate the tokens and configurations against the environment microservice.
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.
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.
Our current API use seesionID for the authentication. We plan to use Azure API management to manage our web api. However Azure web api management has their own authentication. How can we link those two together. Our customer can use the same logon information.
Conversations about authentication and identity in Azure API Management can get tricky because there can be three different identities and then there are the different contexts of runtime requests vs management requests. So, to be sure I'm answering the right question, let me try and get some terms defined.
The three identities:
API Provider: This is the Azure user who has created an API Management instance.
API Consumer: This is a developer who is writing some client software to consume the API.
End User: The user of the application written by the API Consumer and will be the one who actually initiates runtime requests to the API.
I am assuming that you are the API Provider. What I'm not sure about is whether your customers are the API Consumers or the End Users.
Azure API Management provides identity services for API Consumers. Consumers can either manually create a username/password account or use some social identity provider to create an account. They then can get a subscription key that will allow Azure API Management to associate requests to the API Consumer.
I think you are asking if you can connect the sessionID, which I am guessing you use to identify End Users, to a subscription key used to identify API Consumers. If that is correct, then the answer is no (except for the scenario described below), because we need to identify the API Consumer key before any policies are run to ensure we run the correct policies.
You can change our Api Consumer subscription key. So, if you only have a low quantity of customers/End Users you could create an Api Consumer account for each End User. However, you would only be able to map sessionID to API Consumer Subscription Key if sessionID was a constant value. I'm presuming based on the name, that value changes at each login.
Although Azure API Management provides identity services of API Consumers, it does not provide full identity management for End Users. We leave that to external partners like Azure AD, Thinktecture Identity Server and Auth0. I'm assuming that your existing system is already using some kind of identity provider to generate the sessionId. What you can do with Azure API Management is validate that sessionId using policies in the API Management Gateway. To do that we would need to know more about the format of the sessionId.
Sorry for the long post but it is a confusing topic and I wanted to be as clear as possible.
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.