Profile/account REST API naming convention - php

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.

Related

Share common authentication token between web and app

I would like to create a website and app where users can search a song and collect it into a public list (saved to a database). Therefore, I would not like to let the user authenticate himself just to add 1 song to the list. Because you need to provide a token in order to search, I've found several options:
I will save the token into the database (refresh every hour using a CRON job), and when the user wants to search, I will retrieve the code and append it client side so the request will be successful. This, of course, exposes the token, even though it can only search, it is not really safe. PHP is no option, as it has to be a website and an app
I need to let everyone log in which is very annoying
I need to make a PHP script that will receive some endpoints from the client side and will execute it server side and send the response back. This, however, does not scale really well when there are a lot of users and the rate-limiting from one IP will soon be activated.
Are there any other options I can try?
EDIT:
The songs should be searched by calling the Spotify API, not everyone has Spotify, therefore I was thinking about one token that could be shared
Less annoying but not secure:
Mobile App
First time the app is used:
Require authentication and capture the device UUID.
Store the device UUID in the database which is related to the authenticated user and also related to the user's play list.
Next time the app is used the device UUID already exists in the database so assume the related play list is the one to use.
Browser
First time the page (or after clearing cookies) is used:
Require authentication and set a long-lived cookie.
Store the cookie in the database which is related to the authenticated user and also related to the user's play list.
Next time the page is used the cookie will already exist so assume the related play list is the one to use.
If you're looking to use OAuth as a means of TLS between the server and client then each user must authenticate against the server with a request of information.
Since, I assume, this is not a public API (for anyone to access data), you only want your client app to be able to authorise such requests.
In this case, you would not need to send a 'scope' to the authentication server, simply just generate a resource token but FORCE the user to login.
Using that resource token, the client will send a second request to the resource server. Inside this request should hold the ACTION and DATA for that request and on receipt should then delete that token from the database. There is no need for a CRON job.
Client -> Authentication Server
<- Resource Token (OK)
<- Status BAD
Client -> Resource Server { Resource Token, Action, Data }
<- Status OK
<- Status BAD
Check the token exists and "in-date"
Check that the action is permitted
Check that the data is more than 1 song
Execute the insert, remove the token and return a response header
The reason you do not need a CRON job is because you should set a timeout for the token. For example, add a (TIMESTAMP) created DEFAULT CURRENT_TIMESTAMP to the database, pull the row out of the database for that token and ensure that it wasn't created n minutes ago, if it was then its void (expired) and can no longer be used.
Here is a URI example for the resource server:
/api/resource_token/action?data=
Of course, data should be a POST parameter but, for this, it was easier to show it as a GET request. It doesn't need to hold ALL the data, it could be anything like:
?song=[{"artist": "foo", "song": "bar"}]&type="json"
Using AltoRouter it would look something like this:
$router->map('GET|POST', '/api/[*:token]/[*:action]', function($resourceToken, $requestAction) {
foreach(array('Song', 'Type', 'PlaylistId') as $param)
if(!isset($_POST[$param]))
die(...Return your response header error...);
if(($token = SomeModel::getToken($resourceToken))->isValid())
SomeController->using($token)->execute($requestAction);
die(...Return your response header success...);
}, 'API');

How to get parameters in iAuthenticate class (Restler)

For my API, I have a database of items and users. API calls follow the format of
POST(GET, DELETE, etc.) http://example.com/api/items/4
When a user calls an API, I'd like to be able to get the id of the item to make sure that the user actually has permission to modify the item. I'm able to get the user ID without any problem (extracting it from the OAuth2 token), but what's the best way to get the item ID, in this case 4? I would prefer to do this in the __isAllowed() function in the iAuthenticate class to keep my code clean. Is this possible?
Although it is possible, it will complicate the process to reject the user based on the resource at the auth class level.
I always prefer to do this at the api method level, we can still throw 401 Unauthorized from the api method once we find the requested resource does not belong to the user

OAuth2 client without access token

So before I start, I'm a bit of an OAuth2 newbie, so still trying to really wrap my head around the various permission scopes and grants.
I've managed to successfully implement an OAuth2 server using the Laravel OAuth2 Server package.
The current site I'm working on will simply dogfood from the API, using the client_credentials grant type. I've managed to get this successfully working and can make API calls with the provided access token.
However, I'm wondering how I can implement an architecture similar to Instagram, Soundcloud, etc, who don't require an access_token for basic endpoints, just a client_id. How do they do this? Is this a custom grant type?
Preferably, I'd only like to start requiring an access token when accessing private resources, such as those for modifying user information, etc. As far as I'm aware, for these I'd need to use the password grant type, which isn't a problem.
OAuth has a few flows such as 2-legged or 3-legged which basically tells the developer how many requests he needs to make to the server to get the resource he wants.
For example, in a 2-legged flow you send a request with your id and secret (first request), you get back an access_token and using that token you can make other request for the resource you want (second request).
Comming back to your Instagram example, you can think at using just client_id as a 1-legged OAuth flow, because you make only one request to server to get the resource you want.
You can use such a flow for less sensitive resources, like a profile photo or user's nickname for example.
The implementation of a 1-legged flow is simple:
- If the user_id is valid and the application doesn't need user approval to access requested resource, go ahead and show the resource.
So implementing a 1-legged flow consists in checking if the client_id is valid and checking if the requested resource needs user permission. That being said, you can use 1-legged for requesting a user profile photo, but you can't use the same flow for requesting the user's private messages.
You can read more about each OAuth Flow in The OAuth Bible.
You have two different resources on your server - a) Resources that need some access checks b) Resources that are publicly accessible.
Actions on resources that need access checks should require that a user has been identified via the OAuth header in the request. In the context of Laravel - this would be a route with the 'before' key specified as Oauth.
Actions that do not need access could glean context about what user is relevant by building your routes to accept an argument that gives you context about the user. Let's say that you have a profile that a user can see without any sort of access. Your API endpoint for a JSON representation of that could be /api/profile/[user_id], where [user_id] is the ID of the user profile you would like to see. For these routes where you do not care about access, you can leave off the oauth before filter in your route declaration.

PHP REST API Logic

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 :)

Building a simple RESTful api

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.

Categories