REST - Canonical URI vs Relative URI (from a user point of view) - http

I'm currently designing a service.
It is a multi-tier service, that stores data from several clients using a REST interface.
It's not clear to me how should I accept a resource id inside the URI.
Let's say the user 001 creates a resource, the first for him, but the 100th for the system.
What should I return when the user 001 makes a GET to /resource/1 (/resource/{id}). Should I display his record thus making the URI relative to the user performing the request? Or should I return the 1st for the system (denying it because it's missing the permissions to see it)?
I don't want to go deep inside the authorization stuff, but I'd like to know how should I handle this kind of situations. If I should prefer the latter then how can I make a user say "ok, give me the 1st resource I created" or "give me the 2nd ... ", "give me the last .. ", "give me the 100th resource I created"?

I dont claim to be an expert on REST but here is what I would probably do.
In your domain model, if a resource cannot exist without a user then its perfectly OK to model URL calls such as
GET /user/{userId}/resource //Gets all resources of a user
On the other hand if resources can exist without users then this link on stackoverflow gives a nice way of modelling such calls.
RESTful Many-to-Many possible?
Another thing which we did for one of our projects was that, we had the linking table (UserResource table(id,userId,resourceId) ,and we had a unique ID for that and had something like
GET /userResource/{userResourceId}
GET /userResource //Retrieve all the resources user has access to
If security is your concern , there are links on StackOverflow on how to integrate Security with Rest calls. Ideally such logic should be handled on the serverside. You typically do not want to put that logic into the REST url.
For example if you get a call for
GET /resource //Get all resources
Depending on who the user is, you return only that subset of resources he has access to.
Bottom Line : Dont build your resources around permissions.
Again, I am not an expert. Just my humble views. :-)

Related

Web API URL understanding

I have a question about web api. My models are User -* Budget -* Item. I'm sure that a method below is not right for getting an item
http://localhost/api/items/getitem/userid/budgetid/planFact/inOut/month/
and I have to authorize user first and then return only his data, but I don't know how can I do this.
and is it right to pass a lot of parameters in uri to retrieve needed data?
Assuming this is a simple API, you should be able to get away with Basic Auth under SSL (https). Under this scheme, you'd pass the user's credentials up with every request in a header. That gives you ready access to the username for filtering out data. If this is homework, you can probably just say "and I'd use SSL in the real world" - ask your teacher.
As far as URI design, it's difficult to understand from your question what those path segments are supposed to represent, but you probably want to avoid anything that looks like a verb (such as getitem). Consider supporting these calls:
GET /items/{itemId}
// returns details on a specific item
GET /items?userId={userId}&budgetId={budgetId}
// returns a list of all items matching the query parameters
// may return just ids, limited detail, or as much detail as GET /items/{itemId}
It's not really clear what planFact and inOut are supposed to be. If month is to specify the items for a specific month, that should be a query parameter also.
It is likely that everyone will be happier if your URIs do not contain that many path segments.

Controlling access to data

I keep running into cases were I want to limit access to data rather than methods.
As an example, I have a users table. An individual user's record should be visible only to themselves, the helpdesk, and the user's manager. However, only the manager can edit the user.
I can restricted view and edit methods by the above roles using the authorization attributes, but then I still need to check and see if the current user has the ability to touch the data he is requesting. This is where the authorization attribute falls short.
I'm currently considering adding an "IsAuthorized" method to all of my models to check and see check if the current user is allowed to perform the current action, but this seems tedious in general, so I wanted to see if anyone else had a centralized way of doing this.
Thanks again!!
(Currently coding everything in ASP.NET C# MVC 4.5.)

Concept of "active" resource in a REST API

I'm working on a REST API in which a particular resource can be designated as "active." To illustrate, here's a simple example of what I'm trying to achieve:
Suppose I have a URI that represents a collection of books: /books.
A given book has a canonical URI of the form /books/{id}.
I have another URI which provides a pointer to the active book: /books/active. This will simply send an HTTP 303 referencing the canonical URI for the active book.
What is the best way to allow a client to also update the active book? Should I allow a client to issue a PUT on /books/active specifying the canonical URI for the active book, or is there another generally-accepted pattern for doing this sort of thing? (It seems strange to me that a client would issue a PUT that sends the canonical URI rather than an actual representation of the resource.)
Update: Only one book can be active at a time (mutually exclusive), so I don't think it makes sense to make the active flag a property of the book itself, since that would imply that more than one book could have the value set to true.
It's a bad idea to build state into your URIs by allowing something like PUT /books/active. It completely screws with the server's ability to provide adequate caching and has been called out as an anti-pattern by Tim Stokes.
URIs in a RESTful system should uniquely identify a resource. While the representation of the resource may change (and the state of the resource may change), the same URI should never be used to point to a different resource. Doing so goes against the expected semantics of methods such as GET and PUT.
In your case, what's wrong with simply including a query parameter on the books collection? Something like, GET /books?state=active, for instance. That would return you the collection of all active books (which may always be 1 book, but what if that changes in the future?) You could drill down from there and PUT to the canonical URI.
Even better, build up a link relation architecture and simply include a relation for "active-book" next to the "self" link for the books collection. That way your client doesn't even need to be aware of your URL convention; it can simply follow the link the server provides.
If you have a higher level resource that contains the books, then it can have a property which is activeBook with a value of the book id and/or full url to the active book. For example, if a user had a bookshelf then /user/myShelf would have books and the active book I was reading would be the active one from that my shelf.
This is more elegant than having a property on each and every book like isActive or putting state in the url.
We had a similar issue in one of our public APIs and went this route. It's hard to say for sure without clear insight into all the resources and their relationships. Maybe if you clarify the relationships a bit more ...

Keeping track after the back button

I want to write a web app order system using the REST methodology for the first time. I understand the concept of the "message id" when things get posted to a page but this scenario comes up. Once a user posts to the web app, you can keep track of their state with an id attached to the URI but what happens if they hit the back button of the browser to the entry point of the app when they didn't have any id? They then lose their state in the transaction.
I know you can always give them a cookie but you can't do that if they have cookies turned off and, worst case thinking here, they also have javascript turned off.
Now, I understand the answer may be "Yes, that's what will happen", that's the end of the story, and I can live with that but, being new to this, is there something I'm missing?
REST doesn't really have states server-side; you simply point to resources. User sessions aren't tracked; instead cookies are used to track application state. However, if you find that you really do need session state, then you are going to have to break REST and track it on the server.
A few things to consider:
How many of your users have cookies disabled anyway? How many even know how to do that?
Is it really likely that your users will have JS turned off? If so, how will you accomplish PUT (edit) and DELETE (delete) without AJAX?
EDIT: Since you do not want to force cookies and JavaScript, then you cannot have a truly RESTful system. But you can somewhat fake it. You are going to need to track a user server-side. You could do this with a session object, as found in your language/framework of choice or by adding a field to the database for whatever you want to know. Of course, when the user hits the back button, they will likely be going to a cached page. If that's not OK, then you will need to modify the headers to disallow caching. Basically, it gets more complicated if you don't use cookies, but not unmanageable.
What about the missing PUT and DELETE HTTP methods? You can fake those with POSTs and a hidden parameter specifying whether or not you are making something new, editing something, or deleting a record. The GET shouldn't really change.
The answer is that your application (in a REST scenario) simply doesn't keep track of what happens. All state is managed by the client, and state transitions are effected through URI navigation. The "State Transfer" part of REST refers to client navigation to new URIs which are new states.
A URI accessed with GET is effectively a read-only operation as per both the HTTP spec and the REST methodology. That means if the client "backs up" to some previous URI, "the worst" that happens is another GET is made and more data is loaded.
Let's say the client does this (using highly simplified pseudo-HTTP)...
GET //site.com/product/123
This retrieves information (or maybe a page) about product ID 123, which presumably includes a reference to a URI which can be used to POST that item into the user's shopping cart. So the user decides to buy the item. Again, it's oversimplified but:
POST //site.com/shoppingcart/
{productid = 123}
The return from this might be a representation of the shopping cart, or a reference to the added item (which could be used on the shoppingcart URI with DELETE to remove the item again), or a variety of other things (such as deeper XML describing the cart contents with other URIs pointing to the cart items and back to the original products). It's all up to you.
But the "state" is defined by whatever the client is doing. It isn't tracked on the server at all, although you will certainly keep a copy of his shopping cart contents in your database for some period of time. (I once returned to a website two years later and my shopping cart items were still there...) But it's up to him to keep track of the ID. To your server app it's just another record, presumably with some kind of expiration.
In this way you don't need cookies, and javascript is entirely dependent on the client implementation. It's difficult to build a decent REST client without script -- you could probably build something with XSLT and only return XML from the server, but that's probably more pain than anyone needs.
The starting point is to really understand REST, then design the system, then build it. It definitely doesn't lend itself to building it on the fly like most other systems do (right or wrong).
This is an excellent article that gives you a fairly "pure" look at REST without getting too abstract and without bogging you down with code:
http://www.infoq.com/articles/subbu-allamaraju-rest
It is true that the "S" in REST stands for "state" and the "T" for "transfer". But the state is is kept on the client, not on the server. The client always hast all information necessary to decide for himself in whicht direction he wants to change the state.
The way you describe it, your system is not restful.

Query String Parameters make my app at risk?

I'm writing an Asp.Net WebForms app where I am calling an edit page an passing in the data about the record to be edited using query string parameters in the URL.
Like:
http://myapp.path/QuoteItemEdit.aspx?PK=1234&DeviceType=12&Mode=Edit
On a previous page in the app, I have presented the user with a GridView of screened items he can edit based on his account privileges, and I call the edit page with these above parameter list, and the page know what to do. I do NOT do any additional checking on the target page to validate whether the user has access to the passed in PK record value as I planned to rely on the previous page to filter the list down and I would be fine.
However, it is clear the user can now type in a URL to a different PK and get access to edit that record. (Or, he may have access to Mode=View, but not Mode=Edit or Mode=Delete. Basically, I was hoping to avoid validating the record and access rights on the target page.
I have also tested the same workflow using Session variables to store PK, DeviceType, and Mode before calling the target page, and then reading them from Session in the target page. So there are no query string paramaters involved. This would take control away from the user.
So, I'm looking for feedback on these two approaches so that I choose an accepted/standard way of dealing with this, as it seems like a very common app design pattern for CRUD apps.
Agreed, you'll want to validate permissions on the target page, it's the only way to be absolutely sure. When it comes to security, redundancy isn't a bad thing. Secure your database as if you don't trust the business layer, secure your business layer as if you don't trust the UI, and secure the UI as well.
You should always validate before the real execution of the action, especially if passing the parameters by query string. For the second page that does the execution you might not need as much feedback for the user since you do not have to be nice to the user if he tries to cirumvent your security, so error handling should be a lot easier.
Passing the variables per session is acceptable but imho you should still validate the values.
We always use querystrings so records can be bookmarked easily, however always validate in both places, if you write you access control code nicely it should just be a case of re-using the existing code...
I believe the common practice is to do what you're avoiding: On the original page, you need to check to see what the user should have capabilities to do, and display their options appropriately. Then on the actual work page, you need to check the user again to verify they are allowed to be there, with access to that specific task.
From a usability standpoint, this is what the user would want (keeps it simple, allows them to bookmark certain pages, etc), and security on both pages is the only way to do this.
If you really don't want to check access rights on the target page:
You could hash the PK with the UserID and then add the hash value to the query string.
string hash = hashFunction(PK.toString() + UserID.toString());
Then you have to make sure the hash in the queryString equals the hash value calculated before loading the page.
Assuming this is an internal organization Web application.
Session variables can be manipulated as well, although not as easily. Whatever authentication you're using throughout your site, you should definitely use on your target page as well. Otherwise, you'll be open to exposing data you may not want as you have found out.
You could do the following to make your URLs a bit more secure:
-Use Guids for Primary Keys so users cant guess other record ID's
-The Mode couls be implicit: Guid = Edit, no Guid = New
and..
-Server-side validation is the only way to go.

Resources