I'm designing two micro services one for Teacher and other for Student. Now my question is what is the best approach of storing users and doing Authentication Authorization :-
Centralized Auth server which will store user roles as well as all the info.
Centralized Auth server which will only store roles but the user info will be Stored in the databases of their respective services (Student, Teacher)
No centralized Auth server but redirecting login request to either Student or Teacher as per the role in the request body and it will be the responsibility of Gateway.
I want to know the pros and cons of these approaches. If there is any better approach then please share the same.
P.S :- Multiple roles can be assigned to a single user.
I would go for the first approach. Rather than "centralized Auth" server it would be more of a "auth micro service".
Now the important part is how to handle authentication itself. In general you could either use a session or JWT.
For micro services I think JWT is a perfect fit. If you use session you basically "centralize" your authentication and authorization. What I mean by this is that after a user is authenticated, every time the user makes a request all the micro services that react to this response must check on the centralized session. This will not only increase latency but it just doest fit with the distributed system. The point of using micro services is to have make replicas of services and so scale horizontally.
If you use JWT, the micro services only need the secret key to validate the token. Basically no centralized store(session) for authentication infos.
About the "auth service", I would suggest you to store authentication and authorization related data only(including user info related to authentication. phone number, email, name etc. you probably would use this in case user needs to change password, forgot password etc.). Other specific data related to a specific role can be stored in the corresponding service.
Related
I'm designing a system with REST API. REST API will be implemented using Spring Boot. The system should manage employee, product, orders information. It can be used as a standalone or as a part of some existing product ecosystem. I'm looking for some resource (book, blog, online course, etc.) to help me decide how to implement authentication and authorisation.
It's quite obvious how to do it if the system is used as a standalone product. User credentials/authorisation data can be stored in the same database next to product/employee and other data.
I'm not sure how to handle everything when the application is a part of some existing ecosystem. What if:
Someone wants to reuse existing User data store for authentication or third party service like Okta or Auth0.
Use existing data to build authorisation rules. For example authorise a person to modify product data if the person belongs to some User group.
I'm thinking about Oauth2+OIDC solution. For example Okta allows add a Claim based on Expression. User groups can be provided as Claims too. It seems Okta could be a source of both Authentication and Authorisation information. I'm not sure if it's a correct way to use Oauth2 and OIDC? What are potential pitfalls storing the authorisation data this way?
I've checked Keycloak and it seems authorisation data. can be stored there. So it's not an unusual practice to manage such a data in an authorisation server.
Maybe I should use Oauth2/OIDC for authentication only? Authorisation data (assigned roles, groups, etc.) can be stored in my application database. The application should provide means to manage the information.
I'd like to get some advice or source of information for this topic.
Thank you.
I would aim to keep OAuth data fairly small - the Authorization Server (AS) typically only needs a few fields to manage login such as Name / Email and a generated user id.
When data becomes domain specific it can become a burden to manage it in the AS, whereas in your product data it is easier to spin up custom UIs etc.
Instead the AS can reach out during token issuing to an API to include important claims in access tokens - such as roles etc. Meanwhile you don't want to expose detailed access tokens to internet clients.
The Curity web site has some good resources on patterns to meet the above requirements - here are a couple of links:
IAM Primer
Claims Best Practices
I've done a fair amount of research on the many different ways to authenticate and authorize users who use my frontend application to access my REST API. I've built a system that uses OAuth2 and JWT and need a sanity check since I'm working on this alone.
For a bit of background, my frontend is built using Vue.js and my API is built using Django with Django Rest Framework. My team is already planning on concurrently developing the mobile and desktop versions of this app which both would require authentication and authorization as well.
To keep things brief, I'll omit the alternative solutions I have and just talk about the most controversial one.
Right now, OAuth2 (my authorization server) grants users a JWT token using ROPC when they provide their email and password to my frontend client. I should note that my API (my resource server) and authorization server live on the same machine.
My application allows users to essentially signup using different plans (for example a free plan and a paid plan). When a user signs up for a free plan, I need the frontend application to not only disable certain features and elements in the UI, but also I need the authorization server and or resource server to limit what that user is allowed to query based on their plan.
The idea is when a user signs up or logs in, my authorization server will get the associated user record from the database and create a valid JWT with a claim attached that states the user's plan and maybe some other non-personal information. Then once signed it sends it off to the user where the frontend can enable/disable parts of the UI... etc. Hence, if a user logs in on mobile, we can customize the UI based on the same claim sent by the JWT.
My issue is that I don't know if this is a good way to go about it. It seems that everyone I've asked in my circle is split on using JWT or not. Those apposed mostly raise security issues, but, when from what I understand, many of the JWT security pitfalls are well documented and can be avoided just using some commonsense as with any other session/token-based authentication. I'm starting to get analysis paralysis. Please help.
CLASSIFICATION
I would say this is really an API Authorization question, as opposed to an OAuth question:
The role of the Authorization Server and tokens is really just to prove the user's identity
Product specific logic comes after the user logs in and is generally best handled in your app
MY PREFERENCES
Here is how I would handle it:
Save the plan type to your product data when the user signs up
After login, look up the user from the access token
Then look up the user's plan type from your product data
Produce a Claims / Principal object in your API containing both
Enforce business rules based on the plan type claim
I would aim for a Claims object something like this:
class ApiClaims {
// The user id in the access token
userId: string;
// The email
email: string;
// The plan type
planType: string;
// Other claims from the token
// Other claims from product data, eg user roles
}
RESOURCES
If interested in this approach, these blog posts of mine may be of interest:
User Data Management
API Authorization
JWT?
You need some kind of API credential that is sent in HTTPS messages and is web and mobile friendly, so I would use JWTs. You could follow the same pattern with any API credential though.
It depends on what you are trying to protect of course, but JWT bearer tokens are an industry standard. Since you control both the client and the authorization server, you can implement it however you like.
I would look into changing Resource Owner Password Credentials flow to authorization code flow. It will enable you to use social authentication providers like Google or Facebook to sign in users (while still maintaining plan info in your own service). Chances are that people trust those companies more to keep their credentials safe than your company, and it allows you to benefit from any authentication features (MFA) those companies implement.
Also, if you want the clients to read the contents of the token, you should use OpenID Connect id_tokens, as those are guarenteed to be in JWT format.
I am coming today because I would like to make sure I have the right approach in terms of microservice architecture for a login/register/authentication approach.
I first thought I would have 2 services:
API
Users Service
I would have the authentication process shared between my API and my Users Service. I would, by example, login from my API by trying to find the combination username/password in the users service, then on success, generating a token and returning it to the user. API would then handle the authentication token (in Redis or others)
However, moving forward into microservices and loosely coupling approach, I saw that some people actually split the Authentication data from the user data (such as age, first name, phone number, etc...). So I now have the following approach:
API (send the data to the authentication service. On success, it request addUser/getuserbyid of users service and then return the data)
Authentication Service (hold users account information)
Users Service (hold users information)
What's then the best approach? Because on fail, I don't know how can I manage.
Let's take the case where We can authenticate but the users service crashed because of another process. The user has a created account but no user profile. For that case, it makes everything harder..
Thanks for any interesting point of view :)
I am trying to build a pure JavaScript rest-client application that must support anonymous retrieval of information from a REST server that already supports JWT for authentication/authorization for external applications. The server is already being used by other client applications supporting multi-tenancy. Actually embedding the tenant information in the JWT.
Besides that the application needs to support users(human beings) that will want to mark(or select) some resources as favorites so a mechanism is needed for users/role creation and further authentication/authorization for the users. But these users can't be isolated to a single tenant, they will want to use across tenant resources.
So, right now I found that I need to use a JWT value for the anonymous data retrieval that of course should be tenant-agnostic. This means that I have to create an user with a special role that just have permissions for read only resources, except for the permissions for user creation (when the clients do sign up) again this should be tenant-agnostic. And when the user log-in into the system the JWT should be replaced for the one that have the user credentials again tenant agnostic. I am not sure if this is entirely correct, so how should we handle a situation like this ?
My other concern is, that we have the same back-end supporting authentication and credentials storage for human clients (tenant-agnostic) and application clients (tenant-aware), so there is logic that is a little bit more complicated in order to handle the privileges and tenant restrictions here. This could be just my impression but I feel that there should be a separation between application users and human users in the logic and/or data store.
But I am not completely sure and I want to know if some of you have previous experience or could have some ideas about this topic ?
Can you try the following approach, Create the users, assign the users with a read-only role for the tenants to which they need access to.
The data would be like
User1 - tenant1 - administrative role
User1 - tenant2 - data reader role
User1 - tenant 3 - user role
In the jwt, we ensure that the user is authorized. Then we get the list of accessible tenants and see if he has access to the requested tenant data w.r.to the above data and then complete the authorization.
HTH
So let's take the basic e-commerce microservices.
Identity and access . This microservice will take care of user accounts, roles
and authentication. The authentication method will be the based on the usual
token based flow (user enters username + pass and server returns a unique and
random token via cookie). This service can also be used to get the user profile.
Cart microservice. This microservice can be used to put products in a cart.
Check what products a cart has. Etc ...
Asuming that "Identity and access" microservice will be used for generating the random token as a result of a succesful authentication, and for linking this token to a user, how will this token be used to make the user's identity available to the cart microservice? For example, when a user will add a product to his cart, he will send along the authorization token and the cart microservice will have to identify the user based on that token.
Could a distributed database be an option? A database which has these tokens stored and links to user built, and to which all microservices have access?
Or should all microservices get the user's identity from a special identity and access API which will expose users based on the access token?
A distributed data base definitely conflicts with the following basic principle of micro services:
A micro service owns its data and exposes it via well defined interfaces.
No other micro service may access data owned by another micro service directly.
So one solution in this case would be to have a token micro services or the last solution you have described.