1851 lines
55 KiB
Markdown
1851 lines
55 KiB
Markdown
# 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`
|
||
|