Authorization of List/Search endpoints in REST API - api

I want to understand how to deal with authorization in REST API with endpoints like below
GET /resource/:id
DELETE /resource/:id
GET /resource
Assumptions
User Bob is authenticated.
Bob only owns resources with id 1,2,4,5,6 but 3
System has an Access Control and Busines Logic Layers
The business layer doesn't have any awareness of data ownership
Access Control Layer has policies for resources and users and it can check if users have the right to access resources and
reject the request with HTTP403 or pass it to the Business Logic
layer to be processed
Scenario
Bob sends a request to GET /resource/2, the application returns resource details with HTTP 200
Bob sends a request to DELETE /resource/3, and the application returns HTTP 403.
Bob sends a request to list resources GET /resources?page=1&pageSize=10, the application returns resource summaries of 1,2,4,5,6 but 3
Problem
The Access control layer can prevent(403) access to a specific resource by checking the claims of the user for a given resource with defined policies.
But It should not be PREVENTED(403) when accessing search endpoints. It should be FILTERED.
Approach 1
It may assumed that search would include summaries of resources that is not owned by the authenticated user.
Approach 2
Search endpoints may be entirely separated and have the awareness of resource ownership and have the responsibility of resolving ownership and filtering.
Other endpoints stay clean by having only business logic.
Questions
Which alternative approach is better?
Is there any alternative?
Am I mixing concepts of data ownership, access control, and business logic?

I think you are mixing these concepts. Let's start from the very beginning:
If a particular user, in this case Bob, is authenticated and his authentication records have policy which defines access to a particular set of resources ( or defines prevention of access to particular set of resources ) then that status should be PREVENTED. Why?
Bob is PREVENTED from accessing particular resources. FILTERED means filtering data and that's something that you can do even when Bob has access to the data. When Bob receives 200 OK status with records that he wanted, internal functionalities of the API can still filter the data that will be adapted to the policy Bobs authentication records hold.
If in our database we have set of records like this: [1,2,3,4,5,6,7,8,9,10]
And we want to create policies that will prevent some users from access a particular record then we can have policies set up in the way where we describe records that define access a particular user has. On example policy can define a record that holds number 3 in a array ( [3] ) and based on this we can create a logic that would obviously filter out the data that's in the array and return [1,2,4,5,6,7,8,9,10].
However, this model heavily depends on how your data is structured. Questions you might want to ask yourself before designing your policy records:
How are my records structured? Do they have records/tables that I can split my data into? If they do, I can define something like <COLLECTION/TABLE_NAME>:<ACCESS_LEVEL> which would in this case yield numbers:* or numbers:[1,2,4,5,6,7,8,9,10].
Can I save access needed into my records? Common practice is to have needed access definitions saved in the records or related records of the data you save. Something like: access_needed: [ "read", "write" ]
Again, it all comes down to your records and based on that you can structure how to define your policy format.

Related

Is the appropriate way to fetch user roles/permissions/information from an ID Token or an API endpoint (or other)?

