JWT Authorisation through multiple microservices - jwt

The question in short
What would be the correct way to handle JWT authentication for a user
who is accessing data from microservice A but where microservice A requires data from Microservice B.
The Setup
I am using Auth0 to issue and handle authentication and authorisation.
I have two microservices set up. The user is logged in on the front end and needs to load tenant-based accounting information.
Microservice A is an aggregate service that communicates to multiple different services in order to provide a standardized response for different types of data types.
Microservice B is queried by Microservice A in order to retrieve vehicle information owned by the user.
Which solution would be the correct approach?
Solution A:
The token that was issued to the user when he logged in will be used by MS A to communicate with MS B. MS A is essentially forwarding the token provided by the user.
Solution B:
MS A has its own JWT which has super admin rights to access any resource from MS B. MS A will use this token when accessing resources from MS B and MS A will take responsibility for ensuring that resources not accessible to the user are not returned in the aggregated dataset.

In solution B you put a lot of responsibility on MS A to properly handle the data. In my opinion it's just asking for trouble, eventually someone will manage to call MS A in such a way to get some more data than they can access. So I would go with solution A, or a variant of it. There are a couple ways how tokens can be shared between services - passing the same token, embedding tokens or exchanging tokens. I have written an article about Token Sharing a while back, you can have a look at it.

I think it depends - both options are OK depending on the scenario.
Here are a few things to consider.
Does microservice B do any resource owner authorization e.g. using the sub claim from the users JWT? If so it might be easier to just pass through the user access token. Note: generally I only use data inferred from the JWT for authZ logic. If you need something like the resource owner ID as part of the business logic, you should explicitly include this in the request payload, so that the service can also be consumed by back-end services using M2M tokens.
With Auth0, there's a cost for machine MUAs (monthly unique authentications). This is separate to the cost for user MUAs. For an enterprise account the default is 1000 M2M MUAs. Increasing this number is pretty cheap, but still something to consider. In general you should configure your M2M tokens to have a longer expiration (e.g. 1-2 days) and use token caching. Generally an in-memory cache will suffice, but if you're building serverless apps (e.g. AWS Lambda, Azure Function Apps, etc) you'll probably need a distributed cache. All this is extra work, complexity, and potentially cost (e.g. for distributed cache) for M2M tokens.
There's additional network request (to Auth0) for M2M authentications. This is mitigated through the use of token caching, but something to consider as well.
Is microservice B going to be publicly accessible? If yes, you may have some security considerations as users will be able to call microservice B directly with their access tokens (obtained legitimately), but they might be able to tamper with requests in ways you weren't intending.
The company that I work for use a mix of the 2 approaches you mentioned (which generally depend on the scenario). We have some helper utils for things like token caching etc., which make both approaches easy enough, but if you're going to use M2M tokens you'll probably have a bit of additional work up-front.
One last thing to mention; when implementing 'transitive' services like microservice B, I think it's good to ensure the service is consumable by both user and machine tokens. You're authZ policies might allow for one or the other (or both), but at least you'll have the flexibility to change if/when needed.

Related

RESTful API Design based on the RBAC model

