mpyw / scoped-auth
Apply specific scope for user authentication.
Installs: 79 066
Dependents: 0
Suggesters: 0
Security: 0
Stars: 10
Watchers: 2
Forks: 3
Open Issues: 0
pkg:composer/mpyw/scoped-auth
Requires
- php: ^8.2
- illuminate/auth: ^11.0 || ^12.0 || ^13.0
- illuminate/contracts: ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^11.0 || ^12.0 || ^13.0
Requires (Dev)
- mockery/mockery: ^1.6.12
- orchestra/testbench: *
- orchestra/testbench-core: >=9.0
- phpunit/phpunit: >=11.0
README
Apply specific scope for user authentication.
Requirements
- PHP:
^8.2 - Laravel:
^11.0 || ^12.0
Note
Older versions have outdated dependency requirements. If you cannot prepare the latest environment, please refer to past releases.
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); } }
Note
Re-submitted PR laravel/fortify#582 has been already merged, but it's not released yet at 2025-03-05. Once it's released, you can remove this workaround.
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.