REST API URI Design for sensitive resources - api

I have an application backed by RESTFul API. The application have user management section through which an admin user can manage other users. One sample URI for one of the API operation endpoint is below.
Update User : POST https://example.com/api/users/user1
Here user1 is the Username of the user being edited by the admin.
Suggestion from the security side is to remove the username from the URI since it is sensitive info and since it is part of url it will be recorded in network logs. Solution suggested is to pass the username data in POST Request Body .
Moving the data to request body is fine. But if I remove the username from URI ,the URI will be like "**POST https://example.com/api/users**" . This clearly doesn't look like a valid REST URI. And my USER entity doesn't have any other unique property which can be used in the URI.
Is there any recommended way to form a proper REST URI in such a scenario ?

POST /api/users
This clearly doesn't look like a valid REST URI.
Sure it does.
REST doesn't care what spelling you use for your resource identifiers, so long as the spelling is consistent with the production rules in RFC 3986.
That said, there's no particular reason that the identifier for a document needs to include sensitive information.
There are a couple of possible solutions - if the client and the server both know the sensitive data, then you can use a hashed value, rather than a raw value, as part of your identifier.
That's not ideal: we have mechanical ways of communicating URI that accept parameters, but no standard that I know of for communicating that some value should be hashed first.
If code-on-demand is an option, you might be able to manage to instruct the general purpose client to hash the data before sending it.
Otherwise, I think you are reduced to communicating the hashing out of band -- imagine a web form that instructs the human being to type in the hashed value of the sensitive information.
REST is optimized for the use cases that it was optimized for, and that means that some other use cases are more clumsy than we might like. Hooray for trade offs.

One way is to use an "id" instead of "username":
https://example.com/api/users/{id}
where "id" is usually a UUID https://en.wikipedia.org/wiki/Universally_unique_identifier

Related

RESTful URL to check unique username and email address

During registration I am asking for username, email, and password. I am checking if the username and email is unique via the following end points
HEAD /auth/:email
HEAD /users/:username
Uniqueness of emails and usernames is split into auth and users resource because I thought when logging in I am asking for email so that should be in the auth and checking if the username is unique or not can go in users.
Login happens at the following endpoint
POST /auth/login
A new user is created at the following endpoint
POST /users
This is a stateless API and I am wondering if my routes look RESTful?
I am wondering if my routes look RESTful?
REST doesn't care what spelling conventions you use for your resource identifiers, so long as they conform to the production rules described in RFC 3986.
See, for instance: Tilkov 2014.
Instead, you should choose your identifier spelling conventions to make things easier for your human beings: what spellings are easy to document? what spellings are easy to recognize in the access logs? and so on.
You might be better off with a single resource that reports the status of the email address and username together, rather than using two different reports to do that.
Similarly, using HEAD requests is a bit weird; you are apparently using metadata in the transfer of documents over a network domain to communicate your business semantics, which (a) is what the documents are for and (b) is an example of "accidental complexity" -- I won't go so far as to guarantee problems down the road, but you are certainly inviting them, and it's not obvious that the current benefits outweigh that risk.

Add instruction 'how' to perform a REST API request by adding header or body param?

Imagine a simple REST API that allows to create a user account, by sending a JSON resource to POST /users as in the following. By default it sends out a confirmation email to the user.
{
"username": "john#appleseed.com",
"password": "secret"
}
However sometimes there are good reasons for not sending out a confirmation based on the use case, e.g. another API client, or admins signing up users on their behalf.
Since it doesn't have any implications on the created resource but is more of an instruction how to create the user, should it be separate from the request body? What's the best way to do this?
Specify a custom header Confirmation: no-confirmation
Add a query param ?confirmation=false
Add a send_confirmation field to the request body
Let's take the options in order:
Adding a header value to indicate some semantic difference should be generally avoided. The API should be "browseable", meaning it should be discoverable following links only.
Adding a query parameter is, from REST perspective completely equal to creating another URI. It does not really matter how you expose it, the point is that the client needs to follow some links from the previous "state" it was in. This is actually ok, as long as the links to these resources indicate the different semantics you described: like creating users by admin, users creating themselves, etc.
Also note, that the API should not necessarily expose whether a confirmation is sent. The API should expose the "purpose", the server then can decide whether the use-case warrants a confirmation email.
Putting a send_confirmation in the JSON representation itself. This is ok, if this is a functionality available for the user. For example I can ask for a confirmation email. If I can't, and it is only used for differentiating different use-cases, then I would rather prefer option 2.
Summary: For the case you are describing I would pick option 2: different resources for admins and normal users.

