I think i have a rough idea of what a guard does. for some reason there's not really much write-up about it online. I saw this line of code in someones middleware
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
and i don't understand what it does. i understand that there two types of inbuilt guards-web and api and web is the default guard. What does the "Guard" inside the construct do? and how does the $auth variable come into play?.
here's the pic of the full code
The Guard class is used for authentication i.e. logging a user in, checking to see if there is an authenticated user, retrieving the authenticated user, logging them out etc.
I'd say the most common way to access this information (going off the docs and various tutorials) is by using either the Auth Facade or the auth() helper function. With either approach you will have access to the same methods e.g.
auth()->user() or Auth::user() will return the current authenticated user.
auth()->id() or Auth::id() will return the current authenticated user's id.
auth()->check() or Auth::check() will tell you if the current user is logged in or not.
etc.
In either case (using auth()-> or Auth::) you're going to accessing methods on the Guard class.
Laravel also has something called the Service Container which is a way for you to be able to have dependency injection. This is essentially where you can get an instance of a class automatically without having to do something like new ClassName(). This might not seem like a big deal at first but if you have a class that needs to be passed different variable and classes to its constructor you can set this up in the container so you don't have to worry about it. Another benefit might be that you want to use the same instance of a class rather than creating a new one each time which is something that can be done with the container as well.
Now, some people prefer to use dependency injection instead of using Facades or helper functions (see here for more information). With the case in your example you're injecting the Guard class so that you can access it as a property on the class rather than using the Facade or helper function. There isn't more to it than that.
Related
I was looking through the built in auth controllers and I noticed they use something called "Guards". Up until now whenever I made my own logins/register forms I never touched these and would usually just do things like:
Auth::attempt()
without any type of guard. I've tried looking up what exactly it is but I couldn't really find any information on it, could someone explain to me what the purpose of the guards are?
They're the definition of how the system should store and retrieve information about your users.
You can find the configuration in your config/auth.php file. A web guard is the traditional cookie store - so that web guard instructs Laravel to store and retrieve session information the classic way. The API guard, on the other hand, uses tokens. So you would use the API guard if you want to authenticate users and requests using an API token in the header (bearer) or query parameter.
You can also create your own guard if you wish, and there's also this good introductory blog post on the topic by Matt Stauffer.
Since I had the same question and the other answers did not provide me the information I was looking for (they explain perfectly what a guard does, but not why you should ever worry about calling its methods), I will provide another answer.
I was also unsure about the difference between methods provided by the auth() helper and methods provided by the guard itself auth()->guard(), as they seemed to do the same.
A quick dd(auth()) reveals that it returns an instance of AuthManager. So we can look up that class in the source code: On the bottom of AuthManager.php there is a __call() magic method which forwards all undefined calls to its own guard() method.
public function __call($method, $parameters)
{
return $this->guard()->{$method}(...$parameters);
}
This clearly shows us that the methods of auth() and auth()->guard() not only seem to do the same, but are exactly the same. So as long as the default guard should be used, an additional ->guard() can be omitted with peace of mind.
A guard is a way of supplying the logic that is used to identify authenticated users. Laravel provides different guards like sessions and tokens. The session guard maintains the state of the user in each request by cookies, and on the other hand, the token guard authenticates the user by checking a valid token in every request.
Guard role is to authenticate routes
Web guard will authenticate web routes
Api guard will authenticate api routes.
For other user types e.g Admin guard will authenticate admin routes and so on.
Would it be advisable, if i am doing authentication in a middleware and adding some data to the \Illuminate\Http\Request $request object and using that data in the controller by injecting \Illuminate\Http\Request $request into the controller method?
The reason, the app needs to make a database call to find out if the credentials are valid and if it is, it returns something like a primary key that i use in subsequent db operations.
At the moment, everything is done in the controller. If i were to use a separate middleware for authentication, can i bind the data that my controller needs to the request object if the middleware check passes? if so, how should i go about doing it?
Inspiration - Expressjs way of binding and passing data along the request through a stack of middlewares / routes.
I dont understand - why dont you just use the Laravel authenticator?
You say:
The reason, the app needs to make a database call to find out if the credentials are valid and if it is, it returns something like a primary key that i use in subsequent db operations.
And that is exactly what the Laravel Authenticator does?
Then in your controller you can just do
`auth()->user()` // gives you the user record
`auth()->id()` // user_id from the DB
`auth()->user()->name` // gives you the `name` column off the record. You can change it to anything.
Edit: Meanwhile - you can still use the Laravel Authenticator package whilst using a legacy system for authentication. In your middleware you can do something like this:
if (doLegacyCheckHere()) {
Auth::loginUsingId(1);
}
This means you can do your check via the neo4j graph db - and if it returns true that the user is authenticated correctly - then you just log them into the Laravel system yourself.
Yes, that is probably a good way to do it, as the build-in Laravel Authentication system works the same way: you can access a logged in user via $request::user(). See http://laravel.com/docs/5.0/authentication#retrieving-the-authenticated-user
It is ok to validate auth in the middleware. In my application we are using the same functionality to check if user sends the right access_code to access to the API methods. Even Laravel itself handles protected routes by Authenticate middleware.
The problem is, there is no silver bullet of how or where to store additional data.
One method is to store this in the user's session.
The second is to use Illuminate\Foundation\Application class itself. You can inject it into your middleware __constructor() and use it to save your data. Application class extends Container class that implements ArrayAccess interface that allows you to access to it's properties like it is an array. That allows you not only to get variables from the Application but to store them too. Not the best way though the simplest.
public function __construct(\Illuminate\Foundation\Application $app)
{
$app['_foo'] = 'bar';
}
There are more such hacks but these are the simplest.
I am just about three days old in laravel, yesterday I tried creating an authentications system using eloquent, so without looking I deleted the default User model, and then I tried creating my own from what I had read from the documentation. After setting up every thing as I had studied and understood, I tried running my app, but whenever I enter the correct username and password I get this error
Argument 1 passed to Illuminate\Auth\EloquentUserProvider::validateCredentials()
must be an instance of Illuminate\Auth\UserInterface, instance of User given, called in dir
I did not know what the EloquentUserProvider was or where it was even coming from. My original model looked like this
class User extends Eloquent {}
I battled with this error for the whole day (no exaggeration), But today I found out from this SO Can't authenticate user in laravel that it was because I had not implemented some interface, so they linked me to https://github.com/laravel/laravel/blob/master/app/models/User.php where I copied the default model I initially deleted.
I used the documentation almost through out my learning process, and no where in the documention for authentication and for eloquent did they mention that we are suppose to implement these interface for us to be able to use Auth::attempt() method, my question now is how then do we (newbies) know what to implement and what not to implement, or what any of these interfaces even do.
This is simple. It's a laravel's requirement. The User model is generated by default for you. If you do not need to implement the interface's methods, just add them empty in your User class.
And of course, in your case, what to extend or implement will be shown as errors on startup. Reading them carefully can give you all the asnwers.
Also, if you want to use different User Authentication features, or extend the existing ones, you can look some info here in the docs
I like to spend time studying how frameworks are coded in attempt to better my code.
As far as I know the Scope Resolution Operator in PHP calls a function in a class as a static function, meaning that you do not have access to '$this' because the class hasn't been instantiated.
But when I started reading up how the Laravel 4 Auth works I noticed that the documentation tells you to use Auth::check() or Auth::user() to retrieve information, yet the code in those functions is using many '$this' statements.
Can anyone explain to me how they are able to retrieve the instance properties if the functions are being called as static methods?
Here is the link to the github raw file for Laravel Auth
https://raw.githubusercontent.com/illuminate/auth/master/Guard.php
Laravel uses a development pattern known as Facades and Inversion of Control (IoC) in order to take static calls to some objects (the 'Facade') and retrieve an actual instance of an object (from the IoC container) to call the method on.
Put another way, when you do Auth::check() and Auth::user() those seemingly static calls get replaced with actual object instances from within the IoC container, so Auth::check() becomes $auth->check() with $auth being derived from within the container.
This allows you to 1) Write Auth::check() instead of $auth = new Auth; $auth->check() and 2) let the IoC container do all of the dirty work around actually creating the instance you want, so if implementation details change later you don't have to rewrite any code that uses the Auth class.
See this documentation page about facades and this question about IoC in general for more information.
As a side note, the Auth facade referred to in Auth::check() et al is actually this class: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Facades/Auth.php
It's a Fcade.
When you're calling Auth::{anything}, you're actually calling Illuminate\Support\Facades\Auth. The static method is only used as an entry point.
This is a simplified version of the Facade design pattern:
http://sourcemaking.com/design_patterns/facade/php
While testing roles in my application I found the function isGranted of the SecurityContext. It works great but now I need to check the roles of a user that is not the current user so isGranted doesn't work for me.
I've been looking and I found the function hasRole of the user, the problem is that this function doesn't look in the hierarchy tree of Symfony and it just looks in the roles assigned to the user.
So, Is there a function that looks for a role of a user looking in the hierarchy tree like isGranted do for the current user?
EDIT
I found this solution:
How to use the AccessDecisionManager in Symfony2 for authorization of arbitrary users?
I implemented it and it works, the problem is that it needs the ContainerBuilder and I would prefer a different approach.
Any Idea?
Basically AFAIK SecurityContext work with Symfony\Component\Security\Core\Authentication\Token\TokenInterface from where can fetch current user using getUser method.
If user token is not authenticated then isGranted trying authenticate user token first and then use class called AccessDecisionManager which basically iterate over voters objects and call them (and can use different strategies for that) One of called voters is RoleHierarchyVoter which use Symfony\Component\Security\Core\Role\RoleHierarchy.
So answer to your question:
I think that is no such function like isGranted for other users (or do not know about any), but you can write own service which allow to that using security.role_hierarchy (just notice that is private service).
BTW hasRole probably should be sufficient most of the time, so maybe you should think about what do you want to do ;)