When creating an Angular web application that also has a backend API, I feel like there are a few different options when it comes to getting User Info such as roles/permissions/display name/email/etc.
We can use an ID Token to store user claims like this. That token can be put into local storage or a cookie and the Angular app can read it and render the UI/guard against unauthorized route navigation/etc as soon as the app spins up (since the ID token is available right then and there).
We can NOT use an ID Token for this information at all and instead have an API endpoint that we have to call every page re-load to fetch this data. The server would decode our access token/ID token and return the data in JSON format.
Lastly, there could be some hybrid solution where basic User Info like names/emails are stored int he ID token and available right away, but user permissions (which could be a larger payload and maybe not wanted in a token that should be small) could be fetched via an API
Is there maybe a 4th option I didn't think about?
I haven't been able to find many conventions around which of these options is the best. I like the ID token option as it requires no "blocking" of the UI until the API request is done making the page load that much faster, but I'm not sure if that goes against other conventions.
All your approaches rely on a permissions-based system where you would have been granted permissions upon login. These are sometimes referred to as birth rights since they are typically given when the user is created or whenever their permission sets change. The typical way to carry birth rights around is to have them as scopes / assertions inside an identity token (e.g. OAUth 2.0) that you pass along from service to service.
You can also have your applications retrieve additional permissions / roles / entitlements from a backend store (a database for instance) based on the user ID so that you know what your user can or cannot do.
So far this is essentially role-based access control / permissions-based access control.
The main challenge with that approach is role explosion / permissions explosion as well as token bloat (too many permissions in the token) and administration pains - you have to assign roles and permissions to users all the time. You have to deprovision. It becomes a management nightmare and a risk you may have the wrong permissions set for users. You then need to think about identity and access governance as well as recertification. Heavy.
What's the alternative?
You definitely need some roles - yes - but they should be kept to a minimum - essentially the business roles you need in your apps e.g. a doctor, a nurse, a non-medical staff rather than doctor_hospital1_unitA.
You should then express your authorization as plain-old English policies using any number of attributes - not just user attributes but also contextual information (time, location), resource information (what type of object, who owns it, where is it? How sensitive is it?), and action information (view, edit, delete...).
Sample Policies
A doctor can view a medical record if they are assigned to the patient the medical record belongs to
A nurse can view a medical record if the medical record is in the same unit as the nurse
A non-medical staff can view the financial section of a medical record but not the medical section.
Attribute-Based Access Control
Following this approach is called attribute-based access control (abac). In ABAC, you clearly decouple your app from the authorization process. Authorization is expressed as policies rather than code which makes it easier to:
update
audit
review
How to implement?
You have several options to implement ABAC (from open-source to commercial). You can go down the XACML (xacml) path, the ALFA alfa path, or others. They all have similar architectures with:
the notion of a policy decision point (PDP): a service that evaluates the authorization requests against the set of policies you defined and produce decisions (Permit / Deny) that can be enriched with additional information e.g. order to do two-factor Authentication.
the notion of a policy enforcement point (PEP): an interceptor that sits in front of or inside your API that will send an authorization request to the PDP.
I've written about the architecture more in detail in this SO post.
ALFA Example
In ALFA, a sample policy would look like:
policyset viewMedicalRecord{
target clause object == "medical record" and action == "view"
apply firstApplicable
policy allowDoctors{
target clause role == "doctor"
apply firstApplicable
rule allowAssignedPatient{
permit
condition patient.assignedDoctor == user.name
}
}
}

CRUD only for the organization the user belongs to

Background
I'm building a application where all users belongs to a Organization. I only want the user to be able to Create/Read/Update/Delete records in the Organization they belong to.
I'm using sails, but I'm looking for Connect/Express-based, or a standalone answer as sails-permissions node module is unmaintained.
Question
How can one implement a authorization that allow CRUD only for the organization the user belongs to?
We are also not relying on sails-permissions. In our app, users can be members of multiple orgs.
We are using auth0 for all authentication activities, i.e. every request must include a jwt that is included in the request header. The jwt includes userId, orgId and role.
Sails policies decode the jwt and attach userId, orgId and role the the req object for all later checks.
Every model has the property orgId - we are using MongoDB.
Every controller, db operation, etc. adds this verified orgId to the query. Actually we have a small pipeline preparing the query: we add the orgId, in update cases we filter out unwanted property updates, etc.
This approach does not require additional db calls for separation of tenants.
Some models have specific access requirements per individual RECORD. Here we store allowedUser properties (one for read, one for update, etc.) on exactly this record and we extend the query once more so that only records are returned or updated or Xyz where the current user is included in the applicable allowedUsers property.
This approach also does not require additional db calls. This leverages MongoDB-specific query features, though.
We currently do not have ACL-like requirements which would be right between the 2 approaches I described above (re access control granularity).
You'll need to intercept each request using middlewares
combine them with a role system by checking if a certain token is present on request headers and in a acl map and finally, if the token is present in the acl map, see which permissions are related with this token.