The problem to face lies in the design of a RESTful API that can manage requests from multiple roles in an RBAC-based solution.
Currently we have different resources that can be accessed from different users, which can have one or more roles grouped according to their privileges.
The API we're trying to define must be as clear as possible to the client but without the overhead of adding additional metadata to the URL that could damage and even conflict with the REST practices and definitions. Therefore, we must avoid at all costs include information about the roles inside the URL. The plan is to use JWT tokens that carry in their payloads the info needed to know which permissions has the user making the request.
Having raised our current situation, let's provide an example and state the problem to solve:
Suppose we have * financiers * and * providers * as users with some roles who both want to access ** attentions ** (our resource). Should we add before the resource ** attentions ** information about the * user * whose trying to access the resource?
The endpoints in that case should be defined (as an example) as:
https://example.com/api/v1/financiers/:id/attentions
https://example.com/api/v1/providers/:id/attentions
This way we're attempting to inform the respective controllers that we want the ** attentions ** for that specific role / user which are, in some way, a sub-resource of them.
On the other hand, we could simply implement a much simpler endpoint as follows:
https://example.com/api/v1/attentions
The logic about which attentions return from the database should be now implemented in an unique method that must handle this two roles (and potentially new ones that could come up in the following features). All the information needed must be obtained from the payload from the token, exposing a much more generic API and freeing the web client from the responsibility of which endpoint call depending on the role.
I want to highlight that the attentions are managed in a Microservices Architecture and, hence, the logic to retrieve them is gathered in a single service. The cost of the API Gateway to route the two (and potentially more) of the endpoints from the first solution is a variable not to discard in our specific situation.
Having exposed our current situation:
Which we'll be the best approach to handle this issue?
Is there another alternative not contemplated that could ease the role management and provide a clean API to expose to the client?
In the second solution, is correct to return only the attentions accessible to that specific user based on the roles that it has? Isn't it counterintuitive to access an endpoint and only get some of the resources from that collection (and not all) based on its role?
I hope that someone could clarify the approach we're taking as there are little and none literature that I've found regarding this issue.
There there are multiple solutions for such kind of filtration, and developer have to select one depending on given situation.
As per my experience I can list following.
Structure
When data can't be accessed directly and developer has to use a relation (i.e a table JOIN). In that case URL have to include both the main and sub entities. Before going with this approach a good check is to ask, if the same URL can be used with POST ?
Example
If we have to fetch list of roles assigned to a specific user or want to assign additional roles then we can use
GET users/:uid/roles
POST users/:uid/roles
Security
With Multi-tenant systems where each user can have his/her private resources, i.e other users are prohibited from accessing those resources. Developer should save tenancy information and to filter the resources according to current authentication, without bothering client or requiring any additional info in URL
Example
Phone album of the user
GET photos
POST photos
Search
If it is not security or structure related but client still want to filter the result set depending on his scenario. then developer should use query-string for the filtration.
Example
Client have to fetch messages from his/her inbox or outbox or want messages which are not yet read. or he/she want to search his/her inbox
GET messages?folder=inbox
GET messages?folder=inbox&status=unread
GET messages?search=nasir

Microservices architecture on cloud advice needed

I am building a system based on microservices. It is a web application connected to different rest APIS. Now I want to implement the authorization system, (not authentication), so basically I want to be able to define, which users on the system can perform which actions.
So I am thinking to implement a role/permission system for that.
However, I have a dilemma about the two different architecture options that come to my mind, I and would like to know your thoughts, advices, pros and cons, to move forward with it.
There will be a specific microservice to handle the user permissions and roles, so basically this microservice will have access to two database tables making the association between the user and roles, and roles and permissions. This is the common part to the two solutions I have considered.
Now both options with pros and cons in my opinion:
1) Keeping for each microservice, a cache table with the user permissions specific to that microservice. So, every time a user wants to perform an action on that microservice (let's say, delete an order on the ordering microservice), the microservice will check that table, granting or not access to the user to perform the action.
Pros: every microservice is really a microservice, an independent service that can work totally autonomously of the rest of the system. If the main microservice handling the user permission crashes and it is not available, the rest of microservices will continue to work.
Cons: If I update the user permissions in the microservice that handles this, I need to send a message to all microservices to update their correspondent permissions tables.
2) Creating a API gateway microservice to act as a middleware between the frontend and the rest of microservices and use graphql in it. Frontend will no longer know about the rest of microservices, only will know about this one.
This microservice will intercept all request from the frontend, check with the user-permissions microservice if the user has permission to do the action, and if so, calling the correspondent microservice.
Pros: All the business logic to decide if the user has or not access is in a single microservice, instead of being duplicated across microservices. Also, authentication only needs to be implemented in the middleware microservice, no need to double check if the user is authenticated on the internal microservices as if we got there, is because we were succesfully authenticated previously.
No need to update cache tables in the internal microservices if the user roles or permissions are updated.
Cons: This defeats the definition of microservice architecture. I.e If the middleware microservice crashes, the whole system will be down.
I would like to know your thoughts!!
Thank you!

Resource-Server for IdentityServer 4

