REST Authorization - rest

We have Rest calls like http://api.ourdomain.com/dashboard/resource-id Method: GET; where resource-id is the id of a resource which is tied to a logged-in user. We don't want any user be able to access other user's resources.
Thus, to determine if the resource is tied to the current logged-in user, we have to execute some queries(Joins) to know that this resource with resource-id is of logged-in user. Well, this is one of many cases we have. We certainly can't make a generalized AOP kind of method which will decide if requested resource is authorized to see by logged-in user, because the logic to decide that, is different for different resources. Other solution could be: to have "createdBy" column in every "resource" DB table so that the logic for deciding would be pretty simple i.e. just check if current logged-in user == resource record's createdBy column. But the latter seems a bit quirky one. Any suggestion, how we can design solution for this?

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

REST API Resource Naming Conventions - User or Users (pluralisation)

Long Version
For some, myself included, one of the most painful and headache causing parts of building a REST API is determining the name for each resource and the accompanying endpoints.
Whilst it is, of course, down to personal preference; there are certain things that are encouraged by the community. For example, most people, including me, will pluralise their resource names:
GET /notifications
POST /posts
However, there are cases where pluralising just doesn't seem correct. Consider the following example where user essentially represents the logged in user, not the entire users resource:
Endpoints only relevant to the authenticated user
// Phone Verification
POST /user/phone/request
POST /user/phone/resend
POST /user/phone/verify
// User creation based on authenticated and verified phone
POST /user
// Update authenticated user's profile
PUT /user
// Delete the authenticated user
DELETE /user
// Add/remove the authenticated user's profile image
POST /user/image
DELETE /user/image
// Update the authenticated user's device token
PUT /device/token
Endpoints that access the entire users resource
GET /user
GET /user/{id|self}
In the above example, to me, it feels like the singular user resource name is more suited given on the majority of the endpoints, user refers to the authenticated user, not the entire database of users. But, on the other hand, having GET /user return all users just seems plain wrong...
As a result, I am now torn between user and users - both have strong arguments either way as I see it but would very much welcome another person's opinion on the matter...
Short Version
TLDR - To put it simply, consider the following two endpoints:
// Get all users
GET /users
// Update the authenticated user's device token
PUT /user/device
Both of the above seem correct in my eyes. The problem with the above is that there is no way I am going to have both user and users, it has to be one or the other in my opinion.
The dilemma; Why would I use user when the resource refers to the entire users database? Why would I use users when the resource only refers to the authenticated user?
I cannot get my head around this one... Anyone got any thoughts on this? Or, even better, an alternative solution to my proposed endpoint structure?
Update
After some deep thinking, I have come up with an alternative solution to this but I am still not 100% sure on it as I am not overly keen on using the auth resource name.
Consider this:
// auth = authenticated user
// users = users collection
POST /auth/request
POST /auth/resend
POST /auth/verify
POST /auth
PUT /auth
DELETE /auth
POST /auth/image
DELETE /auth/image
PUT /auth/device/token
GET /users
GET /users/{id}
There are obviously different opinions on this matter, the answer below contains my personal views.
The bottom line is that it's all quite subjective and depends on the way one looks at a certain (type of) resource.
Why would I use user when the resource refers to the entire users
database?
In my opinion, you should never use singular for an endpoint that contains multiple resources.
Some people, however, argue that we should stick to singulars for all resources, mostly for the sake of simplicity and uniformity.
Why would I use users when the resource only refers to the
authenticated user?
You will find quite some different opinions on this, but the consensus and most widely adopted is generally to stick with plurals, except for resources that can only contain a single item (for example, a user profile only containing only one avatar).
Also, since using a singular form for the users resource wouldn't make sense following the above logic, we don't want to mix singular and plural names.
// Update the authenticated user's device token
PUT /user/device
You can interpret 'updating the authenticated user's device token' as follows:
Add a device token to a user entity of the users resource collection.
If your API supports view devices' data of other users, the API can be like /users/$user_id/devices
whereas, when you always have to get the current logged-in user's devices information, the API can simply be /devices (as current user is implied).
i.e IMO, wherever you have only 1 parent resource accessible (say in this case current user is always singular), you can skip that resource in the API URL.

