1717use Illuminate \Contracts \Cookie \QueueingFactory as CookieJar ;
1818use Illuminate \Contracts \Events \Dispatcher ;
1919use Illuminate \Contracts \Session \Session ;
20+ use Illuminate \Support \Arr ;
2021use Illuminate \Support \Facades \Hash ;
2122use Illuminate \Support \Str ;
2223use Illuminate \Support \Traits \Macroable ;
@@ -374,6 +375,34 @@ public function attempt(array $credentials = [], $remember = false)
374375 return false ;
375376 }
376377
378+ /**
379+ * Attempt to authenticate a user with credentials and additional callbacks.
380+ *
381+ * @param array $credentials
382+ * @param array|callable $callbacks
383+ * @param false $remember
384+ * @return bool
385+ */
386+ public function attemptWhen (array $ credentials = [], $ callbacks = null , $ remember = false )
387+ {
388+ $ this ->fireAttemptEvent ($ credentials , $ remember );
389+
390+ $ this ->lastAttempted = $ user = $ this ->provider ->retrieveByCredentials ($ credentials );
391+
392+ // This method does the exact same thing as attempt, but also executes callbacks after
393+ // the user is retrieved and validated. If one of the callbacks returns falsy we do
394+ // not login the user. Instead, we will fail the specific authentication attempt.
395+ if ($ this ->hasValidCredentials ($ user , $ credentials ) && $ this ->shouldLogin ($ callbacks , $ user )) {
396+ $ this ->login ($ user , $ remember );
397+
398+ return true ;
399+ }
400+
401+ $ this ->fireFailedEvent ($ user , $ credentials );
402+
403+ return false ;
404+ }
405+
377406 /**
378407 * Determine if the user matches the credentials.
379408 *
@@ -392,6 +421,24 @@ protected function hasValidCredentials($user, $credentials)
392421 return $ validated ;
393422 }
394423
424+ /**
425+ * Determine if the user should login by executing the given callbacks.
426+ *
427+ * @param array|callable|null $callbacks
428+ * @param \Illuminate\Contracts\Auth\Authenticatable $user
429+ * @return bool
430+ */
431+ protected function shouldLogin ($ callbacks , AuthenticatableContract $ user )
432+ {
433+ foreach (Arr::wrap ($ callbacks ) as $ callback ) {
434+ if (! $ callback ($ user , $ this )) {
435+ return false ;
436+ }
437+ }
438+
439+ return true ;
440+ }
441+
395442 /**
396443 * Log the given user ID into the application.
397444 *
0 commit comments