Skip to content

Commit

Permalink
allow granular authentication customization
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Sep 10, 2020
1 parent 6c36b08 commit cd8b6aa
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 14 deletions.
37 changes: 37 additions & 0 deletions src/Actions/AttemptToAuthenticate.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,50 @@ public function __construct(StatefulGuard $guard, LoginRateLimiter $limiter)
*/
public function handle($request, $next)
{
if (Fortify::$authenticateUsingCallback) {
return $this->handleUsingCustomCallback($request, $next);
}

if ($this->guard->attempt(
$request->only(Fortify::username(), 'password'),
$request->filled('remember'))
) {
return $next($request);
}

$this->throwFailedAuthenticationException($request);
}

/**
* Attempt to authenticate using a custom callback.
*
* @param \Illuminate\Http\Request $request
* @param callable $next
* @return mixed
*/
protected function handleUsingCustomCallback($request, $next)
{
$user = call_user_func(Fortify::$authenticateUsingCallback, $request);

if (! $user) {
return $this->throwFailedAuthenticationException();
}

$this->guard->login($user, $request->filled('remember'));

return $next($request);
}

/**
* Throw a failed authentication validation exception.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
protected function throwFailedAuthenticationException($request)
{
$this->limiter->increment($request);

throw ValidationException::withMessages([
Expand Down
40 changes: 30 additions & 10 deletions src/Actions/RedirectIfTwoFactorAuthenticatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ public function __construct(StatefulGuard $guard, LoginRateLimiter $limiter)
*/
public function handle($request, $next)
{
$user = $this->validateCredentials(
$request, $this->guard->getProvider()->getModel()
);
$user = $this->validateCredentials($request);

if (optional($user)->two_factor_secret &&
in_array(TwoFactorAuthenticatable::class, class_uses_recursive($user))) {
Expand All @@ -63,22 +61,44 @@ public function handle($request, $next)
* Attempt to validate the incoming credentials.
*
* @param \Illuminate\Http\Request $request
* @param string $model
* @return mixed
*/
protected function validateCredentials($request, $model)
protected function validateCredentials($request)
{
if (Fortify::$authenticateUsingCallback) {
return tap(call_user_func(Fortify::$authenticateUsingCallback, $request), function ($user) {
if (! $user) {
$this->throwFailedAuthenticationException($request);
}
});
}

$model = $this->guard->getProvider()->getModel();

return tap($model::where(Fortify::username(), $request->{Fortify::username()})->first(), function ($user) use ($request) {
if (! $user || ! Hash::check($request->password, $user->password)) {
$this->limiter->increment($request);

throw ValidationException::withMessages([
Fortify::username() => [trans('auth.failed')],
]);
$this->throwFailedAuthenticationException($request);
}
});
}

/**
* Throw a failed authentication validation exception.
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
protected function throwFailedAuthenticationException($request)
{
$this->limiter->increment($request);

throw ValidationException::withMessages([
Fortify::username() => [trans('auth.failed')],
]);
}

/**
* Get the two factor authentication enabled response.
*
Expand Down
33 changes: 31 additions & 2 deletions src/Fortify.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ class Fortify
*
* @var callable|null
*/
public static $loginThroughCallback;
public static $authenticateThroughCallback;

/**
* The callback that is repsonsible for validating authentication credentials, if applicable.
*
* @var callable|null
*/
public static $authenticateUsingCallback;

/**
* Indicates if Fortify routes will be registered.
Expand Down Expand Up @@ -151,7 +158,29 @@ public static function requestPasswordResetLinkView($view)
*/
public static function loginThrough(callable $callback)
{
static::$loginThroughCallback = $callback;
return static::authenticateThrough($callback);
}

/**
* Register a callback that is responsible for building the authentication pipeline array.
*
* @param callable $callback
* @return void
*/
public static function authenticateThrough(callable $callback)
{
static::$authenticateThroughCallback = $callback;
}

/**
* Register a callback that is responsible for validating incoming authentication credentials.
*
* @param callable $callback
* @return void
*/
public static function authenticateUsing(callable $callback)
{
static::$authenticateUsingCallback = $callback;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Http/Controllers/AuthenticatedSessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ public function store(LoginRequest $request)
*/
protected function loginPipeline(LoginRequest $request)
{
if (Fortify::$loginThroughCallback) {
if (Fortify::$authenticateThroughCallback) {
return (new Pipeline(app()))->send($request)->through(array_filter(
call_user_func(Fortify::$loginThroughCallback, $request)
call_user_func(Fortify::$authenticateThroughCallback, $request)
));
}

Expand Down

0 comments on commit cd8b6aa

Please sign in to comment.