REST Endpoints for Current User vs ID

As far as REST APIs go, which is the better structure to follow in general?
Assume GET/PUT/POST/DELETE for all resources.
1) Use currently signed in user for /users/**/* routes.
/users
/users/password
/users/email
/users/preferences
/users/documents
/documents/:id
2) Having absolute paths with IDs and using /users/:id for currently signed in user?
/users
/users/:id/password
/users/:id/email
/users/:id/preferences
/preferences/:id
Does it matter?
If the resource you are referring can be multiple, you should go with
/resource/resource_id
In the above case, user can only be the current person, so using a pattern like /users/user_id, sounds odd. Because, you will have to handle different cases like What if a logged in USER A triggers an api call with a different user-id USER B??
You can have a namespace like /profile for managing the email, name, image etc. You don't have to make it as /users/profile as it is implicit that the data is going to be manipulated / accessed for the current logged in user.
Both are fine. What's nice about creating unique endpoints for every user, is that one day you can allow user X to access information about user Y.
The pattern I followed in a recent API was to create a unique endpoint for every user, but 1 endpoint /current-user that redirects to the /user/:some-id.
A url might indicate an identity. It makes a lot of sense that other resources might refer to user as a 'creator' or 'modifier' of sommething, and in those places you might want to use a url (and not just a userId).

RESTful endpoints with different permissions

I'm creating an API where based on the permissions that authenticated user different properties of objects can be changed.
Whats the common way to approach this problem?
Should i have endpoints like
/admin/users and /users with different API definition and capabilities?
It sounds rather inflexible design, what about situation where user can have permission like can_modify_foo_prop and can_modify_bar_prop?
I was thinking a better solution would be instead to just provide one endpoint /users and based on authenticated user roles some fields would be read-only/hidden instead? That seems more flexible but could be more annoying to document/implement.
Remember, URI means Uniform Resource Identifier. Which means a given user (concept) should be always identified by the same URI, hence I would suggest your second proposal, to have a single hierarchy/list of users:
/users/1
/users/2
...
It is acceptable to define (in the appropriate Media-Type) the returning document to hold properties based on the current user's permissions.
Now, regarding whether that is easy to use or not is subjective. I would argue that returning pure data is always somewhat inconvenient, because the client has to parse and understand the data. This is why HTML and HTML Forms were created, so the client does not need to know how to present the data, and also doesn't need to know what's editable and what is not. Then again, I don't know your exact use-case.

Restful Api: User id in each repository method?

I am new to both .Net & RESTful services.
Here is the object hierarchy I have in the database: Users->Folders->Notes.
The API: GET /api/note/{noteid}
would get mapped to the repository call
NoteRepository::GetNote(userId, noteId)
Notice that I am passing on the userId to make sure that the note belongs to the logged in user for security purpose.
Is this the right approach? Meaning, every repository call would have the first parameter as the userId to check if the object being accessed belongs to the user.
Is there any better approach?
You don't need the User Id since the
GET /api/note/{noteid}
is indeed unique.
A valid scenario for adding the id would be:
GET /api/{userId}/notes
And then if you want a specific note you can:
GET /api/{userId}/notes/{noteId}
I would implement security at the entry level. whether the user has rights to perform a method on that specific resource. A role model approach would be fine.
Regards.
I would also introduce the user id in the API, because of Stateless and Cacheable constraints described in the Wikipedia REST article.
However, if I check Google Tasks REST API, they don't include the user id, same thing for Twitter API, so it seems a trend not to include the user id. If someone can shed some light I would be grateful.
UPDATE: Thinking more about it, if the noteid is unique across all users, there is no need to include the user id, so a GET /api/note/{noteid} is fine.
However, the logical parent in a restful interface would be GET /api/note/ to get a list of all notes, and here I've the objection, since the list would differ according to the user requesting it, making it non cacheable.
As for your dot net part I think that passing the userid among dot net methods is perfectly fine.