I have restful service and I'm trying to follow the best practices. I was wondering what is the best practice when naming a resource that returns data for a specific user. The user is authenticated with a Token sent in the header.
I need to get all the favorites of a specific user.
Examples:
myservice.com/Favorites -> I get the user with the token and then query the favorites, but it seems weird, i would expect /Favorites to return all favorites of any user.
myservice.com/MyFavorites -> MyFavorites is not really an entity, but that would make things clearer.
myservice.com/Favorites?userId=123 -> This one is clear, but it feels redundant to send the userId since I already know the user with the token.
Is there any other way to do this? What is the best practice?
All are valid and of the three you mention, I like the 3rd, However... but I'd suggest a different pattern for your needs:
https://myservice.com/user/123/favorites
Also, stick to all lowercase in your resource urls.
Tokens are fine authentication, but you might have a need where a user might be a 'super user' and would need to hit other user resources for example.
Related
I implement a web application (with Python+Django - to the extent that matters). Users can log in normally with username and password, but in addition I want to provide an API which users use to script the interaction with my site.
For the API authentication my plan was to do something like this:
In the database I create table with 'tokens' - i.e. random strings which point to the user database.
The user gets a token string.
For every API call the user passes the token string along with their request
In the API implementation the code:
Verify the token.
Log the correct user in and execute the API function as the user matching the token.
Log the user out again.
Return the result
Does this make sense? On the one hand it seems very simple - on the other hand it feels quite homemade, something I have heard is not recommended when it comes to security related topics?
I would wholeheartedly recommend looking at django-rest-framework
https://www.django-rest-framework.org/
It literally does all of that and more!
Nope, not a sales person, just a developer :)
It handles quite literally any use case you can think of, and I would be happy to discuss at great length any its not suitable for.
It handles:
Authentication
Parsing
Encoding
View or object level permissions
Object serialisation
Object creation
Object deletion
Automatically generated documentation
Several authentication methods, including custom managed methods
And a bunch of other stuff that makes writing API's in Django much easier
All in all it supports most if not all use cases.
EDIT
It is worth noting that there is a very good reason DRF has short lived access tokens. That is because of security.
Let's say a malicious actor gets hold of your short lived access token, thats a lot better than a "long life" one as you described.
It's worth weighing up security and ease of access, security and protecting your users should always paramount.
Futhermore, I would recommend taking a look at DRF Knox, which is recommended in the authentication section of the DRF docs:
https://github.com/James1345/django-rest-knox
Currently I set up a RESTful API backend using Django and I can list a set of articles by the following GET:
api/articles/
Also, I can get a single article by:
api/article/1/
Each article is owned by a certain user, and one user could have multiple articles of course.
On the frond end side, I present all the articles at loading of the page, and I hope the user who is logged in currently could see the articles that they own in a different style, e.g, outlined by a box, and has a associated "delete" or "edit" button.
This requires me to tell, after the retrieval of the articles, which ones are owned by the current user programmatically. One way of doing this is to check the current user id with the owner id. However I feel this is not a good choice as the user id is the check is done fully on the client side and may be not consistent with the actual server judgement.
Therefore, is there a way, to tell by looking at the response of the GET, (say, let the server return a property "editable=true/false") to get whether the current user could edit(PUT) the resource?
I understand that this could be done at the server side, by attaching such a property manually. However, I am just asking whether there is better/common practice.
I just started learning web development and I am sorry if the question sounds trivial. Thank you!
You can attach propriety manually as you suggested. The advance of this approach is that you dont need any other http request.
Second possibility might be, that your client intentionally request information about endpoint permissions. In this case I would suggest to use OPTIONS HTTP method. You send OPTIONS HTTP request to api/articles/1 and backend returns wanted info. This might be exactly what OPTIONS method and DRF metadata were made for.
http://www.django-rest-framework.org/api-guide/metadata/
I think that this is a very interesting question.
Several options that come to me:
You can add to the GET api/article/1 response a HTTP header with this information i.e. HTTP_METHODS_ALLOWED=PUT,PATH,DELETE. Doing this way helps the API client because it does not need to know anything else. I think that this is not a good approach when more than one entity is returned.
call to OPTIONS api/article/1. Allowed methods for that user on that resource can be returned but notice that, in my opinion, this approach is not very good in terms of performance, because it duplicates the number of requests to the server.
But what if the entity returned also contains information on the owner or it? can, in this case the client know which policy apply and try to figure out it by itself? notice that the policy can be obtained from another endpoint (just one call would be needed) or even with the login response. If your entities do not contain that kind of information, it could be also returned as a HTTP header (like first option above)
PHP
My website is almost done, but i'm having some problems with security. Actually, i didn't have problems yet, but i need to prevent. For example, the login system, i'm using cookies/session for it. And as people answered here, cookies are easy to overcome, and it's vunerable.
What is the best way to do a login system, including the passwords and data security?
Also, i'm using cookies for write the names of the users on posts. For example.
(Pretending that the login was successful)
$Cookie = $_COOKIE['username'];
$Cookie = $FetchUserNameFromDatabase;
//Then, on posts to write the name of the user, from the cookie.
$DoPost = "INSERT INTO posts (username, message) VALUES ($Cookie, $AnyMessage)";
Is this the best way to write the users name on posts, from a cookie value (since after login, the name of the user is saved on a cookie)?
IF NOT, what is the best way to do it?
Thanks in advanced.
#EDIT
I forgot to ask. Also, what's the best way to prevent people do a lot of comments (mass-spam)? For example, i do a comment (or a vote, or whatever) and works fine. Then, i do another comment and it blocks me for some time and i can't comment again until this time expires. What's the best way to do it, or at least, what the major sites/forums uses to prevent it?
Thanks again.
Why don't you just use session ids? I'd implement a login using a https connection, then assign a sessionid, wich identifies the user against your db. For further reference you won't even need a secure connection anymore.
In case you want to identify a post just use somthing like "SELECT username FROM users WHERE sessid=" . session_id()
In point of view, you should only use cookie information when you perform an operation that DOES NOT change the state of your application; like displaying the User name in the top of a page.
However in every scenario that you application is changing its state like adding a new POST (in your example) you definetly must not trust the client cookies.
To answer "The best way to do it", it depends on what technologies your are relying on.
Edit:
To prevent mass spam you should use the cookie information and the request information the like IP address.
I have perused the questions asked about this, but I still don't have a definitive answer.
I have an application and would like to build a RESTful API to expose a subset of information. I have three resources:
users
reports
photos
Users have reports and reports have photos. Photos cannot exist outside of reports and reports cannot exist outside of users.
I have designed the following URLs for my requirements
User login, server responds with token which is sent in the header of all API calls
GET example.com/api/
Get user info
GET example.com/api/users/{username}
Get all user reports
GET example.com/api/users/{username}/reports
Get all photos of a report
GET example.com/api/users/{username}/reports/{report_id}/photos
Add a photo
POST example.com/api/users/{username}/reports/{report_id}/photos
Delete a photo
DELETE example.com/api/users/{username}/reports/{report_id}/photos/{photo_id}
Modify photo description
PUT example.com/api/users/{username}/reports/{report_id}/photos/{photo_id}
Questions
Is it good practice to add a resource id in the URL, i.e. resource/id, or should this rather be added as a query parameter?
Is this method of chaining resources, i.e. resource/id/sub-resource/id/etc., acceptable and good or should I put all my resources at the top level and specify its position with query parameters?
Nothing wrong in this design.But this creates long URL which sometime are difficult to understand and the user of the API needs to know the hierarchy.Moreover the consumer of the API need to write more code in little bit non-standard way(Even though it can be done, but will be little messy). Think this from a different perspective
You have three resources and each has its own identity.So if we refactor the above URI's it will looks like below (I am demonstrating only GET)
User Resource:
Get users list
GET example.com/api/users
Get specific user
GET example.com/api/users/{username}
Report Resource:
Get all reports
GET example.com/api/reports
Get a specific report
GET example.com/api/reports/{report_id}
Photo Resources
All Photos
GET example.com/api/photos
Specific Photo
GET example.com/api/photos/{photo_id}
User All Reports
GET example.com/api/reports?username={userName}
Specific report of a user
GET example.com/api/report?username={userName}&report_id={reportId}
User All Photos
GET example.com/api/photos?username={userName}
User All Photos for a report id (You may not need user Name if report_id is unique irrespective of the user, which will further simplify the URI)
GET example.com/api/photos?username={userName}&report_id={reportId}
All photos of a report
GET example.com/api/photos?report_id={reportId}
This simplifies the understanding and more standard code can be written on the consumer side using this approach.
IMHO you are modelling it well.
Regarding 1 I'd rather go with resource/id rather than query param. But one thing you must have in mind when modelling is the cache mechanism by proxy and so on. So do not forget the headers.
I go for query params for filtering and those sorts.
About the login, the credentials should be in the headers, and no specific resource is needed. Just apply per resource security.
I don't see anything wrong with your scheme.
Most frameworks nowadays use a similar standard for specifying url's (like Django).
In my personal opinion, it makes the URL more readable and a bit nicer for the user.
A site I am working on (using django) requires that users can access a subset of the functionality temporarily by following a URL sent by email, instead of having to login properly (i.e. with username and password).
I am, of course, aware of the potential security issues with this proposal. Therefore, the tokens included in the url are randomly generated and stored on the server (instead of hashing the username or something similar), and expire.
In addition, I would like to restrict the permissions of users accessing the site through such a token URL, so that they can only access some (very limited) information, while their credentials are required for any more substantial actions.
I had implemented this in a rather crude way: Briefly, instead of authenticating the user through the token, it is stored as a session variable, and the few views that recognize the token validate it. However, it would be great to have an extended solution: For example, a global user.has_token check would be brilliant. I can't imagine, however, how a more elegant solution might be achieved.
So my question is: How would you implement such a system? Is it, for example, possible to temporarily allocate or restrict permissions in django? Might a custom middleware be necessary here?
Any help would be much appreciated. Thanks a lot!
Edit: Following the discussion below, I would like to further specify the question: Would it be efficient to assign groups through a middleware on every page view? Would it be feasible to add properties to the user object at run-time (similar to the user.has_token example above)?
usings django groups you can restict access
below link gives you the example:
http://bradmontgomery.blogspot.com/2009/04/restricting-access-by-group-in-django.html