In an ideal RESTful API that supports multiple accounts, should each resource have it's unique identifier across the entire system, or it is OK if that identifier is unique for the specific account that it belongs to.
Are there any pros and cons for each scenario?
To give an example.
Would this be fine from the REST principles?
http://api.example.com/account/1/users/1
...
http://api.example.com/account/50/users/1
or would this approach be recommended?
http://api.example.com/account/1/users/{UNIQUE_IDENTIFIER}
...
http://api.example.com/account/50/users/{ANOTHER_UNIQUE_IDENTIFIER}
You reveal valid user numbers by always having the first user as 1. Someone then knows that any account will also have a user 1. I'm not saying that you should hide user IDs just through obscurity but why make it easy for someone to find the user IDs in another account?
All that really matters is that each resource has a unique identifier. Both of your examples accomplish that, so you seem to be okay (RESTfully speaking)
I don't see any compelling reason to use one over the other. I'd choose whatever makes more sense for your implementation.
Since, from the perspective of an external system using your REST API, the entire address should be considered to be the "identifier" for that resource object, so your first example is fine.
Related
If I display user_id that represents each unique user in the db as an atrribute in an HTML element, is that good practice? Because I need the reference to the user if I want to perform an action on that particular user such as adding him to be my friend.
Example in HTML:
<div data-user-id='12' onclick=addFriend(12)>
Click to add John as your friend
</div>
Where 12 is John's actual user id in the db. From a security perspective, is it secure to do this?
it's never a problem to display the user id, actually, it's more secure than showing the username which could be used for logins, but a better solution is to display an id that could be set or changed by the user himself, look for facebook design for reference.
In this case, you want the user to be able to set his public id, and you use this public id to identify the user externally, then you map it to the actual user id internally in the back end.
anyway, all of this is not relevant for an abstract case, to decide how secure it's you need to consider the other security design elements of your application, the main question is always what can a malicious user do by knowing the actual user id?
As usual....it's complicated.
It all depends on how attractive your site is to hackers (and therefore how much effort they're going to invest), and how secure the rest of your solution is.
The first step in an organized attack is to find out as much as possible about your website. Your current solution leaks information. Knowing that users are identified by an integer may be useful (some database engines are more likely to use integers rather than GUIDs). It may help attackers guess other keys. By guessing sequential user IDs, they can find out how many users you have.
Once the attacker has found out all this information, they will use it to try and penetrate your application. The more information they have, the easier it is to create a plan. An individual piece of information may not be useful, but when you put it together with other snippets, it may reveal something useful.
So, no, there's no obvious major risk in this design by itself. It may be part of a wider attack, though, and it could be the bit of information that exposes some other flaw.
I'm playing around with a spare time project, mainly to try out new stuff :)
This involves designing a REST API for a system that is multi tenant. Lets say you have an "organization" that is the "top" entity, this might have an API key assigned that is used for authenticating each request. So on each request we have an organization associated.
Now when a user of the API would like to get a list of, lets say projects, only those that belong to that organization should be returned. The actual implementation, the queries to the database, is pretty straight forward. However the approach is interesting I think.
You could implement the filtering each time you query the database, but a better approach would be a general pre-query applied to all "organization" related queries, like all queries for enities that belong to an organization. It's all about avoiding the wrong entities from being returned. You could isolate the database, but if that is not possible how would you approach it?
Right now I use NancyFX and RavenDB so input for that stack would be appreciated, but general ideas and best practices, do's and don't is very welcome.
In this case you could isolate your collections by prefixing them with the organization_id. It will duplicate maybe many collections.
Use case with mongodb: http://support.mongohq.com/use-cases/multi-tenant.html
For a system which as an internal identifier for a resource (like person_id), does it make sense to give direct API access callable on a different unique value (like licensee_id)?
So would having such an API design be reasonable?
GET /people/{:licensee_id}
And:
PUT /people/{:licensee_id}
{
"name": "John"
}
That means that the resource you're talking about doesn't have a unique identifier, but it
has two.
If I were to do it I would expose the same resource from two different URLs, like so:
/licensee/:licensee_id
/people/:person_id
so that if the user of your API in a portion of code is dealing with people (i.e. has easy access to a person_id without any other call) calls the second, otherwise he could call the first.
One of the reasons, beside the fact that it is easier for the consumer of your API, is that it's easier for you to implement, you don't have to understand if what is being passed to you is a licensee_id or a person_id
It makes sense to do it this way. You're not really giving up any important information that would make it really any less difficult for someone to do a SQL injection attack (since all foreign keys in other tables that reference the id would have different a name(s) anyway).
If not direct access to the id field, you'd need a different column that is indexed with something like a uuid or md5 created from unique user fields. The only upside I see to doing it this way is that someone would not be able to use the API to "walk" the users or other objects.
Currently I am developing an API and within that API I want the signed in users to be able to like/unlike or favorite/unfavorite two resources.
My "Like" model (it's a Ruby on Rails 3 application) is polymorphic and belongs to two different resources:
/api/v1/resource-a/:id/likes
and
/api/v1/resource-a/:resource_a_id/resource-b/:id/likes
The thing is: I am in doubt what way to choose to make my resources as RESTful as possible. I already tried the next two ways to implement like/unlike structure in my URL's:
Case A: (like/unlike being the member of the "resource")
PUT /api/v1/resource/:id/like maps to Api::V1::ResourceController#like
PUT /api/v1/resource/:id/unlike maps to Api::V1::ResourceController#unlike
and case B: ("likes" is a resource on it's own)
POST /api/v1/resource/:id/likes maps to Api::V1::LikesController#create
DELETE /api/v1/resource/:id/likes maps to Api::V1::LikesController#destroy
In both cases I already have a user session, so I don't have to mention the id of the corresponding "like"-record when deleting/"unliking".
I would like to know how you guys have implemented such cases!
Update April 15th, 2011: With "session" I mean HTTP Basic Authentication header being sent with each request and providing encrypted username:password combination.
I think the fact that you're maintaining application state on the server (user session that contains the user id) is one of the problems here. It's making this a lot more difficult than it needs to be and it's breaking a REST's statelessness constraint.
In Case A, you've given URIs to operations, which again is not RESTful. URIs identify resources and state transitions should be performed using a uniform interface that is common to all resources. I think Case B is a lot better in this respect.
So, with these two things in mind, I'd propose something like:
PUT /api/v1/resource/:id/likes/:userid
DELETE /api/v1/resource/:id/likes/:userid
We also have the added benefit that a user can only register one 'Like' (they can repeat that 'Like' as many times as they like, and since the PUT is idempotent it has the same result no matter how many times it's performed). DELETE is also idempotent, so if an 'Unlike' operation is repeated many times for some reason then the system remains in a consistent state. Of course you can implement POST in this way, but if we use PUT and DELETE we can see that the rules associated with these verbs seem to fit our use-case really well.
I can also imagine another useful request:
GET /api/v1/resource/:id/likes/:userid
That would return details of a 'Like', such as the date it was made or the ordinal (i.e. 'This was the 50th like!').
case B is better, and here have a good sample from GitHub API.
Star a repo
PUT /user/starred/:owner/:repo
Unstar a repo
DELETE /user/starred/:owner/:repo
You are in effect defining a "like" resource, a fact that a user resource likes some other resource in your system. So in REST, you'll need to pick a resource name scheme that uniquely identifies this fact. I'd suggest (using songs as the example):
/like/user/{user-id}/song/{song-id}
Then PUT establishes a liking, and DELETE removes it. GET of course finds out if someone likes a particular song. And you could define GET /like/user/{user-id} to see a list of the songs a particular user likes, and GET /like/song/{song-id} to see a list of the users who like a particular song.
If you assume the user name is established by the existing session, as #joelittlejohn points out, and is not part of the like resource name, then you're violating REST's statelessness constraint and you lose some very important advantages. For instance, a user can only get their own likes, not their friends' likes. Also, it breaks HTTP caching, because one user's likes are indistinguishable from another's.
I am planning to use Django's comment system (with the threadedcomments app).
Since I only allow registered users to post, the mandatory user/url/email fields are not needed (just want a ForeignKey(User)).
I have a feeling I am not the first (nor the 1000th) to do this, can anyone point me to any implementations ?
I think this is what you need.
http://api.rst2a.com/1.0/rst2/html?uri=http%3A//django-threadedcomments.googlecode.com/svn/trunk/docs/api.txt&style=zope
FreeThreadedCommentFreeThreadedComment is better suited for allowing just about anyone to post comments on an item. Instead of being associated with a particular user, instead it asks for some additional information like name and e-mail.
ThreadedComment
ThreadedComment is useful for allowing registered users to comment. It is for this reason that there is a required foreign key to User.