REST API optional path elements

I am in the process of designing a new API and am trying to make it as simple as possible. For the intended system most API consumers will be referencing objects that belong to them alone however a few other accounts will "own" objects in other peoples accounts. The questions is whether account becomes a required part of the path or an optional inclusion for these special super-accounts.
Here is an example spec and works fine in the single user context (Account ID "basic1"):
# return person "s4t4s2" for account "basic1"
GET /v1/person/s4t4s2
# return team "g3a35a" for account "basic1"
GET /v1/team/g3a35a
For super-accounts they have their own objects where the above implementation works, however they also require access to the properties of accounts they effectively own (Account ID "super1"):
# return person "s4t4s2" for account "super1"
GET /v1/person/s4t4s2
# get team "g399a2" for account "super1"
GET /v1/team/g399a2
# return person "s4t4s2" for account "basic1"
GET /v1/accounts/basic1/person/s4t4s2
Because most of my consumers will be dealing with the single account view is it best practice to use the second format for all accounts or is it entirely valid to use both formats with automatic scoping via authentication credientials when the account is omitted?
If I understand correctly, those are the same "person" resources, but they have multiple URIs? I would probably prefer having one URI for a single instance of a resource. Even if it has different "views". Different views can still be solved by either having different media-types, or just filling out fields differently on the same media-type depending on the user's permissions.
The advantage of having a single URI for a single instance is that it can be bookmarked, cached, etc. For example if a user's team/account view changes, it can't reuse its links to persons because the URIs change. I think that is not a good design.
If my understanding is wrong, and /v1/accounts/basic1/person/s4t4s2 is not the same person as /v1/person/s4t4s2 then disregard my comment. :)

How to use XACML and PIP in real application?

How to cover following scenario using XACML (with WSO2 PDP) and PIP (if required).
In Used Car application, in particular location, salesperson are
allowed to view-update car price. They can only view cars which are
assigned to them.
Now from a xacml prespective, we can create policy for salesperson role and based on location hide the particular menus.
But what to do with the method getCarDetails(Object User){...}?
here based on UserID (salesperson) we will show the list.
How to design this with xacml Specifications?
My understanding for this is : We can use spring-security and add "salesperson" role on top of this method. But it will only restrict other users from different roles. from there I am confused that should we use database call as per our traditional applications with userid and get the list of cars or is there a way to get fine-grained access with xacml?
Your question contains 2 questions:
How do I model my policy?
How do I protect my application? (Enforce the decisions)
First of all, let's model your policy in ALFA:
Rule: A sales person can view a car if and only if the car's assigned salesperson identifier is equal to the requesting user's identity.
In ALFA, this becomes:
namespace com.axiomatics{
/**
* A sales person can view a car if and only if the car's assigned salesperson
* identifier is equal to the requesting user's identity.
*/
policy viewCars{
target clause user.role=="sales person" and actionId == "view" and objectType=="car"
apply firstApplicable
/**
*
*/
rule allowAssignedUser{
permit
condition car.assignedSalesPerson==user.identifier
}
}
}
That's your modelling sorted.
Now, with respect to the second question: how do I enforce the authorization? I would argue against mixing roles managed by Spring Security and XACML policies unless you correctly document them.
There are two approaches you can take.
Use the Multiple Decision Profile - this is part of the XACML 3.0 set of optional profiles, or
Use the Reverse Query approach - this is specific to Axiomatics only. I am not sure WSO2 supports it.
The Multiple Decision Profile (MDP) defines how you can send multiple authorization requests written in xacml to a Policy Decision Point (PDP) using a single request. This saves you several round-trips. The response you will receive will contain as many decisions as authorization requests in the original request sent. You save on transport time and on evaluation time too. Use the MDP when you know how many items you want to protect and when that number is anywhere between 1 and 1,000 but not greater (though, of course, it is always worth a try). You can read more on the MDP on the Axiomatics blog. In your case, the flow would be as follows:
Call getCarDetails(Object user).
Call the underlying db to retrieve all the cars
Call the PDP in an MDP fashion for all the records found to get a decision
Return only those records for which you had a Permit
The main drawback is that you may end up receiving thousands if not millions of records from the database. Using the MDP then is not practical.
The Reverse Query approach is interesting albeit specific to Axiomatics. It defines a new interface on top of a XACML PDP which lets you query the authorization engine in a reverse way. Instead of asking:
Can Alice view car #123?
The Reverse Query lets you ask
Which cars can Alice view?
Instead of the response being a Permit or Deny, the response is a filter expression such as a SQL statement e.g.
SELECT id FROM cars WHERE assignedSP='Alice';
All you have to do then is use the SQL statement against your database to query it and return only the entitled data. This works no matter how much data you have in your database. You can find more information on the ARQ SQL via this webinar.

