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
Related
I previously taught my self php, but now I want to migrate to a framework I have chosen Lavarel currently.
I have been able to do this directly in plain php, but I am having problem re-implementing it in the newest version of Lavarel.
I created a controller based on the google Calendar API.
The first step is authenticating, and that is where my problem exists.
I do the setup, display the google permissions, and accept the permissions. At this point Google does a callback.
If I route the callback to GoogleCalendar#callback then it calls the constructor again re-displaying the google authentication request in an infinite loop.
If I route the callback to another class it gets the tokens, but then the wrong class has the token. I have placed the token in a database, but how do I transfer execution back to the GoogleCalendar class.
return redirect()->action('GoogleCalendar#part2',['code' => $input['code']]);
This fails, even though the class and function exist I get an error message like they don't.
I was able to store the token in the user table, however, I need to pass control back to the GoogleCalendar controller with an operative $client string.
I've only used Laravel's Requests for POST methods. In the documentation, all examples use POST methods, but the class does offer a method to check which HTTP verb is used.
Is it advisable to use a Request when the method is GET if there is a need to validate a query, path, or authorize a user? If I were to use requests for GET methods (specifically to authorize a user), what would be the point of using auth middleware?
I believe you are mixing 2 different terminologies together.
First of all, you must not use GET method to authorize anyone. That is totally against the law... (Unless you really want to tamper your user's privacy etc.)
Secondly, Using POST and GET methods is simply your decision. For purposes like, Authenticating users, or say making payments etc, you must make a POST request, but for purposes like Search, Pagination or Verification By Token... GET method must be preferred.
Using Laravel's Route method, you can pass as many parameters as you want to a function and not use GET method at all.
To simply put this, using either is totally your call.
Lastly, Auth Middleware is used for checking if the user who is accessing that page has a session active or not. If you login someone, you call the Laravel's auth()->login() method, which makes a session for that particular user and you can thereby get that user's info on any other view/method by auth()->user() as long as he/she is logged in. If you want, you can make your own middleware and check from the GET requests if the user's email and password are valid or not, you can do that well. But then again, like I said, this shouldn't be happening... Let's not mix up things.
I hope I have made your concepts clear and answered your question correctly. Since you've not really explained using examples, I feel this is where you were really getting confused. Please comment if you have any further doubts. :)
If you want to check the permission at your GET request you can use middleware at routes.
You can create many middleware as you want
Example:
Route::get('admin/profile', function () {
//
})->middleware('auth');
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.
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 :)
I have an auth resource in my library that is correctly returning one of the various statuses based on whether or not the user exists, wrong password, or correct password. I'm trying to get the identity into my controllers though. So in the auth resource I return the status along with user. What needs to happen in my controllers then? I've already handled logging in and redirecting to a different controller. I'm trying to do something like $this->auth->authenticate() and $this->auth->getIdentity() to make sure that they are already authenticated and that they have an identity. What do I need to do so that the identity gets passed around to all of the controllers that I call auth in predispatch?
Also, is there something in Zend Auth that keeps track of how many attempts at logging in have been made?
If use stored the indentiy with Zend_Auth you can get it everywhere you want with:
Zend_Auth::getInstance()->getIdentity()
see also Matthews Tutorial on Zend_Auth
Accessing the Zend_Auth singleton will work, but if you want to get the exact values returned by your resource, put something like this in your controller:
$auth = $this->getInvokeArg('bootstrap')->auth;