Laravel 5.2 : Do something after user has logged in? - php

(I'm a beginner of Laravel)
I'm using Laravel 5.2. I have successfully enabled the Authentication; by doing the php artisan make:auth and stuffs.
So my login is working.
Now i need to do something once someone has logged in. For an simple example:
LOGIN:
Once a user has logged in, write a value into Session.
For example: $request->session()->put('UserAgent', $ClientUserAgent);
LOGOUT:
Same thing to do, once a user has logged out, delete the custom Session value.
For example: $request->session()->forget('UserAgent');
I'm not sure whether there are (things like) hooks or Event Listeners, Event Handlers, or something like that.
How can i do it please?

For newer versions of Laravel
If you are only doing something very simple then creating an event handler seems overkill to me. Laravel has an empty method included in the AuthenticatesUsers class for this purpose.
Just place the following method inside app\Http\Controllers\LoginController (overriding it):
protected function authenticated(Request $request, $user)
{
// stuff to do after user logs in
}

For the post login, you can do that by modifying App/Http/Controllers/Auth/AuthController.php
Add authenticated() into that class to override the default one:
use Illuminate\Http\Request;
protected function authenticated(Request $request, User $user) {
// put your thing in here
return redirect()->intended($this->redirectPath());
}
For the logout, add this function into the same class:
use Auth;
protected function getLogout()
{
Auth::logout();
// do something here
return redirect('/');
}

You could try setting up event listeners for the Auth events that are fired.
You can setup a listener that listens for Illuminate\Auth\Events\Login to handle what you need post login and Illuminate\Auth\Events\Logout for post logout.
Laravel Docs - Authentication - Events

Alief's Answer below works fine as expected. But as i googled through, using the Event Handlers is probably the more preferred way. (It works like custom hooks).
So without any less respects to Alief's Answer below, let me choose --> this Event Handers approach i just found out.
Thanks all with regards!

If you are testing, with authenticated(Request $request, User $user) method dont use alert inside this method to test, it will not show any result, so better put some insert query or something like that to test this method.

Why not simple check for
if(Auth::check()){
//your code
}
Make sure you include use Auth;

Related

How can we redirect a page to another if a session is not found using route in Laravel 5.3

I am using a session separately other than the default authentication sessions. If an user try to access my secured page, he should have the session set. If anyone without that session try to access means, they will be redirected to error page. I am using Laravel 5.3
The user can view the below two pages only if the session variable named 'secured_user' is set. Otherwise they will be redirect to the error page
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1');
Route::get('/secured-page2', 'ValidationController#CheckSecuredLogin_2');
The best option would be a policy.
You can create certain constrains and couple it with your models. Policies are especially suitable for changing your logic later on.
See here: Create Policy
Within you PagesPolicy, you can add this function:
public function before(User $user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
public function seeSecurePage(User $user)
{
// Your custom Code and session handling
if(session("secured_user")) return true;
return false;
}
and in your controller.
$user->can("seeSecurePage","Pages");
If "can" fails, it will automatically redirect to error 403.
P.S.: Another possibility are Gates
You should use Laravel Middlewares to achieve this, I think middlewares are made for the work you need:
First create a new middleware by running the artisan command:
php artisan make:middleware CheckSesison
Then the CheckSession would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
if ($session_value != 'YOUR_DESIRED_VALUE') {
return redirect('home');
}
return $next($request);
}
}
Now in your routes file you can use laravel's route middleware() method to implement it like this:
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1')
->middleware(CheckSession::class);
Hope this helps!
In addition to the awnser above, you could also use middleware that's used on the routes and even group them if required. It is a simple, quick and clean solution. Inside the middelware you simple check if the session you require is there and depending on the result you take any action necessary.
Laravel middleware docs

Laravel: simplest/right way to save a new step after login?

