RESTful API Design based on the RBAC model - rest

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

Related

Handling User Preferences/States in REST API

We're starting to migrate our Website to a REST Service based system and are in the process of developing the core right now.
In our current setup a user has one or more "accounts" assigned which define what data he can see on the website. Only one account can be active for a given user at any time. Right now we store the selected account in the database and use it to filter all queries.
Now I'm not sure how to handle this properly in a REST environment. Possible solutions I found are:
Sending the requested account with every request
Storing the current account in the auth token. (We're using JWT for that)
Having the current account stored on the server and calling a specific resource to change it
Each of these has its pros and cons for our setup. Currently we're using the 3rd approach in our Website. But what would be the correct way to handle such a thing in a REST environment?
Yea the design you are dealing with is fairly bad, and what you really want to do is remove the state completely out of this system.
For that reason the first option is by far superior:
Sending the requested account with every request
If this is simply an id, there's a very simple way to do this, just prefix all your (relevant) routes / uris with this account id. For example:
http://api.example.org/accounts/{id}/...
This way the 'state' is maintained by virtue of which url you are accessing, and the server can be unaware of the state.

What is the best practice to get related/nested data from REST API?

For example: We have a User model, which in turn has several Company entities. I see 2 solutions:
1) Classical. Make an API like:
/users/
/users/3/
/users/3/companies/
and issue /users or companies request separately. However, if we need to have both user and his/her companies information in one view (on Angular2) - we need to send 2 requests to the server.
2) Put the related/nested data inside the level-1 object model. In request:
/users/3/
the server will provide information about the User, together with his Companies. In this case we get all information for 1 request. But again, the company has an unlimited number of Storage entities. What if they are required in one separate view?
I'm more inclined to the first option, but I'm confused by the description of the REST style: "The view must fully represent the resource." Satisfaction of this requirement can lead to a partition of the resource into child resources and, accordingly, to smaller representations. "
Please, help with advice, I doubt in connection with the lack of experience what decision will be correct in this case. Oh yes, I forgot, Backend on Django (Python) using Django-Rest-Framework - All this is a SaaS for ~ 1000 users.
Approach 1 is an an ideal approach for REST. But when it comes to designing APIs for the displaying information on the UI it involves much more than just partitioning the APIs as per resources.
So I would suggest including the Company information in the User API. But as you suggested Company object can have very large list of Storage objects, in this case I would recommend including only the necessary and sufficient fields of Company model into User API. So that you will be able to render one view. And then later when user expands the Company section then you can pull the left-over fields from /company/<id> API.
This way you will have lesser API calls for the hits where user doesn't look for Company details and your API will be light weight as well.

Access control based on data filtering instead of request authorization

Standard way to control access in a multi user service is to provide as many service methods as necessary, where each service method has concrete results and access permissions.
For example,
Moderator is authorized to call GetModerationAwaitingPosts service method to access posts from any visitor awaiting for moderation
Visitor is authorized to call GetOwnedPosts service method to access only his own posts including draft and moderation awaiting posts
Visitor is authorized to call GetModeratedPosts service method to access only moderated posts from all visitors
But there may be another approach - single service method GetPosts to request posts that the requester is allowed to see.
Any logged in user is authorized to call this method.
Posts are first filtered according to the role of the caller.
Then posts are filtered according to parameters passed in GetPosts method or filtered on client side.
This approach is used, for example, in WCF Data Services through Query Interceptors.
How is approach to filter data based on user inside service method named and treated in different architectures and methodologies, like SOA, REST, CQRS? Is it a solid solution?
Are there any books / articles where difference between these approaches is considered in details?
As for me, I find it really strange and unusual when results of a request depend on the requester.
Yes, there is an access control paradigm called attribute based access control (ABAC, abac) which implements data-based, context-based authorization that uses information about the user (role, department, age, location...) about the resource (owner, classification, type...) action (view, edit, delete), and context (time, IP address...)
ABAC will let you implement policies e.g.:
Medical use cases
doctors can view the medical records of patients they are assigned to
nurses can edit the medical journal of a patient in the same deparment
Finance use cases
A teller can view the accounts of those customers in their branch
A teller can approve a transfer up to their approval limit
ABAC provides an architecture as depicted below.
In the architecture you have the notion of a PEP or policy enforcement point which you can use to secure anything from GUIs, APIs, web services, micro-services, ESBs, and databases.
The PEP calls out to the PDP or policy decision point which is at the core of the architecture. The PDP uses a set of policies to determine whether access should be granted or denied. It can also use external sources of attributes, PIP or policy information points, to help in determining whether access should indeed be granted.
There is one language which implements ABAC today. This language is called XACML (xacml). XACML gives you:
the architecture
a policy language
a request / response scheme
With XACML you can create JSON authorization requests, send them off to the PDP and get a JSON response back. It's an extremely lightweight way of getting a response back.
This means you can either
grant or deny access to a given record, or
filter those records a user can get access to as stated in your requirement

