I'm trying to migrating existing monolithic application to micro-service applications. But get confused of authentication and authorisation strategy with oauth2.0.
Take ordering service as an example, I want to identify the user who is placing order.
1. The user login and get an access token from a separate authentication service.
2. The user (client) submits a place order request with the access token as Authorization header.
3. The ordering service submits a request to the authentication server to verify the access token and then get the user info.
The questions are:
1. each time the ordering service handles a request, it has to interact with the authentication server, does this increase failure risk? e.g. The ordering service fails to accept orders if the authentication server is down.
2. what is the test strategy for integration / functional tests, should I mock the authentication server and if so, how do I do that?
3.Some articles mentioned JWT token to make the authentication server stateless, does this approach alleviate the case and what is the workflow then?
Related
I need some lights about convenience of using an autheorizarion server in my project scope.
We're realising and deploying our services into customer environment.
Customer infrastructure already provides an authentication mechanism in order to authenticate users.
This mechanism intercepts all comunications and redirects user to a "login" form.
After that, user is redirected to our service and we've to handle and digest it and respond with an JWT token.
Here is where I'm feeling lost:
I'm thinking about:
using spring-oauth2 in order to request a JWT token to an authorization server, or
using spring-oauth2 in order to auto-generate an JWT token and validate it. I don't know if it's possible.
My question is, since user is already authenticated, have it sense to use an oauth2 authorization server, using client-credentials in order to authentication client against our resource services?
Short question would be, could I use spring-oauth2 librearies in order to generate a JWT without an authorization server?
You technically can do it, but I would discourage you from doing that. Access tokens in a system should be issued centrally, by a dedicated service. Otherwise, it will be hard to maintain the infrastructure. If your services will start to issue JWTs, then they will also have to provide the public keys for others to validate these JWTs. Keys management, access token contents management, and any rules of mapping user information into claims - will now become part of your service and it will unnecessarily complicate its implementation.
If the customer's authentication mechanism issues a JWT, why not use that one for request authorization? If that one is insufficient, I would recommend having an Authorization Server (or a dedicated service), that can perform Token Exchange and exchange the original JWT for a new one.
I am working on microservices application where the client application sends the access token to orders microservice with the POST call. When saving the order, the inventory micro-service should be called to update the inventory. The Inventory microservice updateIntentory method should also be protected.
In this use case, should I be propagate the same access token to the inventory microservice and restrict the api access to update inventory or should I make use of client-credentials grant flow to allow saveOrder method in the order microservice to invoke the updateInventory method in the inventory microservice.
Note: Both the order and inventory microservices are acting as resource servers.
What is the right approach.
Good question:
BOUNDARIES
If you were calling an external API belonging to someone else you would definitely use client credentials to get a token that entitles you to call that API.
MICROSERVICES
If the data owner is the same then you should simply forward the access token. This is how OAuth is meant to work: a scalable architecture that only requires simple code:
Client gets an access token with scopes for multiple APIs
Each API validates the JWT
Each API verifies its own scopes
Each API trusts the claims in the JWT and uses them for authorization
The Scope Best Practices article explains this for a real world system.
HIGH PRIVILEGE OPERATIONS
It is common to get a fresh token for high security operations, such as redirecting the user with a payment scope. This should be the exception rather than the rule though.
I'm developing an authentication/authorization system in Node Js for a microservice based application.
I read some articles and documentation about the OAuth2 standard but I need some clarification for my use case.
Basically OAuth2 has some actors like:
Resource owner (user)
Client app (a web application in some OAuth2 grant flows like authorization code, implicit, password)
Authorization server
Resource server (service I want to access to)
So in my database I store a client (web application) with its client_id and client_secret.
Let's suppose that one of my microservice needs to access data from another microservice. Both of them espose a REST Api.
There is no interaction with user, all is done in the background. In this case I would use the client credential flow.
Following OAuth2 rules, both of them are resource servers but in the same time it looks like they are client apps as well.
So should I register them in the client DB table/collection with client id, secret etcetera or did I make some mistakes?
Thank you
If I understood your question correctly, the caller micro-service is your client and the one that is being called is your resource. A lot depends on what type of micro-service communication pattern have you implemented. If you are implementing an "API Gateway" pattern, then your Gateway is always client and all other micro-services can be treated as resources. But if your micro-services can call each other then like you mentioned each one of them have to be registered as client and resource at the same time.
I'm creating an online store REST API that will mainly be used by a mobile app. The plan is for a microservices architecture using the Spring Cloud framework and Spring Cloud OAuth for security.
My question is really on best practices for communication between microservices: Should I have each service register for their own token, or should they just pass the user's token around?
For example, I have 3 services: user-service, account-service, order-service.
I've been able to implement two procedures for creating an order: One passes the user's token around, and in the other each service gets their own token. I use Feign for both approaches.
So for option 1: order-service -> GET account-service/account/current
order-service calls the account-service which returns the account based on a userId in the token. Then the order-service creates an order for the account.
Or for option 2: order-service -> GET account-service/account/user-id/{userId}
order-service gets the userId from the sent token, calls the account-service with it's own token, then creates the order with the retrieved account.
I'm really not sure which option is best to use. One better separates information but then requires two Feign Clients. However the other doesn't require the 2 clients and it becomes easier to block off end certain endpoints to outside clients, however it requires extra endpoints to be created and almost every service to go digging into the Authentication object.
What are all your thoughts? Has anyone implemented their system in one way or another way entirely? Or perhaps I've got the completely wrong idea.
Any help is appreciated.
I have found below 3 options:
If each microservice is verifying the token then we can pass the same token. But the problem is - in between same token can be expired.
If we use client_credentials grant then there we are having two issues: one is, we need to send the username/id in next microservice. Another one is, we need to request two times - first for getting the access token, next for actual call.
If we do the token verification in API gateway only (not in microservices) then from the API gateway we need to send the username in every microservices. And microservices implementation needs to be changed to accept that param/header.
When you do server to server communication, you're not really acting on behalf of a user, but you're acting on behalf of the server itself. For that client credentials are used.
Using curl for exemple :
curl acme:acmesecret#localhost:9999/oauth/token -d grant_type=client_credentials
You should do the same with your http client and you will get the access token. use it to call other services.
You should use client tokens using the client_credentials flow for interservice communication. This flow is exposed by default on the /oauth/token endpoint in spring security oauth.
In addition to this, you could use private apis that are not exposed to the internet and are secured with a role that can only be given to oauth clients. This way, you can expose privileged apis that are maybe less restrictive and have less validation since you control the data passed to it.
In your example, you could expose an public endpoint GET account-service/account/current (no harm in getting information about yourself) and a private api GET account-service/internal/account/user-id/{userId} that could be used exclusively by oauth clients to query any existing user.
I wrote an API in rails which is of micro services architecture.
In my API i need to implement Role authorization to authorize each and every user using their roles.
Is there any gem that fits into micro services architecture or should I write my own logic to authorize users.
i was using gem authorization gem but it does provide much capability that fits into micro services architecture.(rolify)
Is there any other that suits micro services architecture?
Thanks in Advance.
Whenever you have to implement MicroServices in Rails, then I prefer to put your authentication and authorization (role based permissions) using JWT (JSON Web Token). Because in MicroServices, there are multiple different projects which are deployed on different servers and communicating with each other through APIs and you require only one API Gateway, where user provides the login credentials and its should work for all different projects. I wont prefer devise because it creates a session after successful login which is Stateful, while JWT is Stateless.
Statelessness means that every HTTP request happens in complete isolation. When the client makes an HTTP request, it includes all information necessary for the server to fulfill that request. The server never relies on information from previous requests. If that information was important, the client would have sent it again in this request.
In case of JWT, each request comes with a token something like "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NjUwOTYxMzMsInN1YiI6MX0.e9yeOf_Ik8UBE2dKlNpMu2s6AzxvzcGxw2mVj9vUjYI" which will contain all required info in its payload for login. Please refer https://restfulapi.net/statelessness.
The token should also include the role or permissions (e.g. admin role) of user and based on role it should fetch the data and its relatively faster than Stateful requests. Because in case of Stateful requests (as happens in traditional Web Apps), it stores the session_id in cookies and sends the session_id with request. So on server side, first it fetches its user info and check whether its valid user, then fetch its role and then after successful authentication and authorization, it fetches requested data. While in case of JWT, since the role and username comes within token itself which would be decoded on server side, and directly fetches the requested data from DB. JWT (or Statelessness) helps in scaling the APIs to millions of concurrent users by deploying it to multiple servers. Any server can handle any request because there is no session related dependency.
Difference between Stateful and Stateless, please refer https://restfulapi.net/statelessness and https://nordicapis.com/defining-stateful-vs-stateless-web-services.
For more info about the implementation, please refer http://pacuna.io/2016/06/03/rails-and-jwt and https://github.com/nsarno/knock.
The devise gem is the leader in the industry. All of its methods are fully customizable - they can be used as a before_action (typical usage but not ideal for micro services) and can also be used as just another method in your code (inside a block, in a 'if' statement, etc). Checkout the github page here
https://github.com/plataformatec/devise
It has so much functionality, I could teach en entire course on this gem. There's a lot to learn if you aren't familiar yet.
Thanks for the Answers guys,
Coming to the answer,i have implemented my own way of authorization.
I had come up with a design where User -> Roles -> Resources -> Permissions
Here the resources are individual parts where every user has some permissions upon using a resource and role has set of defined set of resources with some permissions like
read_only,read_create,read_update etc
Each user can have any number of roles, thus user having a permission to access a specific resource.And i perform this check for each action using
before_action
Thanks,
Suresh