I'm having my first interaction with the core laravel code so I want to be careful not to break anything.
In my project, my users also correspond to person records (via user->person_id), so I have a get_person_from_user() function that takes the \Auth::user() (conveniently accessible anywhere) and returns the person object, so I can grab the person record for the authenticated user from any controller and pass it to a view.
The problem: there's a piece of data from the person record that I'd like to include in a nav partial in my default blade view (which gets extended by a bunch of different views), so it's the one case where I'm not going through a controller first. I'm unclear on how I can make the logged in user's person record available here. Any suggestions?
I think I need to add some step after the user logs in, to save the person record (globally? in the session?) so it's generally accessible. The login stuff happens in AuthenticatesUsers.php, and reading around it sounds like I'll want to add an override of postLogin to my AuthController.
But I tried copying that function from AuthenticatesUsers.php into my AuthController (not adding anything else to it yet), and AuthController gives me a new error when I try to log in:
ReflectionException in RouteDependencyResolverTrait.php line 81:
Class App\Http\Controllers\Auth\Request does not exist
Any advice on a good way to go about accessing the person object for the authenticated user, when I don't have a controller to pass it along?
You can setup the correct relationship on the User model to Person model.
public function person()
{
return $this->belongsTo(Person::class);
}
Then you can do:
Auth::user()->person;
For having a variable available to a particular view you can use a View Composer. (You can create and register a Service Provider and add this to the register method.) Potentially something like this:
view()->composer('someview', function ($view) {
if ($user = Auth::user()) {
$somevar = $user->person->somevar;
} else {
$somevar = null; // or some default
}
$view->with('somevar', $somevar);
});
If this view is also used in a scenario where someone doesn't have to be authed you will want to check if Auth::user() is null before trying to use the relationship.
Laravel Docs - Views - View Composers
I suggest you to use Eloquent relation
User.php
public function person()
{
return $this->belongsTo('NAMESPACE_TO_YOUR_MODEL\Person'); //also you can specify FK, more info in docs
}
then you can access Auth facade in your view
Auth::user()->person

Laravel5: Best practice for global Auth::check on

i'm new to Laravel5, i wrote a little login function for my Web, here's my home function:
public function home()
{
if (Auth::check()) {
return view('start/dashboard');
}else{
return Redirect::to('login');
}
}
The problem is that i will need Auth::check() for each function in my Controllers, so i was wondering: what's the best practice for implementing a global check to my web? i was thinking about implementing it into my header view which would be like #if(!Auth::check()) redirect to login or something ..
any ideas what's the easiest solution?
thanks
The way to achieve this is middleware.
Laravel provides one out of the box that checks if the user is authenticated. It's called auth.
In your routes.php, the easiest way would be wrapping all the routes you want to protect with:
Route::group(['middleware'=>'auth'], function($router){
Route::controller("posts","PostsController");
//or:
$router->controller("posts","PostsController");
// And so on.
});
Further reading
If you want to dive into that specific middleware, it's in app/Http/Middleware/Authenticate.php if I remember right.
You can create new middleware with php artisan make:middleware <name>. Remember to register your new middleware in app/Http/Kernel.php under the $routeMiddleware-property. Alternatively, if you want to run your middleware every single time, (almost) no exceptions, you can put it in $middleware which applies to all requests.

Laravel 5 Auth Logout not destroying session

