3

We have a web-app consuming a Laravel REST API back-end via Ang 1.6.5 front-end.

I'm looking to log 3 different authentication request outcomes: 1. Succesful authentication. 2. Valid user account, invalid password. 3. Invalid user account.

I can't seem to figure out how to go about hooking into Passport's auth process.

I've attempted with some custom Middleware, also a custom Provider. Neither worked, though it could have been the implementation.

What's the correct approach here?

Thanks.

user2977468
  • 183
  • 1
  • 13
  • The logical way to do this is to fire an event. Passport already has events for when an access or refresh token is created. I'm not familiar with the details as I haven't used Passport before, but I'd be inclined to find the controller in Passport that handles authentication attempts, write a controller that extends it and fires new events at the appropriate times, then use that in place of the default authorization controller. – Matthew Daly Nov 03 '17 at 16:55
  • I started checking out the idea of using events, but made the assumption that the events were based on the Oauth access token model. Which would mean that the events are only fired _if_ a model is accessed or modified. This behavior wouldn't occur on failed auth attempts. I'll research the controller better following your suggestion & follow up. Thanks! – user2977468 Nov 03 '17 at 17:03

3 Answers3

4

I spend my evening figuring how to do this myself in Laravel 6.

  1. I create a middleware called AccessLogMiddleware
<?php

namespace App\Http\Middleware;

use App\AccessLog;
use App\User;
use Carbon\Carbon;
use Closure;
use Illuminate\Support\Facades\Hash;


class AccessLogMiddleware
{
    public function handle($request, Closure $next)
    {
        if ($request->route()->getName() === 'passport.token'){ //this the route name of the API endpoint to get the token
            $accessLog = new AccessLog([
                'username' => $request->username,
                'ip_address' => $request->getClientIp(),
                'login_time' => Carbon::now(),
            ]);

            $user = User::query()->where([
                'username' => $request->username,
            ])->first();

            if ($user) {
                $accessLog->is_valid_username = 1;
                if (Hash::check($request->password, $user->password)){
                    $accessLog->is_valid_password = 1;
                }
            };

            $accessLog->save();
        }
        return $next($request);
    }
}
  1. Registered it to Http\Kernel
protected $routeMiddleware = [
     'access_log' => \App\Http\Middleware\AccessLogMiddleware::class,
     ....
]
  1. Apply the middleware to the Passport::routes(), in my case it's in the AuthServiceProvider:
Passport::routes(null, ['middleware' => 'access_log']);

You're all set!

Rizky Arlin
  • 373
  • 1
  • 11
  • This works perfectly for purposes of logging invalid access attempts. Unfortunately, Laravel Passport doesn't emit events for failed attempts as per documentation. – Juha Vehnia Mar 18 '23 at 19:54
1

Without re-writing the vendor source, you could look into After middleware, then just catch it before it returns. It's not the most elegant solution, but it might suffice.

Sorry this isn't a complete solution, I don't have enough points to leave a comment.

moon cheese
  • 471
  • 5
  • 15
0

Don't know if it's still relevant, but Passport emits an Event by the name of AccessTokenCreated, so you can listen to that with an EventListener.