I have read several tutorials to introduce myself to know more about the rest API recently. However, I have got some doubts here and there and hope someone can help me out with this.
Reading the Beginner's Guide to HTML and REST, which states:
"Resources are best thought of as nouns. For example, the following is not RESTful: 1 /clients/add This is because it uses a URL to describe an action. This is a fairly fundamental point in distinguishing RESTful from non-RESTful systems."
As such, I was wondering if for such cases where I have a user resource and to access it to do the usual insert/update/delete/retrieve
would be as follow:
www.example.com/users [get] <-- to retrieve all records
www.example.com/users/1 [get] <-- to retrieve record with id of 1
www.example.com/users/1 [put] <-- to update record with id of 1
www.example.com/user/1 [delete] <-- to delete record with id of 1
www.example.com/user [post] <-- to insert a new user record
This would have used up the 4 common verbs to make request.
What if I were to require a function such as login or perhaps in general any other types of action commands? How should the url be formed and how should the router redirect in such cases?
EDIT:
After looking at the various comments and answers. My take away from them is that the final solution would be somewhere along "use rest principles whenever possible and use the query string method with functions whenever not."
However, I was thinking of a slight variant of the implementation (not a restful implementation anymore, but following similar concepts) and wondering if it could have work out this way. Hope you guys can advice me on this.
Using the same authenticate/login function I would require to implement, could it be something along this instead:
www.example.com/users [get] <-- to retrieve all records
www.example.com/users/1 [get] <-- to retrieve record with id of 1
www.example.com/users/1 [put] <-- to update record with id of 1
www.example.com/user/1 [delete] <-- to delete record with id of 1
www.example.com/user [post] <-- to insert a new user record
as usual and if I were to require an action to be performed it will be as such:
[controller]/[action] --- user/authenticate [post] --- to login
[controller]/[id]/[action] --- user/1/authenticate [put] --- to logout
Will this work? Will there be any foreseen problems that I would face and are there similar implementations out there like this already? Please kindly advice!
REST is stateless so you need to put all the needed information into all queries. The idea is to work with the HTTP Verbs (GET, PUT, DELETE, POST - as you already descripted).
If you want an user authentification for your REST API, use something like HTTP Basic Auth, or your own Authentification. You have to send the Auth Information for every Request to the Server (stateless).
If you don't want an HTTP Basic Auth you can try some Token Authentification or any other auth.
Edit: If you want an "Check Login" Resource, build your own.
For Example GET /account/checklogin with http basic auth header informations. The Result of this Request depends on your Authinformations.
There are some actions that are hard to model in a true RESTful way - but login, for instance, can be implemented using the following pseudo code:
GET the user rights whose userID is x and password is y
if (user rights found)
assign rights to current user
else
do not assign rights to user
See this question for how to retrieve the user rights. The point in this question is that you usually need multiple ways of accessing your resources. Some are based on IDs or well-know attributes, for instance:
www.example.com/users/department [get] (get all users for a department)
www.example.com/users/roleName [get] (get all users in a particular role)
www.example.com/users/status/active [get] (get all users who are "active")
However, some ways of accessing users - especially when you need to combine two or more filtering attributes - are easier to manage using query string parameters. For instance:
www.example.com/users?department=xxx&role=yyy&status=active [get]
So, your REST API might expose a URL along the lines of:
www.example.com/users?userName=xxxx&password=yyy [get]
This URL would match the username and password parameters against the user database, and return either a 404 (if they don't match a known user), or a document representing the user, with their access rights.
Your client code then manages the current user's session - i.e. by setting the status to "logged in ", and associating the session with that user profile.
The key to making this work is assigning responsibility to the right layer - the API should not have to manage user sessions, that is the responsibility of the client application. There are cases where that doesn't work particularly well - not sure if yours is one, though.
If you really want to use a POST request, you can, of course, consider the "login" method the start of a session for that user. You could, therefore, do something like this:
www.example.com/session [POST] with parameters userID and password.
This would return a representation of the user profile and rights; it might also create documents accessible under the URLs
www.example.com/session/sessionID
www.example.com/session/user/ID/session
However, in general, it is a very dangerous idea to manage session state within the API - nearly always, you want the client session to be managed by the application interacting with the client, not by the API it talks to.
What if I were to require a function such as login or perhaps in
general any other types of action commands? How should the url be
formed and how should the router redirect in such cases?
It's not RESTful to have a login-action resource, but it is RESTful to provide a login-form resource:
/login-form
The HTML-form you return in the response functions as code-on-demand; you are supplying a configured piece of software to help the user supply their login credentials.
There would be nothing wrong with identifying the resource as just /login - I added the form-part to make the example clear.
You should avoid redirects where auth is required because it breaks the interface for clients other than web-browsers; instead you might either: provide a link to the login-form; or actually supply the login-form code in the response.
If you want to manage authentication, I prefer the approach of creating auth-tokens; in the case of Web-browsers I consider it acceptable to overload a single cookie for the purpose of helping the client supply the token with each request since they will have no other reasonable way to control the Auth header they send; obviously if you're writing your own client-application this is not a concern.
Answering your comments below, the purpose of the login form in an auth-token scenario is to create a new authentication token. So, thinking RESTfully, you model the users list of auth-tokens and POST a representation of the auth-token. This representation might contain the user's username and password. You might let the user choose their own token, or you might choose it for them and return this in the response. There is no action-URI required, and setting any cookies happens following successful creation of the new auth-token.
I recommend studying Amazon S3 REST API. It's slightly different than your requirement but its the best in-depth description of a potential REST authentication system I've seen set out:
http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAPI.html
Your thoughts on managing users RESTfully are accurate.
Hope it helps :)
Related
I am building an app which is having only two forms. The first form collect user information. There is no user login/registration involved. And the second form displays survey to be filled in by that user. I can not use passport as there is no login/registration involved . I should not even return sensitive data using any API endpoint.
I want to know which approach should I go for then?
I don't know anything about your application, but it sounds like you might want to use a unique token (for example: h38dhe9ajnq2093bdhgj20opdnwspo2a). I'm guessing you will be sending out links to people who will be filling out questionnaires or surveys, so include the token in your email/message so you can uniquely identify them. Once they initially come to your application, store the token in their session or in a client cookie, and base your authentication middleware on that being present in every request.
I'm assuming that security is not a big concern in this case. Otherwise, you may need to implement this system more carefully.
For the last two days I read through multiple resources on authentication in Symfony2. I think I understand most parts, however I feel that I do not understand the whole thing. I successfully created two authentication providers and a UserProvider but I don't understand how to customize the login process.
What I try to do is writing a REST API that will be consumed by a client that I also write. The client will display a form and sent the credentials via Ajax. Therefore, I don't want to use HTTP basic auth (I don't want a browser window to pop up), I don't want to use OAuth or any token (but use credentials) and I don't want to use a form_login (the login form is rendered by Angular).
Using my custom authentication provider, I can verify that a client is logged in, using a cookie I set in the login controller. However, I don't understand how I would login (or what logged in means in Symfony) a user if I'd try to use the session/Symfony security bundle. I could just avoid all security things from Symfony and roll my own implementation but I would prefer to understand how Symfony expects the authentication provider and the login controller to work together.
What I want is one route where a client can check if it is logged in, login and logout.
GET /session # return the session if it exists, or 401
POST /session { session: { email: testy#mctest, password: test1234 }} # login
DELETE /session # destroy session
How would I achieve this in a "Symfony" way?
(Bonuspoints for explaining the general authentication concept in Symfony, outside of the authentication provider)
I'll try to make it the more verbose and simplest that I can from what I personally know :-).
This is what I understood from when I implemented my own Security layer based on the Symfony Security component. If something is not right, please tell me and I will correct it to make it more accurate.
The Security component works with firewalls. A firewall defined a "zone" that is under the responsibility of the Security Component.
For each firewall, you would usually match a pattern that would be matched with the current request. If it matches, then the Security Component tries to determine if the request is allowed to access the resource.
In order to do this, the Security component is divided into two steps :
First : authenticate the user. If the user is not authenticated, we cannot authorize him. So the component will go through its Authentication Manager in order to authenticate the user. Authenticating a user in the Symfony way means trying to create a Token (which is actually juste an instance of the TokenInterface class) matching the current request that is going to be authenticated, and then try to authenticate it.
This Token is supposed to be created thanks to Authentication Listener(s) (classes implementing the ListenerInterface interface). For instance, one will usually use a UserProvider to set a User into the Token object.
Then, when the token is created, it doesn't mean that the Token is authenticated. This Token will be authenticated thanks to the Authentication Manager. An often use kind of Authentication Managers is based on providers that will check if the credentials (or something else) is wrong with the current token. For example, a DaoAuthenticationProvider will check if the password given with the token user matches with the one in what our users provider gives to us. If not, it fails : either another provider can authenticate the current token, or this will be an authentication fail.
http://symfony.com/doc/current/components/security/firewall.html
Second : authorizing the user. For this, I suggest you to read the chapter about it in the Symfony documentation online. You can find it here. It is based on an AccessDecisionManager that will decide if the current user, based on the authenticated token, is now allowed to access the resource. This is usually made thanks to classes called Voters that will vote in order to decide if a user is allowed to access the current resource.
A voter could vote no, another could vote yes, and another could vote I don't know. The final decision is made from the AccessDecisionManager that will, based on how it is configured, determine if these votes will either allow the user ("Any yes allows the user" or forbid him ("Any no is strict").
I think that this is the basis of what you should understand, to me, about the Security component. Keep in mind that it can be very tricky to understand first, especially for the Authentication part.
Last but not least, I highly recommend you to read this whole chapter : Here !. It is the key and your bible if you want to understand what's happening inside this tricky but awesome component.
Now, for your login issue : what would be useful for you is to check how to create your custom Listener (see the authenticating part of my answer) in order to create your own business logic of "how do I authenticate my user based on the current request". Your form would be an entry point of a firewall zone that would be then pointing to this firewall zone. This listener would check if the information provided by your form is inside the request, and then create the Token. Then, you would have a custom way to authenticate your token thanks to the information you provide.
(Sorry for my english !)
I have tried to search the net, but haven't found any example of best practice url naming convention for the following requests.
My API allows user to log into the system, retrieve secure token which can be used to access private data over the HTTPS.
So there following features will be support by API :
Auth. Simple authentification. /api/auth will be used to log into the system first time and get token in response or refresh expired token if required.
View profile data (first name,last name, phone number ....). What is the best way to form url for this resource. I have several ideas : /api/users/me/profile OR /api/users/{id}/profile. In the first case our client (REST API consumer) doesn't need to know exact ID of user, when user tries to access this resource it checks if token is valid,if passed user name exists and tied to the token, and than just returns data based on this information. In the second case we have to know exact ID of user, of course this ID can be returned in response to the auth.
Also other methods like /api/user/me/orderlist, /api/user/me/someuserspecificinfo.
What about making an order. I have read the if you need to create new resource you have to use POST, if update - PUT. How my url should look like ?
/api/neworder (parameters in post body), /api/user/neworder , /api/orders (just with post method)
.......
Please suggest what the commonly used naming convention for such resources
Your resource URIs should be more or less constant, and the HTTP verb determines what action is performed, eg:
/api/orders:
GET: list orders
POST: create new order
/api/orders/{order-id};
GET: retrieve info about an order
POST: create an order with the specified ID
PUT: modify an order
DELETE: remove an order
Putting function-like names in your REST API like /api/user/neworder is a great way to attract the ire of REST fundamentalists.
My api has this routes defined:
GET test.com/api/v1/users
POST test.com/api/v1/users
PUT test.com/api/v1/users/{id}
GET test.com/api/v1/users/{id}
DELETE test.com/api/v1/users/{id}
Also, i'm using OAuth2 Password authentication so these resources are only available once authenticated.
My point is.. keeping RESTFULL API principles, how should I aproach limiting PUT AND DELETE methods to the actual resource owner?
Basically I don't want anybody except the owner to be able to edit his information.
You have implemented the authentication part of your system, meaning your application knows who the users are. Now you need to devise an authorization sub-system, meaning what your users have access to.
As your question is tagged PHP and Laravel, a quick Google search for laravel authorization brings results such as this:
https://github.com/machuga/authority-l4
or
http://laravel.io/forum/02-03-2014-authority-controller-authorization-library-cancan-port
This should be a good starting point.
This is usually solved by appending a custom header, with a secret message, identifying the request as valid. I do not have any source on this I'm afraid.
Usually headers beginning with an X - discarding them from being parsed by other parties. X-Your-Secret for example.
I'm wanting to make an API quickly, following REST principles - for a simple web application I've built. The first place the API will be used is to interface with an iPhone app. The API only needs handle a few basic calls, but all require authentication, nothing is public data.
login/authenticate user
get list of records in users group
get list again, only those that have changed (newly added or updated)
update record
So, following REST principles, would I setup the uri scheme?:
mysite.com/api/auth (POST?)
mysite.com/api/users (GET)
mysite.com/api/update (POST?)
and the responses will be in XML to begin with, JSON too later.
On the website, users login with email and password. Should I let them get a 'token' on their profile page to pass with every api request? (would make the stand alone '/auth' URI resource redundant).
Best practices for structuring the response xml? It seems like with REST, that you should return either 200 ok and the XML or actual proper status codes i.e. 401 etc
Any general pointers appreciated.
1- for auth, you might want to consider something like http-basic, or digest auth (note - basic in particular is insecure if not over https)
for the urls scheme:
/api/auth is not needed if you leverage basic or digest.
/api/group/groupname/ is probably more canonical
/api/update would generally be done as /api/users/username (POST) with the new data added - the resource is the user - POST is the verb
otherwise, basically your API looks sane, much depends on whether groups are hierarchical, and users must live in a group - if so, your urls should reflect that and be navigable.
2- status codes should reflect status - 200 for OK, 401 for access denied, 404 for not found, 500 for error processing. Generally you should only return an XML record if you have a good request
Authentication in an API always works by sending some authenticating token in the request header. I.e., even when using the separate /auth login approach, you would return some token, possibly a cookie, back to the user, which would need to be send together with every request.
HTTP already provides a dedicated header for this purpose though: Authorization.
The most basic HTTP "Authorization" is HTTP Basic access authentication:
Authorization : Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Digest Authentication is another, more secure, scheme. You can use this header field for any form of authentication you want though, even your custom implemented authentication.
Authorization : MyCustomAuthentication foo:bar:n293f82jn398n9r
You could send the aforementioned login token in this field. Or you could employ a request signing scheme, in which certain request fields are hashed together with the password of the user, basically sending the password without sending the password (similar to digest authentication, but you can use something better than md5). That obliterates the separate login step. AWS employs this method.
For an API in general, make good use of the HTTP status codes to indicate what is happening.
You're generally on the right track. The URI scheme should be based around the idea of resources and you should use an appropriate method to do the work.
So, GET to retrieve info. POST (Or maybe PUT) to create/change resources. DELETE for well, delete. And HEAD to check the metadata.
The structure of your XML doesn't have much to do with a RESTful API, assuming it doesn't require state management. That said, you have the right idea. If it's a good request, return the desired XML (for a GET request) and status code 200. If it's a bad request, you may also, and in some cases needed to, return something other than just the status code. Basically, get familiar with the HTTP spec and follow it as closely as possible.