I am using Laravel5 Auth system for my new project, I am able to use registration and login functions with out any problem but logout is not working as expected, however I get redirected to url specified at $redirectAfterLogout but it does not destroy session so even after hitting logout button I am able to see dashboard.
Does laravel has some bug in Auth system, please suggest, thanks
You have not provided any piece of code that you have used. However, the following code works:
public function getLogout(){
Auth::logout();
Session::flush();
return Redirect::to('/');
}
The Session::flush();clears all the existing sessions.
Using Laravel 5.2, I registered a listener, handled the logout event and called Session::flush as suggested above. Seemed to work pretty well. Hope this is helpful.
EventServiceProvider.php
protected $listen = [
'App\Events\SomeEvent' => [
'App\Listeners\EventListener',
],
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\ClearSessionAfterUserLogout'
],
];
ClearSessionAfterUserLogout.php
public function handle(Logout $event)
{
Session::flush();
}
I had the same issue and I tried everything, but in the end I could fix it.
My problem was that when I hit on the logout button, before that I had some http requests that weren't answered yet, so even when the user was log out, later with the response of the pending requests it got logged in again. Here is an example:
Another Request | ***********************************
Logout Request | ********************
|
Time | --|------|-------------------|------|------>
t1 t2 t3 t4
So Removing those non-answered requests worked for me. I hope that this answer helps :)
By accepting the request object in a controller action (Remember to add this after the controller namespace declaration: use Auth; ):
/**
*
* Render page
*
* #route POST /user/{user_id}/logout
*
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function logout(Request $request) {
Auth::logout();
$request->session()->flush();
}
I switched to the database session driver and used the following code in my logout action
$request->session()->getHandler()->destroy($request->session()->getId());
trait AuthenticatesUsers
public function logout(Request $request)
change this
$request->session()->regenerate();
to this
$request->session()->regenerate(true);
It seems that in the
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
The function getLogout() is never reached, hence the logout() method never fires.
In my case, in my
/app/Http/routes.php
Iinstead of this:
Route::get('auth/logout', 'Auth\AuthController#getLogout');
I changed it to:
Route::get('auth/logout', 'Auth\AuthController#logout');
In your case you are not probably reaching the logout() method. If you are using Laravel 5 builting auth mechanism then you will run AuthenticatesAndRegistersUsers trait getLogout() method which does $this->auth->logout();
Find this code edit the method like below for debugging. If you see the string "Logging out" then you must be logged out. Ohterwise something is wrong with your routing and logout is just never executed.
/**
* Log the user out of the application.
*
* #return \Illuminate\Http\Response
*/
public function getLogout()
{
dd("Logging out");
$this->auth->logout();
return redirect('/');
}
I've been fighting with this, and I've come to a solution.
In short: The Laravel session reads and writes with middleware. It reads the stored session in at the start of the request, and writes any changes at the end of the request. If you make a redirect, then the current request never finishes, and the middleware write doesn't happen.
So, how to fix this? Depending on your implementation... you should return the redirect command rather than calling it directly.
return redirect($redirectAfterLogout)
I ran into a similar issue and it turned out using the 'file' driver for sessions somehow the server was creating files it could not modify later but there was no file permission warning. I switched to a redis implementation so I unfortunately can not say how to fix the file creation issue, but thought this might save someone some time.
You can simply override the logout method in AuthController.php
Here is code sample:
public function logout(){
Session::flush();
Auth::guard($this->getGuard())->logout();
return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
}
Auth()->logout();
For the newest versions.

Laravel 5 new auth: Get current user and how to implement roles?

I am currently experimenting with the new Laravel 5 and got the authentication to work (register/login).
To get the authenticated user in my controller I currently inject Guard into the controller action:
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
class ClientController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index(Guard $auth)
{
return view('client.index', ['user' => $auth->user()]);
}
...
First Question: Is this the recommended way?
Second Question: How would I go about implementing some kind of roles/permissions? Something like client.edit, client.add, ... Does Larval 5 offer some kind of convenience here?
How would I set the necessary role/permission for a route/controller action?
I am thinking that I might need to write my own middleware for that. Any suggestions on how to approach the problem?
After spending some more time on Laravel 5 I can an answer my own question:
Is injecting Guard the recommended way? No: If you need to access Auth in your view, you can do so already like this:
#if( Auth::check() )
Current user: {{ Auth::user()->name }}
#endif
This uses the Auth facade. A list of all available facades is in config/app.php under aliases:
What if I need Auth in my controller? Injecting an instance of Guard like shown in the question works, but you don't need to. You can use the Auth facade like we did in the template:
public function index()
{
if(\Auth::check() && \Auth::user()->name === 'Don') {
// Do something
}
return view('client.index');
}
Be aware that the \ is needed before the facade name since L5 is using namespaces.
I want to have permissions/roles using the new auth mechanism in L5: I implemented a lightweight permission module using the new middleware, it is called Laraguard. Check it out on Github and let me know what you think: https://github.com/cgrossde/Laraguard
UPDATE: For the sake of completeness I want to mention two more projects. They provide everything you need to save roles and permissions in the DB and work perfectly together with Laraguard or on their own:
https://github.com/caffeinated/shinobi
https://github.com/romanbican/roles
If you want make your own custom authentification, you need to keep the User model from Laravel 5 with all the dependency. After you will be able to login your user in your controller. Dont forget to put (use Auth;) after the namespace of your controller.

Categories