REST API DESIGN - How to overcome the impedance mismatch between a front end client's needs and REST principles?

Given the following scenario:
a RESTful API
that RESTful API has permissions/authorizations that can be granted to entire entity collections, and/or to particular entities, i.e. complex role based permission rules.
The API is (according to RESTful principles) HATEOS-driven (resource url's are revealed through the API. Once you login and get back the "user" resource, you are able to drive the entire API through links given in responses.
A front-end client (web app) that needs to use this API
Imagine now the front-end wants to build a menu. That menu is based on access to particular entities and/or entity collections. For example an "Administration" menu will be shown if the user has access to one of a number of different entities and/or collections.
How do I build the menu? I need to know the permissions the user has in order to build the menu propertly. I don't know all the permissions the user has because it would require walking the url's of the REST API to see all the objects the user has permissions on.
This seems like a tough thing to overcome, but maybe I am missing some obvious technique. How can this impedance mismatch overcome?
Your REST API can expose a resource (or it can be a part of the user resource returned after a user has been successfully signed in) which will contain information what resources the user can access and therefore what menu items should be available for this user.

RESTFul API endpoint design with filtering and authorization

I am designing a REST API with consumers that have different permissions. I understand that a representation of a resource should not change according to user. Therefore I am trying to determine which is the best approach:
GET - list collection of all documents - admin only.:
/api/documents
GET - list collection of all documents - any user with access to document 123
/api/documents/123
For normal users therefore should the endpoints be
list all documents for user 12
/api/user/12/documents
document 123 assuming user 12 has access
/api/documents/123
OR... should the end points be as below and a query string filter used:
/api/documents?user=12
/api/documents/123
In this case you can get away with just two endpoints (and one header!). Make sure the API for /documents is returning the Vary: Authorization header. Then you can use
GET /api/documents // return all docs the logged-in user can see
GET /api/documents?userId=bob // return all of bob's docs that the logged-in user can see
GET /api/documents/123 // return doc 123 if the logged-in user can see it
It is not entirely unreasonable to nest the user a la GET /api/users/bob/documents. I find it to be harder for end users to learn APIs with a large number of endpoints, and I feel that the nested approach tends to create many endpoints. It's conceptually easier to go to /documents and see what you can filter on, rather than look at each endpoint and see what filters it has.
I would keep business logic and authorization logic entirely separate. If you want to retrieve document XYZ, you wouldn't pass the user id as an HTTP parameter.
You suggested /api/documents?user=12 but in fact it should just be /api/documents. The user information should come from the authentication layer.
Similarly authorization should be entirely separate. The reasons for that are:
separation of concern
ability to update authorization logic independently of of business logic
avoid impact on API design
The API should only reflect those business objects you care about e.g. documents in this case (possibly also users should you wish to display a user profile...).
To handle authentication, use the container's standard techniques (e.g. HTTP Basic authentication) or use advanced authentication techniques (OAuth..) via a dedicated framework.
To handle authorization, use a filter, an interceptor. In the Java world (where JAX-RS implements REST), have a look at the Jersey interceptors and filters. You then want the interceptor (or policy enforcement point - PEP) to query an external authorization service (or policy decision point).
Have a further look at ABAC, the attribute-based access control model, and XACML, the eXtensible Access Control Markup Language which explain how to control access to your REST APIs without mixing business logic and authorization logic.