My task is to implement a resource server(RS) for IdentityServer4(IS4). The RS should fetch data from a database and send the necessary information as a json object back to the caller (client). This is needed because we have to return complex objects.
I already setup IS4 succesfully and its already running in Docker for testing purpose. I also setup the needed database.
My understanding of the flow would be, the user requests data from the RS sending the access-token, the RS then validates the token, checking if the caller is allowed to access the api using the IS4, if everything is okay the RS returns the data to the caller.
My problem is, as I'm new to this subject, how would I implement a RS? Do I create an API which is added as a scope to the user? Or is there a RS already implemented in IS4?
So yes you'll need to write your own API to serve your own resources, IdentityServer will only manage your identities for you (as well as handling external logins if that's what you need). I'd recommend going to the IdentityServer docs and working through the quick starts in order as shown below:
This will give you a good start but you'll then need to go away and research APIs more generally, there's a tonne of good info online about building (RESTful) APIs. You may find it useful to sign up to something like PluralSight and work through a couple of their courses, they're often very good.
One other thing to bear in mind is that IdentityServer is for identity, in other words Authentication and not specifically for Authorisation so you may need to add something for this. You can of course use a users identity for authorisation purposes but in most cases you'll probably need to augment the info you store about their identity to authorise them for access. See this link for more info around this topic.

How to scope and persist claims to different clients in IdentityServer 3?

I'm new to IdentityServer3 and have multiple MVC clients where users have claims which potentially could conflict and give undesired authorization.
Here is an example with two clients able to send emails and notifications to the users. A user might have access to both applications but should only be able to recieve notifications in Application A. How can we prevent the user from recieving notifications in Application B?
Application A
Claim Type: ApplicationFunctionality Claim Value:
RecieveNotifications
Claim Type: ApplicationFunctionality Claim Value: RecieveEmails
Application B
Claim Type: ApplicationFunctionality Claim Value: RecieveEmails
Would a resonable solution be to implement somekind of logic in a class using the IUserService interface?
Would it be correct to use claims in the way I described above across multiple clients, where we sometimes reuse claims for cross-client functionality. I guess it would require me to namespace the claims (perhaps using the requested scope name the client sends to IdentityServer) in order to distinguish claims for different clients and prevent unauthorized access between the clients.
Here is an example of user claim types/claim values:
Name: John Doe
Email: john.doe#acme.com
PreferedLanguages: English,Swedish,Spanish
ApplicationFunctionality: ClientA.RecieveEmails
ApplicationFunctionality: ClientB.RecieveEmails
ApplicationFunctionality: ClientA.RecieveNotifications
ApplicationFunctionality: ClientB.RecieveNotifications
ApplicationFunctionality: ClientA.ViewBackorders
ApplicationFunctionality: ClientA.DeleteBackorder
ApplicationFunctionality: ClientB.SearchProductInformation
CompanyID: 1145
CompanyID: 6785
CompanyName: Acme Inc
ApplicationLicense: ClientA.PayingNormalUser
ApplicationLicense: ClientB.FreeUser
A user from Company Acme Inc have several CompanyID's which is used when filtering data we request from webservices\databases in the data layer. The user have access to multiple applications where he/she could have different levels of functionality depending on what license they have bought in the applications. Some functionality exist in multiple clients but that doesn't mean the user are authorized to same functionality in all clients he/she have access to.
I would appreciate some guidelines about claims, or perhaps point me to some good resources about the subject. I have read that claims primary is used for identity related information (email, name, department, favorite color, shoe size etc), but if no role\permissions style claims should be used with claims then how should information about what a user is authorized to do in the clients be persisted and how should data be filtered in webservices/databases (resource providers) so the user only sees data he/she are authorized to see?
My first thoughts where that the id_token and access token would be convenient to use since they are issued by the STS (IdentityServer) and then later persisted in cookies. The STS would first be required to perform lookup of user account in Active Directory which contains user identity related information together with an lookup (using the username of the Active Directory user account) in custom database containing information about role\permissions and claims of the user.
How should I persist the roles/permissions and claims of a user if not using cookie persisted tokens provided by IdentityServer?
Clients (applications) and users can have their own set of claims. It looks like you want to have applications which have access to different resources. This is where you should use scopes. Basically define two scopes which define action on that resource (this is one common way of doing it) ie one for 'reading' emails and one for 'writing' emails (eg emails.read and emails.write) subsequently the other scopes can be backorders.read and backorders.delete. It's just good practice to have consistent naming here.
Ok now since weve defined those two scopes, you can now define two clients, one which has only the emails.read scope and the other one has both the read and write scopes. All this means is that one client has access to more resources than the other.
All the user identity claims should stick to the user itself. Application/client specific should never be associated with the user. Name,Email,ApplicationLicense, and PreferredLanguages are all valid claims for the user because they describe the user itself and what can be asserted about them.
For "complex" authorization you may want to look at this sample for some ideas on how to set up compound security policies or authorization.
It sounds like you want to expose a different value to different clients for the same claim. This seems like a logical thing to want to do, especially if you are integrating with clients that are not within your control and thus cannot dictate to them what to expect in each claim, or what scopes to request. A simple example might be the "roles" claim - you may wish to send different values depending on the app that's making the request. If you're joining someone else's enterprise, perhaps with multiple OpenID Connect Providers, you don't always have a choice over the scopes or claim names.
I feel that Nat Sakimura eludes to this in the OpenID Connect FAQ video, https://www.youtube.com/watch?v=Kb56GzQ2pSk (1 minute 40s), the idea that an entity might want to expose a different identity to different clients.
In terms of implementation, we've added a table with [identityId, clientId, attributeName, attributeValue] to allow us to store the same identity attribute for different clients. In our case, these identity attributes become claims in the outgoing JWT. As most attributes about a user are global (i.e. not client specific), we treat the data in this table as overrides to a base set, which saves duplicating the same data for each client unnecessarily. The iUserService.GetProfileDataAsync() method has access to the Client, so can tailor its response depending on the consumer of the data.

