I have recently started using laravel 5.2. I don't understand what's the use of guards. As I see everything that can be done with guard can easily be replaced with lot more readable middleware. Am I missing anything ?
Guard will let you to have multi authentication in your app and you we have diffrent provider even drivers(such as doctrine or eloquent). for example, you can have login with user model and an admin model in one application at the same time.
You may specify which guard instance you would like to utilize using the guard method on the Auth facade. This allows you to manage authentication for separate parts of your application using entirely separate authenticatable models or user tables.
The guard name passed to the guard method should correspond to one of the guards configured in your auth.php configuration file:
if (Auth::guard('admin')->attempt($credentials)) {
//
}
Know more about Illuminate/Contracts/Auth/Guard
Related
I'm trying to implement the new Laravel 5.3 auth:api middleware using api tokens. Since I already have a legacy users table containing an 'ApiToken' field I would like to change the TokenGuard storageKey property (and possibly also the inputKey) to "ApiToken" instead of 'api_token'. Similar to the getRememberTokenName method, I couldn't find a 'getApiTokenName' method however. Is there a way to accomplish this without altering the Laravel TokenGuard source?
You cannot override the storageKey in TokenGuard class.
But you have 2 options to solve your problem:
Create your custom guard which should be extended from TokenGuard and inside it change the 'storageKey' property. And then register your custom guard inside AuthServiceProvider as your guard and use them.
Change 'ApiToken' field in your table to snake_case.
This question already has answers here:
How can I implement an Access Control List in my Web MVC application?
(3 answers)
Closed 6 years ago.
I'm working on an MVC application with this structure:
Request
V
FrontController <-> Router
V
Controller <-> Model
V
View
I have two other components that I need to place in this structure:
Authentification: Logs the user in using the $_SESSION global variable;
RBAC: Role Based Access Control that can check if a role has access granted to a "ressource" (Controller method).
Every users can have any given number of roles (they can also have none).
Now, I need to place those two components in my applications, I need them to be able to:
If the User isn't authed and that the Request requires a authed User to be executed, the client should be redirected to a login page;
If the RBAC sees that the authed User doesn't have a role that has access granted to the required "ressource" to execute the Controller's method, the Controller's method should still be executed but with knowledge that the User did not have the permission to do so (Example: A User writes an article but doesn't have the right to publish it, so the article is saved as a draft and the User is told that a Moderator will have to publish it).
I already have a few ideas where to locate the Authentification and RBAC but I'm not sure:
Authentification could go in the FrontController or the Router;
RBAC could go in the FrontController or the Controller.
I saw someone putting the RBAC in the model but I don't understand why.
I'd like to have some insight on the subject please. Where should I put the Authentification and RBAC components?
Thank you!
In my experience, access control business logic changes as new features are added, so it pays to design flexibility and motility into your access control system. Thus, I would engineer Authentication and RBAC as separate traits, then incorporate those traits into the controller space as necessary.
As described, it sounds like the authentication trait would best be incorporated into your front controller: you know that all dependent controllers require authentication, so incorporate that check early in the life cycle to free up request sockets. If your requirements ever change to need some controllers to be ungated, you can push the trait down into specific controllers or into a base controller class.
As for RBAC, that may apply globally to all controllers as well as locally to some controllers. For example, your FrontController may query the RBAC to build the routing table, while dependent controllers would use the RBAC for their specific needs.
One thing to consider, though: you may also have some RBAC needs in the model. That is, some roles may have limited access to some fields in some models: role A can access all of model X, but role B can only read fields 1, 2, and 3 of model X. (Trust me, I have seen very, very complicated rules around roles that can see and act on what fields.)
Engineering RBAC as a controller trait may make porting to model space difficult. Thus, you may find it better to engineer RBAC as a service delegate and inject it on demand. With a well-provisioned IoC container, a service delegate is just as easy as compile-time traiting.
Finally, I'll add that you're going to want both of these under heavy test (they are important, after all). So whatever you choose, engineer so they can be tested. In my opinion, both traits and delegates are easy to test in isolation and either would be a good choice for implementing the necessary logic.
In a typical MVC application the authentication check (i.e. "if not auth, then stop and render the login page instead") is done very early in processing the request, while the business logic (i.e. "if user has this permission then this happens, otherwise that happens") is handled within the "C" (the controller).
Most frameworks have a mechanism in place for tests like the authentication check your are describing - names vary but I have often seen it called "middleware".
The role based access control is purely your implementation.
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.
Laravel's auth class requires a database in order for it to be used right?
Does that consider database coming from the server having their own authentication process ?
Cause I want to use Laravel's Auth class methods where I can distinguish if the user is logged in or not so that I can prevent them(who have logged out) from clicking the back button.
Laravel 4 by default support two authentication driver, 'Eloquent' and 'Database', refer to the file you have in your app\config\auth.php, this is set to Eloquent by default.
The Eloquent ORM itself by default tied to a table in your database, though I have seen it creating tables by itself when no tables are found (maybe someone else can clarify this).
If you are not using the Auth::attempt() then it is of best practice to call the Auth::login() or Auth::loginUsingId() in your application. However this depends on how far you want to use your own authentication method (or how much you want to use the bundled authentication, for that matter).