I decided to try for the first time to implement a microservice architecture instead of a monolithic one and ran into an authorization problem.
In a monolithic architecture, I simply passed the token in the header when accessing the controller on which the [Authorize] attribute was hanging and checked it against the current single database. But in the microservice architecture, each microservice has its own database, how you can check the token when accessing other microservices, I have heard about the implementation of the check in API Gateway, but I think that, anyway, each microservice should have its own check, since, there should be no access to the api if the user is not authorized.
Should I use api gateway to make a request to the authorization microservice for verification?
How can I implement this?
I have a separate microservice for user authorization (registration, login, issue of tokens) which has a database of users with tokens.
That is, I need to make a request to this microservice using API Gateway?
One way -
You should try to do authentication/authorization at API Gateway level. Whenever any API call come to API Gateway that needs some permission then check the token. If the access/token is not present then return 401. On frontend, if you get 401 then do authentication at UI.
2nd Way -
UI pass token to API Gateway that will further send the token to other microservices.
It depends on, how grain level of permission do you need. If it is at very grain level, then go with 2nd else go with 1st.
Related
I have a very basic question as I was watching few tutorials related to Microservices. If I am creating multiple microservices for 1 application, should I need to implement Authentication and Authorization for all microservices? For example If I have an e-commerce website and I have multiple microservices with certain endpoints for the purchase model.
As a user when I login to the UI, initially calling in AccountManagement microservice ( which has few functionality such Register/Login/Reset/Revoke) and then move from one feature to another which interim calls another microservice (should the next microservice read the cookie information and authenticate automatically ? Is that how it works?
Will my other microservices also have all features of the Account management microservice or only authenticating through Refresh token?
I am fairly new to this concept in microservices and trying to grasp as much as I can through tutorials but these questions are something I still struggle to understand properly.
Answer 1.
Token Based Authentication
It is always ok for you to build stateful application for monolith but not for stateless microservices. Session-based authentication works well for Monolith. However, for microservices since you need to route requests to multiple independent services. To maintain statelessness in our system, we opted to use token authentication. We packaged user claims in the jwt. Hence, we need Authentication for Microservice.
You can apply SSO based approach.
When a user logs in for the first time from any frontend app, a cookie called jwt-token gets created on the api-gateway. The cookie’s domain is .myorg.com and hence accessible to all myorg.com subdomain. When a request is made from any of the frontend apps to the api gateway, we extract the cookie named jwt-token if set. If not set, we assume the user is not logged in and return a 401-status code from the api-gateway.
If your microservices are not exposed to internet, you can also introduce basic authentication. This will also make sure reducing any security risks internal to your company.
Answer 2.
Microservice follow DDD (Domain Drive Design) Principle which makes them independent small application. You should not add any functionality of Account management (it is an independent Service). Other Service should have their authentication along with their domain which can be like Customer, Payment, Audit etc.
Refer These articles :
https://medium.com/technology-learning/how-we-solved-authentication-and-authorization-in-our-microservice-architecture-994539d1b6e6
https://medium.com/walmartglobaltech/building-domain-driven-microservices-af688aa1b1b8
There are 2 WebApi Projects on different servers. One of these servers (WebApi-A) has OAuth2 authentication workflow setup with Authorization Server and all.
The another WebApi project (WebApi-B) has an end point that I would like to Authenticate through [Authorize] attribute. I don't want have a new authorization server but to utilize (WebApi-A's) authentication process just to validate the token.
From what I understand if the machine-key is same across these server. We can essentially replicate the authentication process from WebApi-A in WebApi-B without having to call WebApi-A at all.
How do I achieve this?
You could, in theory, pass through the JWT token and if your OAuth setup uses the same client secret and data store it should just work. You would have to ensure that you add the JTW token when requesting and to use some distributed cache to verify.
I would rather ask whether or not you should rather create a gateway that can handle and authenticate the requests and delegate them to the separate APIs? This feels like an identity server (http://docs.identityserver.io/en/latest/topics/apis.html) would solve your problem. Anything you do other than moving the authentication from web api A would just be a stopgap.
Duplicating the setup could work but that will mean that you have to now maintain it in two places. So I agree that doing that is less than ideal.
This is a great article that may aid you:
https://www.scottbrady91.com/OAuth/Delegation-Patterns-for-OAuth-20
This will have a lengthy answer so I will just leave you this diagram showing multiple Resource Server, Client, and a separate Authorization Server
Taken from this article Single sign-on across multiple applications (part II) which I hope could get you started.
you can use your token when login in web api and then you add the token to the header "Authorization" with bearer "your token"
To give some background, bear with me,
We have an existing external OAuth service that is used for shared authentication across all of our apps. It has a login form that is used for user auth and provides JWTs for its APIs, which are called in the app I'm currently working on.
The app I'm working is using .NET Core 2.0 with a React front end. The server side is basically responsible managing the token for the external APIs, and providing 'proxy' APIs for the React client to call, which then in turn call the external APIs. Essentially the architecture is like any other standard Web API/MVC app, but instead of grabbing data from a database directly, it's just calling some other external APIs.
In the context for the .NET Core app, it is using JWT authentication for it's APIs. Once the user has authenticated with that external service, they will have a JWT for the external APIs (stored in session) and another JWT for the internal 'proxy' APIs (passed to the client in a cookie). So the client makes a call ("api/users"), that gets routed to my controller, authorized using JWT, that controller makes a call to some UserService, which uses the JWT stored in the session to make a call to the external API.
React client makes API call with token --> .NET Core API grabs JWT stored in session --> uses JWT to make call to external API
This all works fine, but now I'm running into some issues with refreshing the client JWT. I'm currently passing just the an access token to the client in a cookie, but I need to also pass a refresh token to the client so that it can grab a new access token when the expiration time has passed, which I'm not currently doing. I also need to somehow pass the expiration time of the token as well. Does it make sense to serialize all of this into a JSON object and pass that in a cookie? What would be a good way to get all of this to the client? I'm essentially trying to get to a point where the client will check, "Has my token expired yet?", if yes, use the refresh token to get a new one, if not, continue with the API call.
Sorry if all of this information is an overkill to a simple question, just trying to give some context.
If you are using Identity Server, you can check the refresh tokens here
I have a big system. This system consist of client desktop app and many wcf services. Each of wcf service have it's own logic and isolate it from client code. One of the services is authorization service. It's main task is to authenticate user and let all other services to know what user is logged on without additional stuff. For example, as i think i should at the start of client to make authentification of the user, check it's login and password and next generate some token and use this token in all requests to other services to let any service know what user is working with it. Well, firstly, i wanted to use claims authentification, but it is quite complicated for realization. Now an idea of my algorithm is to generete some kind of token, put it into the header of any request and pass to services. Service will send this token to the authorization service and service will check it.
The question is: is there any more beautiful and more easy for realization algorithm to let any service know which user is now working with him? Or maybe wcf have some standard solution for this problem?
Update 1. I can't use active directory and any windows default authorization mechanism. I have my own database of users, their roles and permissions. I need just to let other services to know the name of the user. I need to write this mechanism once and let other developers to use it in any wcf service of our system. Is it a bad idea to send a login in every request?
I'm posting this in the hope of receiving some feedback/advice and information on something I've been struggling with the last few days. To start I'll give a quick breakdown of the project.
There are 2 applications in the solution:
WebAPI resource & authorization server - Uses OWIN (hosted in IIS) and ASP.NET Identity to issue an authentication token on a correct login and then allow requests to the various controllers.
MVC client application - Has no authorization as of yet (until I figure it out) but will make calls to the WebAPI resource server to get all data. These calls will only ever be made from actions of the controllers in the client app, no client side AJAX calls.
The client application doesn't have it's own datasource. All information is stored in a database which the WebAPI service has access to, so essentially if they provide the correct credentials and the client app receives a bearer token I need to deliver a way for the application to see them as authorized.
What's the best way to handle this?
Is it possible to configure OWIN on the client side to use the OAuth
settings of the server? Am I barking up the wrong tree and will I need to just use HTTPClients?
Could I deserialize the bearer token and store it in session, and
then write my own authorization providers to check these on the client side?
My initial concerns are I'm abusing Bearer Tokens and trying to cobble them into a solution which isn't ideal. All examples of external authorization I've found so far usually involve making calls to providers hosted by Google/Facebook/Twitter to check the user is who they say they are, and then moves on to creating a user record in their system. My application can't do this.
In regards to security I was planning to introduce filters which would validate the request has came from the client application by providing an identifier and secret, along with IP validation.
I realize this may be a bit open ended, but I'd appreciate any advice. The scope of the project is that the web service is the only thing to have access to the database. The MVC client application will be hosted on a different server, and the service will only accept requests from said client application.
You don't need to access the data source in your MVC app to validate the bearer token. Basically, you can do it in the following way,
MVC app requests access_token from webapi and passes it to the UI client (let's say a browser).
Browser stores the access_token in a cookie/localstorage and sends them to the MVC app for all subsequent requests.
Create an ActionFilter in the MVC app to validate if the request from the browser has the token supplied in the header. If not, reject the request.
MVC app passes the access_token in the Authorization header to the webapi.
Use HTTPS for all communications (between MVC app <-> Client and MVC app <-> WebAPI)
You can further obfuscate or encrypt the access_token you get from the WebAPI on the MVC app side for additional security but then you will have to send the decrypted version back to the WebAPI.
I realize that my answer is a bit late, but maybe it helps other people:
The bearer token that you get from the API has a list of claims encrypted that only the API can decrypt. I assume you need to have these claims on the MVC application as well so you can restrict resources on the client.
So, what I have done was to first get token. After you get it, you make another request to the API resource api/me/claims to get the list of readable claims on the client. Based on this list you can allow access to resources in your MVC CLient Application using a custom claims based Authorize attribute. Also, you can store the claims in a cookie in the client session. Below is the code for the API controller to get the Claims.
[RoutePrefix("api/me/claims")]
public class ClaimsController : BaseApiController
{
[Authorize]
[Route("")]
public IHttpActionResult GetClaims()
{
var identity = User.Identity as ClaimsIdentity;
var claims = from c in identity.Claims
select new
{
subject = c.Subject.Name,
type = c.Type,
value = c.Value
};
return Ok(claims);
}
}
The idea is to reconstruct the ClaimsIdentity object of the logged User on the Client side and maybe add it to the session.
The token is not enough. You might risk getting a Not Authorized response from the API on a resource that you have made visible for the user in the MVC Client Application. Needles to say that is recommended to use HTTPS for all requests.