mpyw / scoped-auth
Apply specific scope for user authentication.
Installs: 76 617
Dependents: 0
Suggesters: 0
Security: 0
Stars: 10
Watchers: 4
Forks: 2
Open Issues: 0
Requires
- php: ^8.0
- illuminate/auth: ^9.0 || ^10.0 || ^11.0
- illuminate/contracts: ^9.0 || ^10.0 || ^11.0
- illuminate/database: ^9.0 || ^10.0 || ^11.0
- illuminate/support: ^9.0 || ^10.0 || ^11.0
Requires (Dev)
- mockery/mockery: ^1.3.3 || ^1.4.2
- orchestra/testbench: *
- orchestra/testbench-core: >=7.0
- phpunit/phpunit: >=9.5
README
Apply specific scope for user authentication.
Requirements
- PHP:
^8.0
- Laravel:
^9.0 || ^10.0
Installing
Via Composer
$ composer require mpyw/scoped-auth
For Fortify users
Warning
Default Fortify's RedirectIfTwoFactorAuthenticatable
implementation directly uses internal Model
under UserProvider
, however, the Laravel author won't be willing to fix it for whatever reason. So we need to configure Fortify like this:
CustomFortifyAuthenticator.php
<?php namespace App\Auth; use Illuminate\Http\Request; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Contracts\Auth\UserProvider; use Laravel\Fortify\Fortify; class CustomFortifyAuthenticator { private const PASSWORD_NAME = 'password'; private readonly UserProvider $provider; public function __construct(StatefulGuard $guard) { // Assert `StatefulGuard` has `getProvider()` which is not declared in the contract assert(method_exists($guard, 'getProvider')); $provider = $guard->getProvider(); assert($provider instanceof UserProvider); $this->provider = $provider; } public function __invoke(Request $request): ?Authenticatable { $user = $this->provider->retrieveByCredentials([ Fortify::username() => $request->input(Fortify::username()), ]); return $user && $this->provider->validateCredentials($user, [ self::PASSWORD_NAME => $request->input(self::PASSWORD_NAME), ]) ? $user : null; } }
AuthServiceProvider.php
<?php namespace App\Providers; use App\Auth\CustomFortifyAuthenticator; use Illuminate\Support\ServiceProvider; use Laravel\Fortify\Fortify; class AuthServiceProvider extends ServiceProvider { public function boot(CustomFortifyAuthenticator $authenticator): void { Fortify::authenticateUsing($authenticator); } }
Testing
Via PHPUnit
$ composer test
Usage
Implement AuthScopable contract on your Authenticatable Eloquent Model.
<?php namespace App; use Illuminate\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable as UserContract; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Mpyw\ScopedAuth\AuthScopable; class User extends Model implements UserContract, AuthScopable { use Authenticatable; public function scopeForAuthentication(Builder $query): Builder { return $query->where('active', 1); } }
<?php use Illuminate\Support\Facades\Auth; $user = Auth::user(); // Only include users where "active" is 1
Note that you can reuse another existing scope.
public function scopeActive(Builder $query): Builder { return $query->where('active', 1); } public function scopeForAuthentication(Builder $query): Builder { return $this->scopeActive($query); }
As a by-product, you can also run scope queries based on the standard Eloquent way.
$user = User::where('email', 'xxx@example.com')->forAuthentication()->firstOrFail();
$user = User::where('email', 'xxx@example.com')->scopes(['forAuthentication'])->firstOrFail();
Standards
Credits
License
Licensed under the MIT License. See License File for more information.