REST and HttpSession object

I know that REST is not supposed to use HttpSession.
From the other side, the REST service is running within a servlet container.
From what I saw, the HttpSession object will be created only when:
HttpSession session = request.getSession();
code is executed. Is it always the case? Besides using JSP?
My question is: will be HttpSession objects be created when the REST method is executed or not?
Let's say I use the JAX-RS framework, if it can make any difference.
If such objects are not created, it actually can mean that the size of the server memory may not grow irrespective of how many clients use it the server.
HTTP sessions are actually used quite often with REST interfaces, but should never contain anything truly critical. Thus, they can be used to contain the fact that you've authenticated or what your preferred default ordering of some list is; in the former case, you could also support other authentication mechanisms at the same time allowing fully stateless operation, and in the latter you can easily also support explicit overrides. So long as you don't require a session — well, under the assumption that your site was using HTTP BASIC auth for the sake of argument; if you're using OAuth then you need sessions enabled to stop performance from being crippled — then you're still potentially reasonably close to RESTful (in this area for sure; REST is not “don't use sessions” after all).
Is there a concern about how long a session lasts before timing out? Well, maybe but not really. A session is really an object that you've mapped into some database table, and you can configure the expiry policy on them so that they last long enough to support effective use without being over-burdensome. Which depends on how many clients use the site at once, what their usage patterns are, and what hardware resources you've got available (of course).
I think this is the limitation of Java EE framework at the moment I haven't seen it done otherwise any other server yet. If you need to have a container managed security-constraint a session will be created.
That being said you do not require to implement your code to use container managed authentication. People do implement authentication login/mechanisms themselves like Shiro and what not.
If you're concerned about scalibility, you may have to handle the authentication on your own. However, before you continue with this path consider the following... how many people are you expecting to use your app? Unless you're some really big and popular service like Facebook or Google etc, present hardware/cloud offerings should be able to handle your load with HTTP Sessions with a lot of room to spare.
However, if you wanted to do it an implement yourself then I suggest the following:
unauthenticated client passes credentials (via WWW-Authorization is the easiest to test with)
credentials are validated and a token is returned. The token is an encoded encrypted string containing client ID, an expiration and a reauth token. This token is passed back to the client with Set-Cookie
Client makes future requests with the Cookie containing the token
The token can be used as long as it hasn't expired, this would just be crypto calculations on a server node and thus can be scaled across multiple servers if needed there's no single data store to deal with.
The reauth token can be used to generate a new token for the client should it expire (this is useful for user applications where the interaction can last for minutes).
You can add an enterprise cache to store which ones are still valid at the expense of an extra backend call.