mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-02-23 05:41:05 +01:00
Fix Authentication listeners
This commit is contained in:
parent
57d78a8675
commit
8c89c6f0ab
@ -2,8 +2,11 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Events\VisitedByProxyUser;
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
@ -17,13 +20,13 @@ class Authenticate extends Middleware
|
||||
*/
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
$proxyGuard = 'reverse-proxy-guard';
|
||||
|
||||
if (empty($guards)) {
|
||||
// Will retreive the default guard
|
||||
$guards = [null];
|
||||
} else {
|
||||
// We replace routes guard by the reverse proxy guard if necessary
|
||||
$proxyGuard = 'reverse-proxy-guard';
|
||||
|
||||
if (config('auth.defaults.guard') === $proxyGuard) {
|
||||
$guards = [$proxyGuard];
|
||||
}
|
||||
@ -35,12 +38,22 @@ protected function authenticate($request, array $guards)
|
||||
|
||||
// We now have an authenticated user so we override the locale already set
|
||||
// by the SetLanguage global middleware
|
||||
$lang = $this->auth->guard()->user()->preferences['lang'];
|
||||
$user = $this->auth->guard()->user();
|
||||
$lang = $user->preferences['lang'];
|
||||
|
||||
if (in_array($lang, config('2fauth.locales')) && ! App::isLocale($lang)) {
|
||||
App::setLocale($lang);
|
||||
}
|
||||
|
||||
// Unlike the SessionGuard, the reverse-proxy-guard does not implement an attempt()
|
||||
// method when it comes to log the user in. So auth events (Login, FailedLogin, etc..) are not
|
||||
// fired by the guard, they are not even relevant.
|
||||
// So when using the reverse-proxy-guard, we fire a VisitedByProxyUser event from here, but only
|
||||
// if the user last request is older than 15 minutes to avoid too many dispatchs
|
||||
if ($guard === $proxyGuard && (! $user->last_seen_at || Carbon::parse($user->last_seen_at) < Carbon::now()->subMinutes(15))) {
|
||||
event(new VisitedByProxyUser($user));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
use App\Notifications\FailedLoginNotification;
|
||||
use Illuminate\Auth\Events\Failed;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use TypeError;
|
||||
|
||||
class FailedLoginListener extends AbstractAccessListener
|
||||
{
|
||||
@ -35,23 +37,22 @@ class FailedLoginListener extends AbstractAccessListener
|
||||
public function handle(mixed $event) : void
|
||||
{
|
||||
if (! $event instanceof Failed) {
|
||||
return;
|
||||
throw new TypeError(self::class . '::handle(): Argument #1 ($event) must be of type ' . Failed::class);
|
||||
}
|
||||
|
||||
if ($event->user) {
|
||||
/**
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
$user = $event->user;
|
||||
$guard = $event->guard;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
$user = $event->user;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
|
||||
$log = $user->authentications()->create([
|
||||
'ip_address' => $ip,
|
||||
'user_agent' => $this->request->userAgent(),
|
||||
'login_at' => now(),
|
||||
'login_successful' => false,
|
||||
'guard' => $guard,
|
||||
'guard' => $event->guard,
|
||||
'login_method' => $this->loginMethod(),
|
||||
]);
|
||||
|
||||
@ -59,5 +60,6 @@ public function handle(mixed $event) : void
|
||||
$user->notify(new FailedLoginNotification($log));
|
||||
}
|
||||
}
|
||||
else Log::info(sprintf('%s received an event with a null $user member. Nothing has been written to the auth log', self::class));
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
use App\Notifications\SignedInWithNewDeviceNotification;
|
||||
use Illuminate\Auth\Events\Login;
|
||||
use Illuminate\Support\Carbon;
|
||||
use TypeError;
|
||||
|
||||
class LoginListener extends AbstractAccessListener
|
||||
{
|
||||
@ -36,7 +37,7 @@ class LoginListener extends AbstractAccessListener
|
||||
public function handle(mixed $event) : void
|
||||
{
|
||||
if (! $event instanceof Login) {
|
||||
return;
|
||||
throw new TypeError(self::class . '::handle(): Argument #1 ($event) must be of type ' . Login::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,16 +46,21 @@ public function handle(mixed $event) : void
|
||||
$user = $event->user;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
$userAgent = $this->request->userAgent();
|
||||
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereLoginSuccessful(true)->first();
|
||||
$known = $user->authentications()
|
||||
->whereIpAddress($ip)
|
||||
->whereUserAgent($userAgent)
|
||||
->whereLoginSuccessful(true)
|
||||
->whereGuard($event->guard)
|
||||
->whereLoginMethod($this->loginMethod())
|
||||
->first();
|
||||
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now(), true) < 1;
|
||||
$guard = $event->guard;
|
||||
|
||||
$log = $user->authentications()->create([
|
||||
'ip_address' => $ip,
|
||||
'user_agent' => $userAgent,
|
||||
'login_at' => now(),
|
||||
'login_successful' => true,
|
||||
'guard' => $guard,
|
||||
'guard' => $event->guard,
|
||||
'login_method' => $this->loginMethod(),
|
||||
]);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
use App\Models\AuthLog;
|
||||
use Illuminate\Auth\Events\Logout;
|
||||
use TypeError;
|
||||
|
||||
class LogoutListener extends AbstractAccessListener
|
||||
{
|
||||
@ -34,8 +35,8 @@ class LogoutListener extends AbstractAccessListener
|
||||
*/
|
||||
public function handle(mixed $event) : void
|
||||
{
|
||||
if (! $event instanceof Logout || $event->user == null) {
|
||||
return;
|
||||
if (! $event instanceof Logout) {
|
||||
throw new TypeError(self::class . '::handle(): Argument #1 ($event) must be of type ' . Logout::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,14 +45,20 @@ public function handle(mixed $event) : void
|
||||
$user = $event->user;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
$userAgent = $this->request->userAgent();
|
||||
$log = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereGuard($event->guard)->orderByDesc('login_at')->first();
|
||||
$guard = $event->guard;
|
||||
$log = $user->authentications()
|
||||
->whereIpAddress($ip)
|
||||
->whereUserAgent($userAgent)
|
||||
->whereGuard($event->guard)
|
||||
->whereLoginMethod($this->loginMethod())
|
||||
->orderByDesc('login_at')
|
||||
->first();
|
||||
|
||||
if (! $log) {
|
||||
$log = new AuthLog([
|
||||
'ip_address' => $ip,
|
||||
'user_agent' => $userAgent,
|
||||
'guard' => $guard,
|
||||
'ip_address' => $ip,
|
||||
'user_agent' => $userAgent,
|
||||
'guard' => $event->guard,
|
||||
'login_method' => $this->loginMethod(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
use App\Models\AuthLog;
|
||||
use Illuminate\Auth\Events\OtherDeviceLogout;
|
||||
use TypeError;
|
||||
|
||||
class OtherDeviceLogoutListener extends AbstractAccessListener
|
||||
{
|
||||
@ -35,7 +36,7 @@ class OtherDeviceLogoutListener extends AbstractAccessListener
|
||||
public function handle(mixed $event) : void
|
||||
{
|
||||
if (! $event instanceof OtherDeviceLogout) {
|
||||
return;
|
||||
throw new TypeError(self::class . '::handle(): Argument #1 ($event) must be of type ' . OtherDeviceLogout::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +45,11 @@ public function handle(mixed $event) : void
|
||||
$user = $event->user;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
$userAgent = $this->request->userAgent();
|
||||
$authLog = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->first();
|
||||
$authLog = $user->authentications()
|
||||
->whereIpAddress($ip)
|
||||
->whereUserAgent($userAgent)
|
||||
->whereLoginMethod($this->loginMethod())
|
||||
->first();
|
||||
$guard = $event->guard;
|
||||
|
||||
if (! $authLog) {
|
||||
|
@ -6,6 +6,8 @@
|
||||
use App\Extensions\RemoteUserProvider;
|
||||
use App\Notifications\SignedInWithNewDeviceNotification;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use TypeError;
|
||||
|
||||
class VisitedByProxyUserListener extends AbstractAccessListener
|
||||
{
|
||||
@ -15,7 +17,7 @@ class VisitedByProxyUserListener extends AbstractAccessListener
|
||||
public function handle(mixed $event) : void
|
||||
{
|
||||
if (! $event instanceof VisitedByProxyUser) {
|
||||
return;
|
||||
throw new TypeError(self::class . '::handle(): Argument #1 ($event) must be of type ' . VisitedByProxyUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -24,9 +26,14 @@ public function handle(mixed $event) : void
|
||||
$user = $event->user;
|
||||
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
|
||||
$userAgent = $this->request->userAgent();
|
||||
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereLoginSuccessful(true)->first();
|
||||
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now(), true) < 1;
|
||||
$guard = config('auth.defaults.guard');
|
||||
$known = $user->authentications()
|
||||
->whereIpAddress($ip)
|
||||
->whereUserAgent($userAgent)
|
||||
->whereLoginSuccessful(true)
|
||||
->whereGuard($guard)
|
||||
->first();
|
||||
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now(), true) < 1;
|
||||
|
||||
$log = $user->authentications()->create([
|
||||
'ip_address' => $ip,
|
||||
@ -34,9 +41,10 @@ public function handle(mixed $event) : void
|
||||
'login_at' => now(),
|
||||
'login_successful' => true,
|
||||
'guard' => $guard,
|
||||
'login_method' => null,
|
||||
]);
|
||||
|
||||
if (! $known && ! $newUser && ! str_ends_with($user->email, RemoteUserProvider::FAKE_REMOTE_DOMAIN) && $user->preferences['notifyOnNewAuthDevice']) {
|
||||
if (! $known && ! $newUser && Str::endsWith($user->email, RemoteUserProvider::FAKE_REMOTE_DOMAIN) && $user->preferences['notifyOnNewAuthDevice']) {
|
||||
$user->notify(new SignedInWithNewDeviceNotification($log));
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
use Illuminate\Auth\GuardHelpers;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ReverseProxyGuard implements Guard
|
||||
@ -75,13 +76,7 @@ public function user()
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->user = $this->provider->retrieveById($identifier)) {
|
||||
if ($this->user->lastLoginAt() < now()->subMinutes(15)) {
|
||||
event(new VisitedByProxyUser($this->user));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
return $this->user = $this->provider->retrieveById($identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user