Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

massoud's avatar

Auth::login in an Event listener does not work

Greetings, I have a listener, which receives an email address, checks if there is a user with that email address, and logins the user if exists. I am sure the handle function of the listener is called. But Auth::login does nothing there:

public function handle(LoginEvent $event)

{

$email = $event->getEmail();

$u = User::where('email', $email )->first();

if (empty($u)) {

return redirect()->route('unexpected');

}

Auth::login($u);

}

If I run the same code in an ordinary web guard route, it logins the user. All I change is giving an existing user's email address:

$u = User::where('email', '[email protected]' )->first();

So what I am missing in the listener, which prevents Auth::login to run successfully?

thanks

0 likes
30 replies
munazzil's avatar

Your simple missing a else in the condition,

 if (empty($u)) {

 return redirect()->route('unexpected');

 }
 else
 {

 Auth::login($u);

 }
munazzil's avatar

and can check with below query,

$u = User::where('email', $request->email )->firstOrFail();
massoud's avatar

Thanks for the reply.

My query works, and I checked it.

But for some other reason, Auth::login is not working.

Maybe I am missing some trait or Facade to use.

That's what I put at the top of the file:

use Illuminate\Support\Facades\Auth;

use Illuminate\Foundation\Auth\AuthenticatesUsers;

use Aacotroneo\Saml2\Events\MyEvent;

use Illuminate\Queue\InteractsWithQueue;

use Illuminate\Contracts\Queue\ShouldQueue;

use Event;

use App\User;

chatty's avatar

are you sure your get an email from this $email = $event->getEmail();?

are you sure $u is an existing user model?

munazzil's avatar

I think you have missed this in top of your controller,

    namespace App\Http\Controllers;
bobbybouwmann's avatar

Listeners are not meant for this kind of actions. A listener can for example send an email, or queue up some job, or set some state in the database. It shouldn't be logging in your user at all. In general you would have something like this in your controller

class LoginController extends Controller
{
    public function login(Request $request)
    {
        Auth::login($user):

        event(new UserLoggedIn($user));

        return redirect()->route('some.route');
    }
}

So stuff like login and redirect should be done in the controller and not in the event/listeners

massoud's avatar

@KANE - Thanks for the reply. Yes. I used dd($u) to make sure I get the user right.

massoud's avatar

@BOBBYBOUWMANN - Thank you very much for the reply.

Actually I don't have much choice. I am using a package, which implements SAML protocol, as a service provider.

All I can do is to listen for its event, to receive an id or email address, then login the user.

If I cannot do this in the listener, what other choices I have?

thanks.

bobbybouwmann's avatar

Mmh, I looked at the package but it seems that this is the only way to handle this! It doesn't sound like the best approach, but let's see what we can do with this approach!

First of all you need to use the correct event and listener. How have you defined that in your EventServiceProvider?

massoud's avatar

@BOBBYBOUWMANN - Yes. then I ran "php artisan event:generate" to create the listener.

The listener is working.

thanks

massoud's avatar

this is in EventServiceProvider:

    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        'Aacotroneo\Saml2\Events\Saml2LoginEvent' => [
            'App\Listeners\SAMLLoginListener'
        ],
    ];

and this is the listener:

namespace App\Listeners;

use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Aacotroneo\Saml2\Events\Saml2LoginEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Event;
use App\User;

class SAMLLoginListener
{
    public function __construct()
    {
        //
    }

    public function handle(Saml2LoginEvent $event)
    {
        $user = $event->getSaml2User();
        $u = User::where('email', $user->getUserId() )->first();
        if (empty($u)) {
            return redirect()->route('unexpected');
        }
        // Now we can login the user
        Auth::login($u);
    }
}

thanks

Snapey's avatar

Your events are sync? You are not pushing it to a queue?

The thing is, the Login process is effectively setting a session for the user. When you handle the event, is it still using the browser user's session? It could well be logging in but its not affecting the right session.

munazzil's avatar

