Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 814
John Royal Avatar asked Jun 19 '14 09:06

John Royal


People also ask

What is filtering in REST API?

SAS REST APIs: Filtering. Filtering is the application of a Boolean condition against a collection of resources in order to subset the collection to ony those resources for which the condition is true. (For those familiar with SQL, filtering is analogous to a SQL query with a WHERE clause.)

What are the 3 components of a RESTful API?

A REST message contains these components: Resource Path. HTTP Verb. Body.


2 Answers

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.

like image 92
Eric Stein Avatar answered Nov 02 '22 22:11

Eric Stein


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).

Protecting a REST API - Architecture

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.

like image 36
David Brossard Avatar answered Nov 02 '22 21:11

David Brossard