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');
Related
I am building a weather app with laravel(almost finished) and i decided to implement the frontend with react/redux/react-router and use laravel from api calls. The only thing that i decided to leave the same is my custom laravel auth implementation with routes and views. However, i struggle to find a secure way to pass my Auth::user object after login in order to store on redux. I have 2 options:
1) After login and before render the main jsx, to make an axios request to specific route in order to return the Auth::user like:
in routes.php
Route::post('/auth/user' ,function(){
return response()->json(['user'=>auth()->user()]);
})->middleware('auth');
in js
axios.post('/auth/user').then((res)=>{console.log(res.data.user)}).catch((e)=>{console.log(e)})
2) pass Auth::user with blade, catch it with getAttribute, save it to redux and instantly remove from DOM:
<div id="app" data-usr="{{ auth()->user() }}"></div>
However neither of them seem to me like a secure way to pass this kind of data. Can anyone tell me his opinion about this or figure me with a better solution?
Thanks a lot.
I would create a Class to represent the user with just the vital information I need to show on the front-end.
So instead of passing auth->user() to the front, you can inject it into a decorator and generate a simpler user class with just the methods you wish to display.
Thankfully i found a solution with API TOKEN implementation built-in with Laravel. Also i destroy token after logout and recreate it in login, so nobody can use it with other services to collect data if he is not signed in
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
I've been working for a while on an API-including project. I have an ApiUsersController which handles all user's actions for the API and another API controller.
But I need to ensure that this is secure, so I've created an apiKey() function which detects if the user sending the request to my API has the right credentials.
My question now is where should I put the apiKey() function in order to make use of it in any API controller?
Any API security recommendations are also very welcomed.
Thank you in advance!
My question now is where should I put the apiKey() function in order
to make use of it in any Api controller?
Easy to answer, the correct place is an authentication adapter. Ceeram has already created a token (that's what you're using) adapter for CakePHP. See this link here.
If you want a more secure way you should go for OAuth as suggested by Dave. But instead of using a specific OAuth plugin I would go for Opauth for CakePHP, it comes with an OAuth Strategy adapter.
Also instead of creating API controllers I would use prefix routing and share most of the code for the API actions with the normal actions in a model. This way it can be reused very easy and no need to duplicate work.
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;