Are you sure your getting $user from the listener dd($user) and check,

   public function handle(Saml2LoginEvent $event)
{
    $user = $event->getSaml2User();
    dd($user);
    $u = User::where('email', $user->getUserId() )->first();
    if (empty($u)) {
        return redirect()->route('unexpected');
    }
 
    // Now we can login the user
    Auth::login($u);
}
massoud's avatar

@SNAPEY - thank you very much for the reply.

The code is very straightforward. I don't think the event is sync or pushed to a queue.

As I checked, in the folder "storage/framework/sessions", when I have Auth::login running in the listener, or comment it out, in both cases I have just one session file.

Snapey's avatar

I don't think the event is sync or pushed to a queue.

It must be one or the other?

When you login there should be a NEW session file as the user's session is swapped for the authenticated one.

massoud's avatar

@SNAPEY - All I see in the folder "storage/framework/sessions" is one file.

After running Auth::login in the listener, no new file is added.

So I think Auth::login does nothing there.

Snapey's avatar

id be tempted to chuck some logging in either side of the login, in particular log Auth::user()

massoud's avatar

@SNAPEY - thanks for the tip.

I put "Log::info(Auth::user());" before and after the Auth::login, and I got this.

It seems the login is working, but when I redirect to home page, the user is lost.

But it does not create any new session file.

[2019-05-31 20:00:01] local.INFO:   
[2019-05-31 20:00:01] local.INFO: {"id":1,"username":"massoud","email":"[email protected]","email_verified_at":"2019-05-26 00:00:00","verified":1,"created_at":"2019-05-25 19:09:53","updated_at":"2019-05-25 19:09:53"} 
Snapey's avatar

So I built a test

URL called a closure in web.php where I fired an event. A listener linked to the event in EventServiceProvider.

In the handle method of the listener, I manually logged a user in.

All worked fine.

The events queue was setup as sync meaning that it is dealt with in-line during the request cycle.

I'm curious how your use case differs. Is the event fired as part of a http request cycle?

massoud's avatar

@SNAPEY - Would you please share the code of your event and the listener?

thanks

Snapey's avatar
Snapey
Best Answer
Level 122

Test route

Route::get('/test', function () {

    event(new App\Events\BodgeMeIn());

    return redirect('/');
});

Event (is untouched)

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class BodgeMeIn
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

Listener

<?php

namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;
use Auth;

class listenBodgeMeIn
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle($event)
    {
        dump('event listened to');

        $u = User::find(1);

        Auth::login($u);

        dump(Auth::user());
    }
}

massoud's avatar

@SNAPEY - Thank you very much.

It helped me a lot, to find the problem.

scorpio's avatar

I have the same problem. Could you tell me how did you solve it?

massoud's avatar

in App\Http\Kernel

protected $middlewareGroups = [
        'web' => [
        ...
    ],
    'api' => [
            ...
        ],
        'saml' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
        ],

And use that middleware :

    /**
     * which middleware group to use for the saml routes
     * Laravel 5.2 will need a group which includes StartSession
     */
    'routesMiddleware' => ['saml'],
zubaer_ahammed's avatar

Found solution at last! So, Auth::login($user) was not working for me even after trying everything. (Added middlewares, etc). It worked for me after removing all dump(), var_dump(), die(), etc. from the Listener! :D

1 like
direktornd's avatar

If you're experiencing the same issue as others above, you may need to add the middleware group and then execute the following command:

php artisan route:clear

This should resolve the issue, didn't work for me before I cleared the routes.

brenninator's avatar

hey @massoud i'm trying to do this exact same thing with this package and hitting a very similar issue and have been struggling to get it working for longer than I'd like to admit.

Question(s) for you, if you dont mind and are still active on here. If its possible, could you share your files/git relevant for this? Would love to see what you have going on to get this over the finish line, if not i understand.

I had found a suggestion/tutorial/something that had me doing the login method thru a service provider (Saml2ServiceProvider.php) did you do this approach at all or is it all thru the event & listener?

Please or to participate in this conversation.