Files
laravelDocScrappy/output/12.x/authentication.md
2025-09-02 15:19:23 +02:00

1851 lines
55 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Authentication
* Introduction
* Starter Kits
* Database Considerations
* Ecosystem Overview
* Authentication Quickstart
* Install a Starter Kit
* Retrieving the Authenticated User
* Protecting Routes
* Login Throttling
* Manually Authenticating Users
* Remembering Users
* Other Authentication Methods
* HTTP Basic Authentication
* Stateless HTTP Basic Authentication
* Logging Out
* Invalidating Sessions on Other Devices
* Password Confirmation
* Configuration
* Routing
* Protecting Routes
* Adding Custom Guards
* Closure Request Guards
* Adding Custom User Providers
* The User Provider Contract
* The Authenticatable Contract
* Automatic Password Rehashing
* [Social Authentication](/docs/12.x/socialite)
* Events
## Introduction
Many web applications provide a way for their users to authenticate with the
application and "login". Implementing this feature in web applications can be
a complex and potentially risky endeavor. For this reason, Laravel strives to
give you the tools you need to implement authentication quickly, securely, and
easily.
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](/docs/12.x/eloquent)
and the database query builder. However, you are free to define additional
providers as needed for your application.
Your application's authentication configuration file is located at
`config/auth.php`. This file contains several well-documented options for
tweaking the behavior of Laravel's authentication services.
Guards and providers should not be confused with "roles" and "permissions". To
learn more about authorizing user actions via permissions, please refer to the
[authorization](/docs/12.x/authorization) documentation.
### Starter Kits
Want to get started fast? Install a [Laravel application starter
kit](/docs/12.x/starter-kits) in a fresh Laravel application. After migrating
your database, navigate your browser to `/register` or any other URL that is
assigned to your application. The starter kits will take care of scaffolding
your entire authentication system!
**Even if you choose not to use a starter kit in your final Laravel
application, installing a[starter kit](/docs/12.x/starter-kits) can be a
wonderful opportunity to learn how to implement all of Laravel's
authentication functionality in an actual Laravel project.** Since the Laravel
starter kits contain authentication controllers, routes, and views for you,
you can examine the code within these files to learn how Laravel's
authentication features may be implemented.
### Database Considerations
By default, Laravel includes an `App\Models\User` [Eloquent
model](/docs/12.x/eloquent) 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 provider which uses the Laravel query builder. If your
application is using MongoDB, check out MongoDB's official [Laravel user
authentication
documentation](https://www.mongodb.com/docs/drivers/php/laravel-
mongodb/current/user-authentication/).
When building the database schema for the `App\Models\User` model, make sure
the password column is at least 60 characters in length. Of course, the
`users` table migration that is included in new Laravel applications already
creates a column that exceeds this length.
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. Again, the default `users` table migration that
is included in new Laravel applications already contains this column.
### Ecosystem Overview
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](/docs/12.x/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 for authentication 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's Built-in Browser Authentication Services
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 authentication data in the user's session and issue the
user's session cookie. A discussion of how to use these services is contained
within this documentation.
**Application Starter Kits**
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 starter
kits](/docs/12.x/starter-kits) that provide robust, modern scaffolding of the
entire authentication layer.
#### Laravel's API Authentication Services
Laravel provides two optional packages to assist you in managing API tokens
and authenticating requests made with API tokens:
[Passport](/docs/12.x/passport) and [Sanctum](/docs/12.x/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](/docs/12.x/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 (SPA) 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"](/docs/12.x/sanctum#how-it-works) documentation.
#### Summary and Choosing Your Stack
In summary, if your application will be accessed using a browser and you are
building a monolithic Laravel application, your application will use Laravel's
built-in authentication services.
Next, if your application offers an API that will be consumed by third
parties, you will choose between [Passport](/docs/12.x/passport) or
[Sanctum](/docs/12.x/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".
If you are building a single-page application (SPA) that will be powered by a
Laravel backend, you should use [Laravel Sanctum](/docs/12.x/sanctum). When
using Sanctum, you will either need to manually implement your own backend
authentication routes or utilize [Laravel Fortify](/docs/12.x/fortify) as a
headless authentication backend service that provides routes and controllers
for features such as registration, password reset, email verification, and
more.
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
[our application starter kits](/docs/12.x/starter-kits) as a quick way to
start a new Laravel application that already uses our preferred authentication
stack of Laravel's built-in authentication services.
## Authentication Quickstart
This portion of the documentation discusses authenticating users via the
[Laravel application starter kits](/docs/12.x/starter-kits), 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.
### Install a Starter Kit
First, you should [install a Laravel application starter
kit](/docs/12.x/starter-kits). Our starter kits offer beautifully designed
starting points for incorporating authentication into your fresh Laravel
application.
### Retrieving the Authenticated User
After creating an application from a starter kit and allowing users to
register and authenticate with your application, you will often need to
interact with the currently authenticated user. While handling an incoming
request, you may access the authenticated user via the `Auth` facade's `user`
method:
1use Illuminate\Support\Facades\Auth;
2 
3// Retrieve the currently authenticated user...
4$user = Auth::user();
5 
6// Retrieve the currently authenticated user's ID...
7$id = Auth::id();
use Illuminate\Support\Facades\Auth;
// Retrieve the currently authenticated user...
$user = Auth::user();
// Retrieve 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 via the
request's `user` method:
1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\RedirectResponse;
6use Illuminate\Http\Request;
7 
8class FlightController extends Controller
9{
10 /**
11 * Update the flight information for an existing flight.
12 */
13 public function update(Request $request): RedirectResponse
14 {
15 $user = $request->user();
16 
17 // ...
18 
19 return redirect('/flights');
20 }
21}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* Update the flight information for an existing flight.
*/
public function update(Request $request): RedirectResponse
{
$user = $request->user();
// ...
return redirect('/flights');
}
}
#### Determining if the Current User is Authenticated
To determine if the user making the incoming HTTP request is authenticated,
you may use the `check` method on the `Auth` facade. This method will return
`true` if the user is authenticated:
1use Illuminate\Support\Facades\Auth;
2 
3if (Auth::check()) {
4 // The user is logged in...
5}
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](/docs/12.x/authentication#protecting-routes).
### Protecting Routes
[Route middleware](/docs/12.x/middleware) can be used to only allow
authenticated users to access a given route. Laravel ships with an `auth`
middleware, which is a [middleware alias](/docs/12.x/middleware#middleware-
aliases) for the `Illuminate\Auth\Middleware\Authenticate` class. Since this
middleware is already aliased internally by Laravel, all you need to do is
attach the middleware to a route definition:
1Route::get('/flights', function () {
2 // Only authenticated users may access this route...
3})->middleware('auth');
Route::get('/flights', function () {
// Only authenticated users may access this route...
})->middleware('auth');
#### Redirecting Unauthenticated Users
When the `auth` middleware detects an unauthenticated user, it will redirect
the user to the `login` [named route](/docs/12.x/routing#named-routes). You
may modify this behavior using the `redirectGuestsTo` method within your
application's `bootstrap/app.php` file:
1use Illuminate\Http\Request;
2 
3->withMiddleware(function (Middleware $middleware) {
4 $middleware->redirectGuestsTo('/login');
5 
6 // Using a closure...
7 $middleware->redirectGuestsTo(fn (Request $request) => route('login'));
8})
use Illuminate\Http\Request;
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo('/login');
// Using a closure...
$middleware->redirectGuestsTo(fn (Request $request) => route('login'));
})
#### Redirecting Authenticated Users
When the `guest` middleware detects an authenticated user, it will redirect
the user to the `dashboard` or `home` named route. You may modify this
behavior using the `redirectUsersTo` method within your application's
`bootstrap/app.php` file:
1use Illuminate\Http\Request;
2 
3->withMiddleware(function (Middleware $middleware) {
4 $middleware->redirectUsersTo('/panel');
5 
6 // Using a closure...
7 $middleware->redirectUsersTo(fn (Request $request) => route('panel'));
8})
use Illuminate\Http\Request;
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectUsersTo('/panel');
// Using a closure...
$middleware->redirectUsersTo(fn (Request $request) => route('panel'));
})
#### Specifying a Guard
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:
1Route::get('/flights', function () {
2 // Only authenticated users may access this route...
3})->middleware('auth:admin');
Route::get('/flights', function () {
// Only authenticated users may access this route...
})->middleware('auth:admin');
### Login Throttling
If you are using one of our [application starter kits](/docs/12.x/starter-
kits), 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 / email address and their IP address.
If you would like to rate limit other routes in your application, check out
the [rate limiting documentation](/docs/12.x/routing#rate-limiting).
## Manually Authenticating Users
You are not required to use the authentication scaffolding included with
Laravel's [application starter kits](/docs/12.x/starter-kits). If you choose
not to 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](/docs/12.x/facades), 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.
The `attempt` method is normally used to handle authentication attempts from
your application's "login" form. If authentication is successful, you should
regenerate the user's [session](/docs/12.x/session) to prevent [session
fixation](https://en.wikipedia.org/wiki/Session_fixation):
1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\Request;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Support\Facades\Auth;
8 
9class LoginController extends Controller
10{
11 /**
12 * Handle an authentication attempt.
13 */
14 public function authenticate(Request $request): RedirectResponse
15 {
16 $credentials = $request->validate([
17 'email' => ['required', 'email'],
18 'password' => ['required'],
19 ]);
20 
21 if (Auth::attempt($credentials)) {
22 $request->session()->regenerate();
23 
24 return redirect()->intended('dashboard');
25 }
26 
27 return back()->withErrors([
28 'email' => 'The provided credentials do not match our records.',
29 ])->onlyInput('email');
30 }
31}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* Handle an authentication attempt.
*/
public function authenticate(Request $request): RedirectResponse
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
])->onlyInput('email');
}
}
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 incoming request's `password`
value, since the framework will automatically hash the value before comparing
it to the hashed password in the database. An authenticated session will be
started for the user if the two hashed passwords match.
Remember, Laravel's authentication services will retrieve users from your
database based on your authentication guard's "provider" configuration. In the
default `config/auth.php` configuration file, the Eloquent user provider is
specified and it is instructed to use the `App\Models\User` model when
retrieving users. You may change these values within your configuration file
based on the needs of your application.
The `attempt` method will return `true` if authentication was successful.
Otherwise, `false` will be returned.
The `intended` method provided by Laravel's 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.
#### Specifying Additional Conditions
If you wish, you may also add extra query conditions to the authentication
query in addition to the user's email and password. To accomplish this, we may
simply add the query conditions to the array passed to the `attempt` method.
For example, we may verify that the user is marked as "active":
1if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
2 // Authentication was successful...
3}
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// Authentication was successful...
}
For complex query conditions, you may provide a closure in your array of
credentials. This closure will be invoked with the query instance, allowing
you to customize the query based on your application's needs:
1use Illuminate\Database\Eloquent\Builder;
2 
3if (Auth::attempt([
4 'email' => $email,
5 'password' => $password,
6 fn (Builder $query) => $query->has('activeSubscription'),
7])) {
8 // Authentication was successful...
9}
use Illuminate\Database\Eloquent\Builder;
if (Auth::attempt([
'email' => $email,
'password' => $password,
fn (Builder $query) => $query->has('activeSubscription'),
])) {
// Authentication was successful...
}
In these examples, `email` is not a required option, it is merely used as an
example. You should use whatever column name corresponds to a "username" in
your database table.
The `attemptWhen` method, which receives a closure as its second argument, may
be used to perform more extensive inspection of the potential user before
actually authenticating the user. The closure receives the potential user and
should return `true` or `false` to indicate if the user may be authenticated:
1if (Auth::attemptWhen([
2 'email' => $email,
3 'password' => $password,
4], function (User $user) {
5 return $user->isNotBanned();
6})) {
7 // Authentication was successful...
8}
if (Auth::attemptWhen([
'email' => $email,
'password' => $password,
], function (User $user) {
return $user->isNotBanned();
})) {
// Authentication was successful...
}
#### Accessing Specific Guard Instances
Via the `Auth` facade's `guard` method, you may specify which guard instance
you would like to utilize when authenticating the user. 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:
1if (Auth::guard('admin')->attempt($credentials)) {
2 // ...
3}
if (Auth::guard('admin')->attempt($credentials)) {
// ...
}
### Remembering Users
Many web applications provide a "remember me" checkbox on their login form. 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.
When this value is `true`, Laravel 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. The `users` table migration included with new Laravel applications
already includes this column:
1use Illuminate\Support\Facades\Auth;
2 
3if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
4 // The user is being remembered...
5}
use Illuminate\Support\Facades\Auth;
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}
If your application offers "remember me" functionality, you may use the
`viaRemember` method to determine if the currently authenticated user was
authenticated using the "remember me" cookie:
1use Illuminate\Support\Facades\Auth;
2 
3if (Auth::viaRemember()) {
4 // ...
5}
use Illuminate\Support\Facades\Auth;
if (Auth::viaRemember()) {
// ...
}
### Other Authentication Methods
#### Authenticate a User Instance
If you need to set an existing user instance as the currently authenticated
user, you may pass the user instance to the `Auth` facade's `login` method.
The given user instance must be an implementation of the
`Illuminate\Contracts\Auth\Authenticatable` [contract](/docs/12.x/contracts).
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:
1use Illuminate\Support\Facades\Auth;
2 
3Auth::login($user);
use Illuminate\Support\Facades\Auth;
Auth::login($user);
You may pass a boolean value as the second argument to the `login` method.
This value indicates if "remember me" functionality is desired for the
authenticated session. Remember, this means that the session will be
authenticated indefinitely or until the user manually logs out of the
application:
1Auth::login($user, $remember = true);
Auth::login($user, $remember = true);
If needed, you may specify an authentication guard before calling the `login`
method:
1Auth::guard('admin')->login($user);
Auth::guard('admin')->login($user);
#### Authenticate a User by ID
To authenticate a user using their database record's primary key, you may use
the `loginUsingId` method. This method accepts the primary key of the user you
wish to authenticate:
1Auth::loginUsingId(1);
Auth::loginUsingId(1);
You may pass a boolean value to the `remember` argument of the `loginUsingId`
method. This value indicates if "remember me" functionality is desired for the
authenticated session. Remember, this means that the session will be
authenticated indefinitely or until the user manually logs out of the
application:
1Auth::loginUsingId(1, remember: true);
Auth::loginUsingId(1, remember: true);
#### Authenticate a User Once
You may use the `once` method to authenticate a user with the application for
a single request. No sessions or cookies will be utilized when calling this
method, and the `Login` event will not be dispatched:
1if (Auth::once($credentials)) {
2 // ...
3}
if (Auth::once($credentials)) {
// ...
}
## HTTP Basic Authentication
[HTTP Basic
Authentication](https://en.wikipedia.org/wiki/Basic_access_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](/docs/12.x/middleware) to a route. The `auth.basic` middleware is
included with the Laravel framework, so you do not need to define it:
1Route::get('/profile', function () {
2 // Only authenticated users may access this route...
3})->middleware('auth.basic');
Route::get('/profile', function () {
// Only authenticated users may access this route...
})->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 assume the `email` column on your `users`
database table is the user's "username".
#### A Note on FastCGI
If you are using [PHP FastCGI](https://www.php.net/manual/en/install.fpm.php)
and Apache to serve your Laravel application, HTTP Basic authentication may
not work correctly. To correct these problems, the following lines may be
added to your application's `.htaccess` file:
1RewriteCond %{HTTP:Authorization} ^(.+)$
2RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
### Stateless HTTP Basic Authentication
You may also use HTTP Basic Authentication without setting a user identifier
cookie in the session. This is primarily helpful if you choose to use HTTP
Authentication to authenticate requests to your application's API. To
accomplish this, [define a middleware](/docs/12.x/middleware) that calls the
`onceBasic` method. If no response is returned by the `onceBasic` method, the
request may be passed further into the application:
1<?php
2 
3namespace App\Http\Middleware;
4 
5use Closure;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Auth;
8use Symfony\Component\HttpFoundation\Response;
9 
10class AuthenticateOnceWithBasicAuth
11{
12 /**
13 * Handle an incoming request.
14 *
15 * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
16 */
17 public function handle(Request $request, Closure $next): Response
18 {
19 return Auth::onceBasic() ?: $next($request);
20 }
21 
22}
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class AuthenticateOnceWithBasicAuth
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
return Auth::onceBasic() ?: $next($request);
}
}
Next, attach the middleware to a route:
1Route::get('/api/user', function () {
2 // Only authenticated users may access this route...
3})->middleware(AuthenticateOnceWithBasicAuth::class);
Route::get('/api/user', function () {
// Only authenticated users may access this route...
})->middleware(AuthenticateOnceWithBasicAuth::class);
## Logging Out
To manually log users out of your application, you may use the `logout` method
provided by the `Auth` facade. This will remove the authentication information
from the user's session so that subsequent requests are not authenticated.
In addition to calling the `logout` method, it is recommended that you
invalidate the user's session and regenerate their [CSRF
token](/docs/12.x/csrf). After logging the user out, you would typically
redirect the user to the root of your application:
1use Illuminate\Http\Request;
2use Illuminate\Http\RedirectResponse;
3use Illuminate\Support\Facades\Auth;
4 
5/**
6 * Log the user out of the application.
7 */
8public function logout(Request $request): RedirectResponse
9{
10 Auth::logout();
11 
12 $request->session()->invalidate();
13 
14 $request->session()->regenerateToken();
15 
16 return redirect('/');
17}
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
/**
* Log the user out of the application.
*/
public function logout(Request $request): RedirectResponse
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
### Invalidating Sessions on Other Devices
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 included on
the routes that should receive session authentication. Typically, you should
place this middleware on a route group definition so that it can be applied to
the majority of your application's routes. By default, the
`AuthenticateSession` middleware may be attached to a route using the
`auth.session` [middleware alias](/docs/12.x/middleware#middleware-aliases):
1Route::middleware(['auth', 'auth.session'])->group(function () {
2 Route::get('/', function () {
3 // ...
4 });
5});
Route::middleware(['auth', 'auth.session'])->group(function () {
Route::get('/', function () {
// ...
});
});
Then, you may use the `logoutOtherDevices` method provided by the `Auth`
facade. This method requires the user to confirm their current password, which
your application should accept through an input form:
1use Illuminate\Support\Facades\Auth;
2 
3Auth::logoutOtherDevices($currentPassword);
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
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.
## Password Confirmation
While building your application, you may occasionally have actions that should
require the user to confirm their password before the action is performed or
before the user is redirected to a sensitive area of the application. 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 another 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 application starter kits](/docs/12.x/starter-kits)
include support for this feature!
### Configuration
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 application's
`config/auth.php` configuration file.
### Routing
#### The Password Confirmation Form
First, we will define a route to display a view that requests the user to
confirm their password:
1Route::get('/confirm-password', function () {
2 return view('auth.confirm-password');
3})->middleware('auth')->name('password.confirm');
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.
#### Confirming the 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:
1use Illuminate\Http\Request;
2use Illuminate\Support\Facades\Hash;
3use Illuminate\Support\Facades\Redirect;
4 
5Route::post('/confirm-password', function (Request $request) {
6 if (! Hash::check($request->password, $request->user()->password)) {
7 return back()->withErrors([
8 'password' => ['The provided password does not match our records.']
9 ]);
10 }
11 
12 $request->session()->passwordConfirmed();
13 
14 return redirect()->intended();
15})->middleware(['auth', 'throttle:6,1']);
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;
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']);
Before moving on, let's examine this route in more detail. First, the
request's `password` field 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.
### Protecting Routes
You should ensure that any route that performs an action which requires 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](/docs/12.x/routing#named-routes):
1Route::get('/settings', function () {
2 // ...
3})->middleware(['password.confirm']);
4 
5Route::post('/settings', function () {
6 // ...
7})->middleware(['password.confirm']);
Route::get('/settings', function () {
// ...
})->middleware(['password.confirm']);
Route::post('/settings', function () {
// ...
})->middleware(['password.confirm']);
## Adding Custom Guards
You may define your own authentication guards using the `extend` method on the
`Auth` facade. You should place your call to the `extend` method within a
[service provider](/docs/12.x/providers). Since Laravel already ships with an
`AppServiceProvider`, we can place the code in that provider:
1<?php
2 
3namespace App\Providers;
4 
5use App\Services\Auth\JwtGuard;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\Facades\Auth;
8use Illuminate\Support\ServiceProvider;
9 
10class AppServiceProvider extends ServiceProvider
11{
12 // ...
13 
14 /**
15 * Bootstrap any application services.
16 */
17 public function boot(): void
18 {
19 Auth::extend('jwt', function (Application $app, string $name, array $config) {
20 // Return an instance of Illuminate\Contracts\Auth\Guard...
21 
22 return new JwtGuard(Auth::createUserProvider($config['provider']));
23 });
24 }
25}
<?php
namespace App\Providers;
use App\Services\Auth\JwtGuard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::extend('jwt', function (Application $app, string $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 reference the
guard in the `guards` configuration of your `auth.php` configuration file:
1'guards' => [
2 'api' => [
3 'driver' => 'jwt',
4 'provider' => 'users',
5 ],
6],
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
### Closure Request Guards
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 application's `AppServiceProvider`. 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`:
1use App\Models\User;
2use Illuminate\Http\Request;
3use Illuminate\Support\Facades\Auth;
4 
5/**
6 * Bootstrap any application services.
7 */
8public function boot(): void
9{
10 Auth::viaRequest('custom-token', function (Request $request) {
11 return User::where('token', (string) $request->token)->first();
12 });
13}
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::viaRequest('custom-token', function (Request $request) {
return User::where('token', (string) $request->token)->first();
});
}
Once your custom authentication driver has been defined, you may configure it
as a driver within the `guards` configuration of your `auth.php` configuration
file:
1'guards' => [
2 'api' => [
3 'driver' => 'custom-token',
4 ],
5],
'guards' => [
'api' => [
'driver' => 'custom-token',
],
],
Finally, you may reference the guard when assigning the authentication
middleware to a route:
1Route::middleware('auth:api')->group(function () {
2 // ...
3});
Route::middleware('auth:api')->group(function () {
// ...
});
## Adding Custom User Providers
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. The user provider resolver should return an implementation of
`Illuminate\Contracts\Auth\UserProvider`:
1<?php
2 
3namespace App\Providers;
4 
5use App\Extensions\MongoUserProvider;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\Facades\Auth;
8use Illuminate\Support\ServiceProvider;
9 
10class AppServiceProvider extends ServiceProvider
11{
12 // ...
13 
14 /**
15 * Bootstrap any application services.
16 */
17 public function boot(): void
18 {
19 Auth::provider('mongo', function (Application $app, array $config) {
20 // Return an instance of Illuminate\Contracts\Auth\UserProvider...
21 
22 return new MongoUserProvider($app->make('mongo.connection'));
23 });
24 }
25}
<?php
namespace App\Providers;
use App\Extensions\MongoUserProvider;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::provider('mongo', function (Application $app, array $config) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new MongoUserProvider($app->make('mongo.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:
1'providers' => [
2 'users' => [
3 'driver' => 'mongo',
4 ],
5],
'providers' => [
'users' => [
'driver' => 'mongo',
],
],
Finally, you may reference this provider in your `guards` configuration:
1'guards' => [
2 'web' => [
3 'driver' => 'session',
4 'provider' => 'users',
5 ],
6],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
### The User Provider Contract
`Illuminate\Contracts\Auth\UserProvider` implementations are responsible for
fetching an `Illuminate\Contracts\Auth\Authenticatable` implementation out of
a persistent storage system, such as MySQL, MongoDB, 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 the
authenticated user:
Let's take a look at the `Illuminate\Contracts\Auth\UserProvider` contract:
1<?php
2 
3namespace Illuminate\Contracts\Auth;
4 
5interface UserProvider
6{
7 public function retrieveById($identifier);
8 public function retrieveByToken($identifier, $token);
9 public function updateRememberToken(Authenticatable $user, $token);
10 public function retrieveByCredentials(array $credentials);
11 public function validateCredentials(Authenticatable $user, array $credentials);
12 public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
13}
<?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);
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
}
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`, typically stored in a database column like
`remember_token`. As with the previous method, the `Authenticatable`
implementation with a matching token value should be returned by this method.
The `updateRememberToken` method updates the `$user` instance's
`remember_token` with the new `$token`. A fresh token is assigned to users on
a successful "remember me" authentication 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 authenticate with 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 that searches for a user record with a
"username" matching the value of `$credentials['username']`. The method should
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 will
typically use the `Hash::check` method to compare the value of
`$user->getAuthPassword()` to the value of `$credentials['password']`. This
method should return `true` or `false` indicating whether the password is
valid.
The `rehashPasswordIfRequired` method should rehash the given `$user`'s
password if required and supported. For example, this method will typically
use the `Hash::needsRehash` method to determine if the
`$credentials['password']` value needs to be rehashed. If the password needs
to be rehashed, the method should use the `Hash::make` method to rehash the
password and update the user's record in the underlying persistent storage.
### The Authenticatable Contract
Now that we have explored each of the methods on the `UserProvider`, let's
take a look at the `Authenticatable` contract. Remember, user providers should
return implementations of this interface from the `retrieveById`,
`retrieveByToken`, and `retrieveByCredentials` methods:
1<?php
2 
3namespace Illuminate\Contracts\Auth;
4 
5interface Authenticatable
6{
7 public function getAuthIdentifierName();
8 public function getAuthIdentifier();
9 public function getAuthPasswordName();
10 public function getAuthPassword();
11 public function getRememberToken();
12 public function setRememberToken($value);
13 public function getRememberTokenName();
14}
<?php
namespace Illuminate\Contracts\Auth;
interface Authenticatable
{
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPasswordName();
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" column for the user and the `getAuthIdentifier`
method should return the "primary key" of the user. When using a MySQL back-
end, this would likely be the auto-incrementing primary key assigned to the
user record. The `getAuthPasswordName` method should return the name of the
user's password column. The `getAuthPassword` method 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 an `App\Models\User` class in the `app/Models` directory
which implements this interface.
## Automatic Password Rehashing
Laravel's default password hashing algorithm is bcrypt. The "work factor" for
bcrypt hashes can be adjusted via your application's `config/hashing.php`
configuration file or the `BCRYPT_ROUNDS` environment variable.
Typically, the bcrypt work factor should be increased over time as CPU / GPU
processing power increases. If you increase the bcrypt work factor for your
application, Laravel will gracefully and automatically rehash user passwords
as users authenticate with your application via Laravel's starter kits or when
you manually authenticate users via the `attempt` method.
Typically, automatic password rehashing should not disrupt your application;
however, you may disable this behavior by publishing the `hashing`
configuration file:
1php artisan config:publish hashing
php artisan config:publish hashing
Once the configuration file has been published, you may set the
`rehash_on_login` configuration value to `false`:
1'rehash_on_login' => false,
'rehash_on_login' => false,
## Events
Laravel dispatches a variety of [events](/docs/12.x/events) during the
authentication process. You may [define listeners](/docs/12.x/events) for any
of the following events:
Event Name
---
`Illuminate\Auth\Events\Registered`
`Illuminate\Auth\Events\Attempting`
`Illuminate\Auth\Events\Authenticated`
`Illuminate\Auth\Events\Login`
`Illuminate\Auth\Events\Failed`
`Illuminate\Auth\Events\Validated`
`Illuminate\Auth\Events\Verified`
`Illuminate\Auth\Events\Logout`
`Illuminate\Auth\Events\CurrentDeviceLogout`
`Illuminate\Auth\Events\OtherDeviceLogout`
`Illuminate\Auth\Events\Lockout`
`Illuminate\Auth\Events\PasswordReset`