Laravel makes implementing authentication very simple. In fact, almost everything is configured for you out of the box. The authentication configuration file is located at config/auth.php
, which contains several well documented options for tweaking the behavior of the authentication services.
At its core, Laravel's authentication facilities are made up of "guards" and "providers". Guards define how users are authenticated for each request. For example, Laravel ships with a session
guard which maintains state using session storage and cookies.
Providers define how users are retrieved from your persistent storage. Laravel ships with support for retrieving users using Eloquent and the database query builder. However, you are free to define additional providers as needed for your application.
Don't worry if this all sounds confusing now! Many applications will never need to modify the default authentication configuration.
Want to get started fast? Install Laravel Jetstream in a fresh Laravel application. After migrating your database, navigate your browser to /register
or any other URL that is assigned to your application. Jetstream will take care of scaffolding your entire authentication system!
By default, Laravel includes an App\Models\User
Eloquent model in your app/Models
directory. This model may be used with the default Eloquent authentication driver. If your application is not using Eloquent, you may use the database
authentication driver which uses the Laravel query builder.
When building the database schema for the App\Models\User
model, make sure the password column is at least 60 characters in length. Maintaining the default string column length of 255 characters would be a good choice.
Also, you should verify that your users
(or equivalent) table contains a nullable, string remember_token
column of 100 characters. This column will be used to store a token for users that select the "remember me" option when logging into your application.
Laravel offers several packages related to authentication. Before continuing, we'll review the general authentication ecosystem in Laravel and discuss each package's intended purpose.
First, consider how authentication works. When using a web browser, a user will provide their username and password via a login form. If these credentials are correct, the application will store information about the authenticated user in the user's session. A cookie issued to the browser contains the session ID so that subsequent requests to the application can associate the user with the correct session. After the session cookie is received, the application will retrieve the session data based on the session ID, note that the authentication information has been stored in the session, and will consider the user as "authenticated".
When a remote service needs to authenticate to access an API, cookies are not typically used because there is no web browser. Instead, the remote service sends an API token to the API on each request. The application may validate the incoming token against a table of valid API tokens and "authenticate" the request as being performed by the user associated with that API token.
Laravel includes built-in authentication and session services which are typically accessed via the Auth
and Session
facades. These features provide cookie based authentication for requests that are initiated from web browsers. They provide methods that allow you to verify a user's credentials and authenticate the user. In addition, these services will automatically store the proper data in the user's session and issue the proper session cookie. A discussion of how to use these services is contained within this documentation.
Jetstream / Fortify
As discussed in this documentation, you can interact with these authentication services manually to build your application's own authentication layer. However, to help you get started more quickly, we have released free packages that provide robust, modern scaffolding of the entire authentication layer. These packages are Laravel Jetstream and Laravel Fortify.
Laravel Fortify is a headless authentication backend for Laravel that implements many of the features found in this documentation, including cookie-based authentication as well as other features such as two-factor authentication and email verification. Laravel Jetstream is a UI that consumes and exposes Fortify's authentication services with a beautiful, modern UI powered by Tailwind CSS, Laravel Livewire, and / or Inertia.js. Laravel Jetstream, in addition to offering browser-based cookie authentication, includes built-in integration with Laravel Sanctum to offer API token authentication. Laravel's API authentication offerings are discussed below.
Laravel provides two optional packages to assist you in managing API tokens and authenticating requests made with API tokens: Passport and Sanctum. Please note that these libraries and Laravel's built-in cookie based authentication libraries are not mutually exclusive. These libraries primarily focus on API token authentication while the built-in authentication services focus on cookie based browser authentication. Many applications will use both Laravel's built-in cookie based authentication services and one of Laravel's API authentication packages.
Passport
Passport is an OAuth2 authentication provider, offering a variety of OAuth2 "grant types" which allow you to issue various types of tokens. In general, this is a robust and complex package for API authentication. However, most applications do not require the complex features offered by the OAuth2 spec, which can be confusing for both users and developers. In addition, developers have been historically confused about how to authenticate SPA applications or mobile applications using OAuth2 authentication providers like Passport.
Sanctum
In response to the complexity of OAuth2 and developer confusion, we set out to build a simpler, more streamlined authentication package that could handle both first-party web requests from a web browser and API requests via tokens. This goal was realized with the release of Laravel Sanctum, which should be considered the preferred and recommended authentication package for applications that will be offering a first-party web UI in addition to an API, or will be powered by a single-page application that exists separately from the backend Laravel application, or applications that offer a mobile client.
Laravel Sanctum is a hybrid web / API authentication package that can manage your application's entire authentication process. This is possible because when Sanctum based applications receive a request, Sanctum will first determine if the request includes a session cookie that references an authenticated session. Sanctum accomplishes this by calling Laravel's built-in authentication services which we discussed earlier. If the request is not being authenticated via a session cookie, Sanctum will inspect the request for an API token. If an API token is present, Sanctum will authenticate the request using that token. To learn more about this process, please consult Sanctum's "how it works" documentation.
Laravel Sanctum is the API package we have chosen to include with the Laravel Jetstream authentication scaffolding because we believe it is the best fit for the majority of web application's authentication needs.
In summary, if your application will be accessed using a browser, your application will use Laravel's built-in authentication services.
Next, if your application offers an API, you will choose between Passport or Sanctum to provide API token authentication for your application. In general, Sanctum should be preferred when possible since it is a simple, complete solution for API authentication, SPA authentication, and mobile authentication, including support for "scopes" or "abilities".
Passport may be chosen when your application absolutely needs all of the features provided by the OAuth2 specification.
And, if you would like to get started quickly, we are pleased to recommend Laravel Jetstream as a quick way to start a new Laravel application that already uses our preferred authentication stack of Laravel's built-in authentication services and Laravel Sanctum.
This portion of the documentation discusses authenticating users via the Laravel Jetstream package, which includes UI scaffolding to help you get started quickly. If you would like to integrate with Laravel's authentication systems directly, check out the documentation on manually authenticating users.
Laravel's laravel/jetstream
package provides a quick way to scaffold all of the routes, views, and other backend logic needed for authentication using a few simple commands:
composer require laravel/jetstream // Install Jetstream with the Livewire stack... php artisan jetstream:install livewire // Install Jetstream with the Inertia stack... php artisan jetstream:install inertia
This command should be used on fresh applications and will install a layout view, registration and login views, as well as routes for all authentication end-points. A /dashboard
route will also be generated to handle post-login requests to your application's dashboard.
If you are starting a brand new application and would like to include the authentication scaffolding, you may use the --jet
directive when creating your application via the Laravel Installer. This command will create a new application with all of the authentication scaffolding compiled and installed:
laravel new kitetail --jet
To learn more about Jetstream, please visit the official Jetstream documentation.
As mentioned in the previous section, the laravel/jetstream
package's php artisan jetstream:install
command will create all of the views you need for authentication and place them in the resources/views/auth
directory.
Jetstream will also create a resources/views/layouts
directory containing a base layout for your application. All of these views use the Tailwind CSS framework, but you are free to customize them however you wish.
Now that your application has been scaffolded for authentication, you are ready to register and authenticate! You may simply access your application in a browser since Jetstream's authentication controllers already contain the logic to authenticate existing users and store new users in the database.
When a user is successfully authenticated, they will typically be redirected to the /home
URI. You can customize the post-authentication redirect path using the HOME
constant defined in your RouteServiceProvider
:
public const HOME = '/home';
When using Laravel Jetstream, the Jetstream installation process will change the value of the HOME
constant to /dashboard
.
While handling an incoming request, you may access the authenticated user via the Auth
facade:
use Illuminate\Support\Facades\Auth; // Get the currently authenticated user... $user = Auth::user(); // Get the currently authenticated user's ID... $id = Auth::id();
Alternatively, once a user is authenticated, you may access the authenticated user via an Illuminate\Http\Request
instance. Remember, type-hinted classes will automatically be injected into your controller methods. By type-hinting the Illuminate\Http\Request
object, you may gain convenient access to the authenticated user from any controller method in your application:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class FlightController extends Controller { /** * Get a list of all available flights. * * @param Request $request * @return Response */ public function update(Request $request) { // $request->user() returns an instance of the authenticated user... } }
To determine if the user is already logged into your application, you may use the check
method on the Auth
facade, which will return true
if the user is authenticated:
use Illuminate\Support\Facades\Auth; if (Auth::check()) { // The user is logged in... }
Even though it is possible to determine if a user is authenticated using the
check
method, you will typically use a middleware to verify that the user is authenticated before allowing the user access to certain routes / controllers. To learn more about this, check out the documentation on protecting routes.
Route middleware can be used to only allow authenticated users to access a given route. Laravel ships with an auth
middleware, which references the Illuminate\Auth\Middleware\Authenticate
class. Since this middleware is already registered in your HTTP kernel, all you need to do is attach the middleware to a route definition:
Route::get('flights', function () { // Only authenticated users may enter... })->middleware('auth');
When the auth
middleware detects an unauthorized user, it will redirect the user to the login
named route. You may modify this behavior by updating the redirectTo
function in your app/Http/Middleware/Authenticate.php
file:
/** * Get the path the user should be redirected to. * * @param \Illuminate\Http\Request $request * @return string */ protected function redirectTo($request) { return route('login'); }
When attaching the auth
middleware to a route, you may also specify which guard should be used to authenticate the user. The guard specified should correspond to one of the keys in the guards
array of your auth.php
configuration file:
Route::get('flights', function () { // Only authenticated users may enter... })->middleware('auth:api');
If you are using Laravel Jetstream, rate limiting will automatically be applied to login attempts. By default, the user will not be able to login for one minute if they fail to provide the correct credentials after several attempts. The throttling is unique to the user's username / e-mail address and their IP address.
If you would like to rate limit your own routes, check out the rate limiting documentation.
You are not required to use the authentication scaffolding included with Laravel Jetstream. If you choose to not use this scaffolding, you will need to manage user authentication using the Laravel authentication classes directly. Don't worry, it's a cinch!
We will access Laravel's authentication services via the Auth
facade, so we'll need to make sure to import the Auth
facade at the top of the class. Next, let's check out the attempt
method:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { /** * Handle an authentication attempt. * * @param \Illuminate\Http\Request $request * * @return Response */ public function authenticate(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { // Authentication passed... return redirect()->intended('dashboard'); } } }
The attempt
method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email
column. If the user is found, the hashed password stored in the database will be compared with the password
value passed to the method via the array. You should not hash the password specified as the password
value, since the framework will automatically hash the value before comparing it to the hashed password in the database. If the two hashed passwords match an authenticated session will be started for the user.
The attempt
method will return true
if authentication was successful. Otherwise, false
will be returned.
The intended
method on the redirector will redirect the user to the URL they were attempting to access before being intercepted by the authentication middleware. A fallback URI may be given to this method in case the intended destination is not available.
If you wish, you may also add extra conditions to the authentication query in addition to the user's e-mail and password. For example, we may verify that the user is marked as "active":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // The user is active, not suspended, and exists. }
In these examples,
You may specify which guard instance you would like to utilize using the guard
method on the Auth
facade. This allows you to manage authentication for separate parts of your application using entirely separate authenticatable models or user tables.
The guard name passed to the guard
method should correspond to one of the guards configured in your auth.php
configuration file:
if (Auth::guard('admin')->attempt($credentials)) { // }
To log users out of your application, you may use the logout
method on the Auth
facade. This will clear the authentication information in the user's session:
Auth::logout();
If you would like to provide "remember me" functionality in your application, you may pass a boolean value as the second argument to the attempt
method, which will keep the user authenticated indefinitely, or until they manually logout. Your users
table must include the string remember_token
column, which will be used to store the "remember me" token.
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // The user is being remembered... }
If you are "remembering" users, you may use the viaRemember
method to determine if the user was authenticated using the "remember me" cookie:
if (Auth::viaRemember()) { // }
If you need to log an existing user instance into your application, you may call the login
method with the user instance. The given object must be an implementation of the Illuminate\Contracts\Auth\Authenticatable
contract. The App\Models\User
model included with Laravel already implements this interface. This method of authentication is useful when you already have a valid user instance, such as directly after a user registers with your application:
Auth::login($user); // Login and "remember" the given user... Auth::login($user, true);
You may specify the guard instance you would like to use:
Auth::guard('admin')->login($user);
To log a user into the application by their ID, you may use the loginUsingId
method. This method accepts the primary key of the user you wish to authenticate:
Auth::loginUsingId(1); // Login and "remember" the given user... Auth::loginUsingId(1, true);
You may use the once
method to log a user into the application for a single request. No sessions or cookies will be utilized, which means this method may be helpful when building a stateless API:
if (Auth::once($credentials)) { // }
HTTP Basic Authentication provides a quick way to authenticate users of your application without setting up a dedicated "login" page. To get started, attach the auth.basic
middleware to your route. The auth.basic
middleware is included with the Laravel framework, so you do not need to define it:
Route::get('profile', function () { // Only authenticated users may enter... })->middleware('auth.basic');
Once the middleware has been attached to the route, you will automatically be prompted for credentials when accessing the route in your browser. By default, the auth.basic
middleware will use the email
column on the user record as the "username".
If you are using PHP FastCGI, HTTP Basic authentication may not work correctly out of the box. The following lines should be added to your .htaccess
file:
RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
You may also use HTTP Basic Authentication without setting a user identifier cookie in the session, which is particularly useful for API authentication. To do so, define a middleware that calls the onceBasic
method. If no response is returned by the onceBasic
method, the request may be passed further into the application:
<?php namespace App\Http\Middleware; use Illuminate\Support\Facades\Auth; class AuthenticateOnceWithBasicAuth { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, $next) { return Auth::onceBasic() ?: $next($request); } }
Next, register the route middleware and attach it to a route:
Route::get('api/user', function () { // Only authenticated users may enter... })->middleware('auth.basic.once');
To manually log users out of your application, you may use the logout
method on the Auth
facade. This will clear the authentication information in the user's session:
use Illuminate\Support\Facades\Auth; Auth::logout();
Laravel also provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device. This feature is typically utilized when a user is changing or updating their password and you would like to invalidate sessions on other devices while keeping the current device authenticated.
Before getting started, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession
middleware is present and un-commented in your app/Http/Kernel.php
class' web
middleware group:
'web' => [ // ... \Illuminate\Session\Middleware\AuthenticateSession::class, // ... ],
Then, you may use the logoutOtherDevices
method on the Auth
facade. This method requires the user to provide their current password, which your application should accept through an input form:
use Illuminate\Support\Facades\Auth; Auth::logoutOtherDevices($password);
When the logoutOtherDevices
method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by.
When using the
AuthenticateSession
middleware in combination with a custom route name for thelogin
route, you must override theunauthenticated
method on your application's exception handler to properly redirect users to your login page.
While building your application, you may occasionally have actions that should require the user to confirm their password before the action is performed. Laravel includes built-in middleware to make this process a breeze. Implementing this feature will require you to define two routes: one route to display a view asking the user to confirm their password, and one route to confirm that the password is valid and redirect the user to their intended destination.
The following documentation discusses how to integrate with Laravel's password confirmation features directly; however, if you would like to get started more quickly, the Laravel Jetstream authentication scaffolding package includes support for this feature!
After confirming their password, a user will not be asked to confirm their password again for three hours. However, you may configure the length of time before the user is re-prompted for their password by changing the value of the password_timeout
configuration value within your auth
configuration file.
First, we will define the route that is needed to display a view requesting that the user confirm their password:
Route::get('/confirm-password', function () { return view('auth.confirm-password'); })->middleware(['auth'])->name('password.confirm');
As you might expect, the view that is returned by this route should have a form containing a password
field. In addition, feel free to include text within the view that explains that the user is entering a protected area of the application and must confirm their password.
Next, we will define a route that will handle the form request from the "confirm password" view. This route will be responsible for validating the password and redirecting the user to their intended destination:
use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; Route::post('/confirm-password', function (Request $request) { if (! Hash::check($request->password, $request->user()->password)) { return back()->withErrors([ 'password' => ['The provided password does not match our records.'] ]); } $request->session()->passwordConfirmed(); return redirect()->intended(); })->middleware(['auth', 'throttle:6,1'])->name('password.confirm');
Before moving on, let's examine this route in more detail. First, the request's password
attribute is determined to actually match the authenticated user's password. If the password is valid, we need to inform Laravel's session that the user has confirmed their password. The passwordConfirmed
method will set a timestamp in the user's session that Laravel can use to determine when the user last confirmed their password. Finally, we can redirect the user to their intended destination.
You should ensure that any route that performs an action that should require recent password confirmation is assigned the password.confirm
middleware. This middleware is included with the default installation of Laravel and will automatically store the user's intended destination in the session so that the user may be redirected to that location after confirming their password. After storing the user's intended destination in the session, the middleware will redirect the user to the password.confirm
named route:
Route::get('/settings', function () { // ... })->middleware(['password.confirm']); Route::post('/settings', function () { // ... })->middleware(['password.confirm']);
You may define your own authentication guards using the extend
method on the Auth
facade. You should place this call to extend
within a service provider. Since Laravel already ships with an AuthServiceProvider
, we can place the code in that provider:
<?php namespace App\Providers; use App\Services\Auth\JwtGuard; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Auth; class AuthServiceProvider extends ServiceProvider { /** * Register any application authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Auth::extend('jwt', function ($app, $name, array $config) { // Return an instance of Illuminate\Contracts\Auth\Guard... return new JwtGuard(Auth::createUserProvider($config['provider'])); }); } }
As you can see in the example above, the callback passed to the extend
method should return an implementation of Illuminate\Contracts\Auth\Guard
. This interface contains a few methods you will need to implement to define a custom guard. Once your custom guard has been defined, you may use this guard in the guards
configuration of your auth.php
configuration file:
'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],
The simplest way to implement a custom, HTTP request based authentication system is by using the Auth::viaRequest
method. This method allows you to quickly define your authentication process using a single Closure.
To get started, call the Auth::viaRequest
method within the boot
method of your AuthServiceProvider
. The viaRequest
method accepts an authentication driver name as its first argument. This name can be any string that describes your custom guard. The second argument passed to the method should be a Closure that receives the incoming HTTP request and returns a user instance or, if authentication fails, null
:
use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; /** * Register any application authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Auth::viaRequest('custom-token', function ($request) { return User::where('token', $request->token)->first(); }); }
Once your custom authentication driver has been defined, you use it as a driver within the guards
configuration of your auth.php
configuration file:
'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ],
If you are not using a traditional relational database to store your users, you will need to extend Laravel with your own authentication user provider. We will use the provider
method on the Auth
facade to define a custom user provider:
<?php namespace App\Providers; use App\Extensions\RiakUserProvider; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Auth; class AuthServiceProvider extends ServiceProvider { /** * Register any application authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Auth::provider('riak', function ($app, array $config) { // Return an instance of Illuminate\Contracts\Auth\UserProvider... return new RiakUserProvider($app->make('riak.connection')); }); } }
After you have registered the provider using the provider
method, you may switch to the new user provider in your auth.php
configuration file. First, define a provider
that uses your new driver:
'providers' => [ 'users' => [ 'driver' => 'riak', ], ],
Finally, you may use this provider in your guards
configuration:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], ],
The Illuminate\Contracts\Auth\UserProvider
implementations are only responsible for fetching an Illuminate\Contracts\Auth\Authenticatable
implementation out of a persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.
Let's take a look at the Illuminate\Contracts\Auth\UserProvider
contract:
<?php namespace Illuminate\Contracts\Auth; interface UserProvider { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(Authenticatable $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(Authenticatable $user, array $credentials); }
The retrieveById
function typically receives a key representing the user, such as an auto-incrementing ID from a MySQL database. The Authenticatable
implementation matching the ID should be retrieved and returned by the method.
The retrieveByToken
function retrieves a user by their unique $identifier
and "remember me" $token
, stored in a field remember_token
. As with the previous method, the Authenticatable
implementation should be returned.
The updateRememberToken
method updates the $user
field remember_token
with the new $token
. A fresh token is assigned on a successful "remember me" login attempt or when the user is logging out.
The retrieveByCredentials
method receives the array of credentials passed to the Auth::attempt
method when attempting to sign into an application. The method should then "query" the underlying persistent storage for the user matching those credentials. Typically, this method will run a query with a "where" condition on $credentials['username']
. The method should then return an implementation of Authenticatable
. This method should not attempt to do any password validation or authentication.
The validateCredentials
method should compare the given $user
with the $credentials
to authenticate the user. For example, this method should probably use Hash::check
to compare the value of $user->getAuthPassword()
to the value of $credentials['password']
. This method should return true
or false
indicating on whether the password is valid.
Now that we have explored each of the methods on the UserProvider
, let's take a look at the Authenticatable
contract. Remember, the provider should return implementations of this interface from the retrieveById
, retrieveByToken
, and retrieveByCredentials
methods:
<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifierName(); public function getAuthIdentifier(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); }
This interface is simple. The getAuthIdentifierName
method should return the name of the "primary key" field of the user and the getAuthIdentifier
method should return the "primary key" of the user. In a MySQL back-end, again, this would be the auto-incrementing primary key. The getAuthPassword
should return the user's hashed password. This interface allows the authentication system to work with any User class, regardless of what ORM or storage abstraction layer you are using. By default, Laravel includes a User
class in the app
directory which implements this interface, so you may consult this class for an implementation example.
Laravel raises a variety of events during the authentication process. You may attach listeners to these events in your EventServiceProvider
:
/** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Illuminate\Auth\Events\Registered' => [ 'App\Listeners\LogRegisteredUser', ], 'Illuminate\Auth\Events\Attempting' => [ 'App\Listeners\LogAuthenticationAttempt', ], 'Illuminate\Auth\Events\Authenticated' => [ 'App\Listeners\LogAuthenticated', ], 'Illuminate\Auth\Events\Login' => [ 'App\Listeners\LogSuccessfulLogin', ], 'Illuminate\Auth\Events\Failed' => [ 'App\Listeners\LogFailedLogin', ], 'Illuminate\Auth\Events\Validated' => [ 'App\Listeners\LogValidated', ], 'Illuminate\Auth\Events\Verified' => [ 'App\Listeners\LogVerified', ], 'Illuminate\Auth\Events\Logout' => [ 'App\Listeners\LogSuccessfulLogout', ], 'Illuminate\Auth\Events\CurrentDeviceLogout' => [ 'App\Listeners\LogCurrentDeviceLogout', ], 'Illuminate\Auth\Events\OtherDeviceLogout' => [ 'App\Listeners\LogOtherDeviceLogout', ], 'Illuminate\Auth\Events\Lockout' => [ 'App\Listeners\LogLockout', ], 'Illuminate\Auth\Events\PasswordReset' => [ 'App\Listeners\LogPasswordReset', ], ];
© Taylor Otwell
Licensed under the MIT License.
Laravel is a trademark of Taylor Otwell.
https://laravel.com/docs/8.x/authentication