Apigee App Services - Securing sensitive data in /Users collection

I've got a collection of users stored in the default App Services /Users collection.
Out of the box, to create a user, you only need to collect the following data:
{
"username" : "john.doe",
"email" : "john.doe#gmail.com",
"name" : "John Doe",
"password" : "test1234"
}
Name and email aren't exceptionally sensitive (albeit still should be properly secured), but if I wanted to include address, date of birth, mother's maiden name, etc., this data would become significantly more sensitive.
Luckily /users data isn't available without authenticating, but it is if I request an access_token and log in.
Of course one could easily design a front-end that obscures sensitive bits, hiding it from view. But looking at the underlying endpoint, it wouldn't take much to capture out my access_token and make an authenticated GET request to /{org}/{app}/users, thus seeing all of every user's personal information.
Is it possible, through roles and permissions or ownership, to limit segments of an entity only to self? (For example, the logged in user could access their entire user entity, but only limited segments of other user entities).
If not, is there a different way to approach this predicament and secure sensitive information in user objects?
Remus,
Unless you delete or modify the "Default" role, you cannot see one user's data with another user's token. So nothing to worry about there.
Also, as a matter of good practice, you should make sure you are sending the oauth token in the header, rather than in the query string (e.g. don't do ?access_token=''.
Rod
I would suggest that you put App Services behind API Services (Apigee Gateway) then rewrite the payload.
Basically (although it's a few extra steps than I'm going to be able to put into a short response) you would do the following:
1) Create a proxy in API Services to your usergrid.com target (https://api.usergrid.com/{yourorg}/{your app})
2) Create a /users resource.
3) Either use a Javascript callout to rewrite the payload with only the elements you want to expose or use the ExtractVariables policy to pull the specific elements you want to expose and the AssignMessage policy to Set a new Payload with only the response you want to expose.

RESTful way of having a single resource based on authentication

I have an API that provides an Account resource based on the authentication (login) that is supplied. As a user can only have one account, and can only see it's own account and not those of others, this API will basically be a single resource API in all cases.
So to keep things simple, I have this resource under the url accounts/ and when you access accounts/?username=dude&password=veryhard you'll get your account data (if you dohn't supply authentication you'll get a 403).
Now I wonder if this is RESTful. Also, you should be able to update your account info, and I wonder if PUT would be appropriate. In my knowledge, PUT should be done on a unique URI for the resource. Well, is this a unique URI for the resource? Generally a URI for an account would look like accounts/3515/ where 3515 is the account id. However, users don't know their account id. Also, there should be more ways to log in, instead of a username + password you should also be able to use a token (like accounts/?token=d3r90jfhda139hg). So then we got 2 URL's that point to the same resource, which also isn't really beautiful for a RESTful URI, is it?
So, what would be the most RESTful solution? Or should I not do this RESTful?
REST purists will consider that use of /accounts/ to obtain a single account is bad practice as it should specify a collection. Instead consider a key which cannot be mistaken for an ID, for example if your IDs are UUIDs then use a token such as 'me' so your URL is /accounts/me. This has the advantage that if later on you wish to obtain different account information, say for example you need to list users or you have an administration system using the same API, then you can expand it easily.
Putting username and password in the URL is also not pure REST. The query parameters should be directly related to the resource you are obtaining; commonly filtering and limiting the resources returned. Instead you should seriously consider using something like HTTP Basic authentication over an encrypted (HTTPS) connection so that you separate out your authentication/authorisation and resource systems. If you prefer to use a token system then take a look at oauth or hawk.
Finally, yes if you use PUT you should supply a full resource identifier. Given that it is very common for systems to read data before updating it the lack of ID won't be a problem as that will come back as part of the prior GET.
Yes accounts/?username=dude&password=veryhard is a correct REST URL.
PUT is used with an id if it used to update a resource, if you use it to create you must supply an ID. otherwise you use post to create a resource without id

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.