RESTful HTTP: Showing different representations to two users on the same URI

I'm designing a hypermedia API, yes, a RESTful API, with the hypertext constraint.
Each user of the system will access the system using their own credentials, so every request we process is authenticated and authorized. Each user will typically have specific credentials so that they may have different permissione (e.g. none, read, read/write) on each collection.
We want the client to be primed with the one URI that it starts with, which would be perhaps an atom services document, or a hierarchy (draft atom hierarchy extensions) of atom collections.
My question is basically should users see different representations for the same URI, or should users be directed to different URIs based on their permissions?
For example: User A and User B have different permissions in the system. They log in with different credentials, to the same start URI. A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same URI
302 (or other redirect) each user to e.g. /endpoint/userA (which they own)
The tradeoff between cacheability is of course minimal, since resources are cached only by the client and not by intermediaries, but there's a tradeoff for visibility too (URI contains (aythenticated) user ID). Finally there's the future possibility of allowing User A (or a super user) to see what User B sees.
I'm not asking what Twitter or Facebook do, I'm more interested in what REST practicioners have to say about this.
My question is basically should users see different representations
for the same URI, or should users be directed to different URIs based
on their permissions?
For example: User A and User B have different permissions in the
system. They log in with different credentials, to the same start URI.
A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same
URI
302 (or other redirect) each user to e.g. /endpoint/userA (which
they own)
Both ways are RESTful. The representation of a resource can depend on the permissions. The communication is stateless because you send the credentials (username, password) with http auth by every request. Redirection to another representation variant after permission check is a great idea. That way you can completely separate the authorization logic from the resource representation logic, so you can move it even to another server and you can create very well cacheable resource representations. For example by GET /endpoint/userA you can redirect userA to /endpoint/userA?owner=true, because she is the owner of the profile, or you can create a composition of features: /endpoint/userA?feature1=true&feature2=false etc... It is very easy to setup fine grained access control for that. Another way to stay cacheable if you append the user id to every request's queryString, but this solution with redirection is much cleaner. Thank you for that!
Personally I find this a really tough call to make and I think it depends a lot how much content would change. If the difference is the omission of a few extra details then I would probably treat it as a single resource that varies based on the user.
However, once the differences start to get more significant then I would look at creating different resources. I would still try and avoid creating resources that are specific to a particular user. Maybe for a particular resource you could create a set of subresources, with differing levels of content. e.g.
/Customer/123?accesslevel=low
/Customer/123?accesslevel=medium
/Customer/123?accesslevel=high
This method in combination with the 302 may be sufficient in some cases. For more complex cases you could use multiple query string parameters.
/Employee/123?SocialSecurityNo=yes&SalaryInfo=yes
I do not believe there is an easy answer to this question. I think the answer is similar to most tricky REST scenarios: your solution can be as creative as you want as long as you don't violate the constraints :-)
Option 1, replying with 200 is an acceptable REST response and is more user friendly than option 2.
The Google Data APIs provide a decent REST implementation on top of their user services, and they implement option 1. For example the Google Calendar Data API allows a user to query the person's own feed by performing a HTTP GET request on http://www.google.com/calendar/feeds/default/private/full.