Introduction
Laravel makes implementing authentication very simple. In
fact, almost everything is configured for you out of the
box. The authentication configuration file is located at
config/auth.php
, which contains several
well documented options for tweaking the behavior of the
authentication services.
Database Considerations
By default, Laravel includes an App\User
Eloquent model in your
app
directory. This model may be used with
the default Eloquent authentication driver. If your
application is not using Eloquent, you may use the
database
authentication driver which uses
the Laravel query builder.
When building the database schema for the
App\User
model, make sure the password
column is at least 60 characters in 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
"remember me" sessions being maintained by
your application. This can be done by using
$table->rememberToken();
in a
migration.
Authentication Quickstart
Laravel ships with two authentication controllers out of
the box, which are located in the
App\Http\Controllers\Auth
namespace. The
AuthController
handles new user
registration and authentication, while the
PasswordController
contains the logic to
help existing users reset their forgotten passwords.
Each of these controllers uses a trait to include their
necessary methods. For many applications, you will not
need to modify these controllers at all.
Routing
By default, no routes are
included to point requests to the authentication
controllers. You may manually add them to your
app/Http/routes.php
file:
// Authentication routes...
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');
// Registration routes...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');
Views
Though the authentication controllers are included with
the framework, you will need to provide views that these controllers
can render. The views should be placed in the
resources/views/auth
directory. You are
free to customize these views however you wish. The
login view should be placed at
resources/views/auth/login.blade.php
, and
the registration view should be placed at
resources/views/auth/register.blade.php
.
Sample Authentication Form
<!-- resources/views/auth/login.blade.php -->
<form method="POST" action="/auth/login">
{!! csrf_field() !!}
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
Password
<input type="password" name="password" id="password">
</div>
<div>
<input type="checkbox" name="remember"> Remember Me
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
Sample Registration Form
<!-- resources/views/auth/register.blade.php -->
<form method="POST" action="/auth/register">
{!! csrf_field() !!}
<div>
Name
<input type="text" name="name" value="{{ old('name') }}">
</div>
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
Password
<input type="password" name="password">
</div>
<div>
Confirm Password
<input type="password" name="password_confirmation">
</div>
<div>
<button type="submit">Register</button>
</div>
</form>
Authenticating
Now that you have routes and views setup for the included authentication controllers, you are ready to register and authenticate new users for your application. You may simply access your defined routes in a browser. The authentication controllers already contain the logic (via their traits) to authenticate existing users and store new users in the database.
When a user is successfully authenticated, they will be
redirected to the /home
URI, which you will
need to register a route to handle. You can customize
the post-authentication redirect location by defining a
redirectPath
property on the
AuthController
:
protected $redirectPath = '/dashboard';
When a user is not successfully authenticated, they will
be redirected to the /auth/login
URI. You
can customize the failed post-authentication redirect
location by defining a loginPath
property
on the AuthController
:
protected $loginPath = '/login';
The loginPath
will not change where a user
is bounced if they try to access a protected route. That
is controlled by the
App\Http\Middleware\Authenticate
middleware's handle
method.
Customizations
To modify the form fields that are required when a new
user registers with your application, or to customize
how new user records are inserted into your database,
you may modify the AuthController
class.
This class is responsible for validating and creating
new users of your application.
The validator
method of the
AuthController
contains the validation
rules for new users of the application. You are free to
modify this method as you wish.
The create
method of the
AuthController
is responsible for creating
new App\User
records in your database using
the Eloquent ORM. You are
free to modify this method according to the needs of
your database.
Retrieving The Authenticated User
You may access the authenticated user via the
Auth
facade:
$user = Auth::user();
Alternatively, once a user is authenticated, you may
access the authenticated user via an
Illuminate\Http\Request
instance:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
/**
* Update the user's profile.
*
* @param Request $request
* @return Response
*/
public function updateProfile(Request $request)
{
if ($request->user()) {
// $request->user() returns an instance of the authenticated user...
}
}
}
Determining If The Current User Is Authenticated
To determine if the user is already logged into your
application, you may use the check
method
on the Auth
facade, which will return
true
if the user is authenticated:
if (Auth::check()) {
// The user is logged in...
}
However, you may use 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.
Protecting Routes
Route middleware can be
used to allow only authenticated users to access a given
route. Laravel ships with the auth
middleware, which is defined in
app\Http\Middleware\Authenticate.php
. All
you need to do is attach the middleware to a route
definition:
// Using A Route Closure...
Route::get('profile', ['middleware' => 'auth', function() {
// Only authenticated users may enter...
}]);
// Using A Controller...
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'ProfileController@show'
]);
Of course, if you are using controller classes, you
may call the middleware
method from the
controller's constructor instead of attaching it in the
route definition directly:
public function __construct()
{
$this->middleware('auth');
}
Authentication Throttling
If you are using Laravel's built-in
AuthController
class, the
Illuminate\Foundation\Auth\ThrottlesLogins
trait may be used to throttle login attempts to your
application. By default, the user will not be able to
login for one minute if they fail to provide the correct
credentials after several attempts. The throttling is
unique to the user's username / e-mail address and their
IP address:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
// Rest of AuthController class...
}
Manually Authenticating Users
Of course, you are not required to use the authentication controllers included with Laravel. If you choose to remove these controllers, you will need to manage user authentication using the Laravel authentication classes directly. Don't worry, it's a cinch!
We will access Laravel's authentication services via the
Auth
facade, so
we'll need to make sure to import the Auth
facade at the top of the class. Next, let's check out
the attempt
method:
<?php
namespace App\Http\Controllers;
use Auth;
use Illuminate\Routing\Controller;
class AuthController extends Controller
{
/**
* Handle an authentication attempt.
*
* @return Response
*/
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
}
The attempt
method accepts an array of key /
value pairs as its first argument. The values in the
array will be used to find the user in your database
table. So, in the example above, the user will be
retrieved by the value of the email
column.
If the user is found, the hashed password stored in the
database will be compared with the hashed
password
value passed to the method via the
array. If the two hashed passwords match an
authenticated session will be started for the user.
The attempt
method will return
true
if authentication was successful.
Otherwise, false
will be returned.
The intended
method on the redirector will
redirect the user to the URL they were attempting to
access before being caught by the authentication filter.
A fallback URI may be given to this method in case the
intended destination is not available.
If you wish, you also may add extra conditions to the authentication query in addition to the user's e-mail and password. For example, we may verify that user is marked as "active":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// The user is active, not suspended, and exists.
}
To log users out of your application, you may use the
logout
method on the Auth
facade. This will clear the authentication information
in the user's session:
Auth::logout();
Note: In these examples,
Remembering Users
If you would like to provide "remember me"
functionality in your application, you may pass a
boolean value as the second argument to the
attempt
method, which will keep the user
authenticated indefinitely, or until they manually
logout. Of course, your users
table must
include the string remember_token
column,
which will be used to store the "remember me"
token.
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}
If you are "remembering" users, you may use the
viaRemember
method to determine if the user
was authenticated using the "remember me"
cookie:
if (Auth::viaRemember()) {
//
}
Other Authentication Methods
Authenticate A User Instance
If you need to log an existing user instance into your
application, you may call the login
method
with the user instance. The given object must be an
implementation of the
Illuminate\Contracts\Auth\Authenticatable
contract. Of course, the
App\User
model included with Laravel
already implements this interface:
Auth::login($user);
Authenticate A User By ID
To log a user into the application by their ID, you may
use the loginUsingId
method. This method
simply accepts the primary key of the user you wish to
authenticate:
Auth::loginUsingId(1);
Authenticate A User Once
You may use the once
method to log a user
into the application for a single request. No sessions
or cookies will be utilized, which may be helpful when
building a stateless API. The once
method
has the same signature as the attempt
method:
if (Auth::once($credentials)) {
//
}
HTTP Basic Authentication
HTTP
Basic Authentication provides a quick way to
authenticate users of your application without setting
up a dedicated "login" page. To get started,
attach the auth.basic
middleware to your route.
The auth.basic
middleware is included with
the Laravel framework, so you do not need to define
it:
Route::get('profile', ['middleware' => 'auth.basic', function() {
// Only authenticated users may enter...
}]);
Once the middleware has been attached to the route, you
will automatically be prompted for credentials when
accessing the route in your browser. By default, the
auth.basic
middleware will use the
email
column on the user record as the
"username".
A Note On FastCGI
If you are using PHP FastCGI, HTTP Basic authentication
may not work correctly out of the box. The following
lines should be added to your .htaccess
file:
RewriteCond %{HTTP:Authorization} ^(. )$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Stateless HTTP Basic Authentication
You may also use HTTP Basic Authentication without
setting a user identifier cookie in the session, which
is particularly useful for API authentication. To do so,
define a middleware that
calls the onceBasic
method. If no response
is returned by the onceBasic
method, the
request may be passed further into the application:
<?php
namespace Illuminate\Auth\Middleware;
use Auth;
use Closure;
class AuthenticateOnceWithBasicAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return Auth::onceBasic() ?: $next($request);
}
}
Next, register the route middleware and attach it to a route:
Route::get('api/user', ['middleware' => 'auth.basic.once', function() {
// Only authenticated users may enter...
}]);
Resetting Passwords
Database Considerations
Most web applications provide a way for users to reset their forgotten passwords. Rather than forcing you to re-implement this on each application, Laravel provides convenient methods for sending password reminders and performing password resets.
To get started, verify that your App\User
model implements the
Illuminate\Contracts\Auth\CanResetPassword
contract. Of course, the App\User
model
included with the framework already implements this
interface, and uses the
Illuminate\Auth\Passwords\CanResetPassword
trait to include the methods needed to implement the
interface.
Generating The Reset Token Table Migration
Next, a table must be created to store the password reset
tokens. The migration for this table is included with
Laravel out of the box, and resides in the
database/migrations
directory. So, all you
need to do is migrate:
php artisan migrate
Routing
Laravel includes an Auth\PasswordController
that contains the logic necessary to reset user
passwords. However, you will need to define routes to
point requests to this controller:
// Password reset link request routes...
Route::get('password/email', 'Auth\PasswordController@getEmail');
Route::post('password/email', 'Auth\PasswordController@postEmail');
// Password reset routes...
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');
Views
In addition to defining the routes for the
PasswordController
, you will need to
provide views that can be returned by this controller.
Don't worry, we will provide sample views to help you
get started. Of course, you are free to style your forms
however you wish.
Sample Password Reset Link Request Form
You will need to provide an HTML view for the password
reset request form. This view should be placed at
resources/views/auth/password.blade.php
.
This form provides a single field for the user's e-mail
address, allowing them to request a password reset
link:
<!-- resources/views/auth/password.blade.php -->
<form method="POST" action="/password/email">
{!! csrf_field() !!}
@if (count($errors) > 0)
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
<button type="submit">
Send Password Reset Link
</button>
</div>
</form>
When a user submits a request to reset their password,
they will receive an e-mail with a link that points to
the getReset
method (typically routed at
/password/reset
) of the
PasswordController
. You will need to create
a view for this e-mail at
resources/views/emails/password.blade.php
.
The view will receive the $token
variable
which contains the password reset token to match the
user to the password reset request. Here is an example
e-mail view to get you started:
<!-- resources/views/emails/password.blade.php -->
Click here to reset your password: {{ url('password/reset/'.$token) }}
Sample Password Reset Form
When the user clicks the e-mailed link to reset their
password, they will be presented with a password reset
form. This view should be placed at
resources/views/auth/reset.blade.php
.
Here is a sample password reset form to get you started:
<!-- resources/views/auth/reset.blade.php -->
<form method="POST" action="/password/reset">
{!! csrf_field() !!}
<input type="hidden" name="token" value="{{ $token }}">
@if (count($errors) > 0)
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
<div>
Email
<input type="email" name="email" value="{{ old('email') }}">
</div>
<div>
Password
<input type="password" name="password">
</div>
<div>
Confirm Password
<input type="password" name="password_confirmation">
</div>
<div>
<button type="submit">
Reset Password
</button>
</div>
</form>
After Resetting Passwords
Once you have defined the routes and views to reset your
user's passwords, you may simply access the routes in
your browser. The PasswordController
included with the framework already includes the logic
to send the password reset link e-mails as well as
update passwords in the database.
After the password is reset, the user will automatically
be logged into the application and redirected to
/home
. You can customize the post password
reset redirect location by defining a
redirectTo
property on the
PasswordController
:
protected $redirectTo = '/dashboard';
Note: By default, password reset tokens expire after one hour. You may change this via the
reminder.expire
option in yourconfig/auth.php
file.
Social Authentication
In addition to typical, form based authentication, Laravel also provides a simple, convenient way to authenticate with OAuth providers using Laravel Socialite. Socialite currently supports authentication with Facebook, Twitter, LinkedIn, Google, GitHub and Bitbucket.
To get started with Socialite, add to your
composer.json
file as a dependency:
composer require laravel/socialite
Configuration
After installing the Socialite library, register the
Laravel\Socialite\SocialiteServiceProvider
in your config/app.php
configuration
file:
'providers' => [
// Other service providers...
Laravel\Socialite\SocialiteServiceProvider::class,
],
Also, add the Socialite
facade to the
aliases
array in your app
configuration file:
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
You will also need to add credentials for the OAuth
services your application utilizes. These credentials
should be placed in your
config/services.php
configuration file, and
should use the key facebook
,
twitter
, linkedin
,
google
, github
or
bitbucket
, depending on the providers your
application requires. For example:
'github' => [
'client_id' => 'your-github-app-id',
'client_secret' => 'your-github-app-secret',
'redirect' => 'http://your-callback-url',
],
Basic Usage
Next, you are ready to authenticate users! You will need
two routes: one for redirecting the user to the OAuth
provider, and another for receiving the callback from
the provider after authentication. We will access
Socialite using the Socialite
facade:
<?php
namespace App\Http\Controllers;
use Socialite;
use Illuminate\Routing\Controller;
class AuthController extends Controller
{
/**
* Redirect the user to the GitHub authentication page.
*
* @return Response
*/
public function redirectToProvider()
{
return Socialite::driver('github')->redirect();
}
/**
* Obtain the user information from GitHub.
*
* @return Response
*/
public function handleProviderCallback()
{
$user = Socialite::driver('github')->user();
// $user->token;
}
}
The redirect
method takes care of sending
the user to the OAuth provider, while the
user
method will read the incoming request
and retrieve the user's information from the provider.
Before redirecting the user, you may also set
"scopes" on the request using the
scope
method. This method will overwrite
all existing scopes:
return Socialite::driver('github')
->scopes(['scope1', 'scope2'])->redirect();
Of course, you will need to define routes to your controller methods:
Route::get('auth/github', 'Auth\AuthController@redirectToProvider');
Route::get('auth/github/callback', 'Auth\AuthController@handleProviderCallback');
A number of OAuth providers support optional parameters
in the redirect request. To include any optional
parameters in the request, call the with
method with an associative array:
return Socialite::driver('google')
->with(['hd' => 'example.com'])->redirect();
Retrieving User Details
Once you have a user instance, you can grab a few more details about the user:
$user = Socialite::driver('github')->user();
// OAuth Two Providers
$token = $user->token;
// OAuth One Providers
$token = $user->token;
$tokenSecret = $user->tokenSecret;
// All Providers
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();
Adding Custom Authentication Drivers
If you are not using a traditional relational database to
store your users, you will need to extend Laravel with
your own authentication driver. We will use the
extend
method on the Auth
facade to define a custom driver. You should place this
call to extend
within a service provider:
<?php
namespace App\Providers;
use Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Auth::extend('riak', function($app) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new RiakUserProvider($app['riak.connection']);
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
After you have registered the driver with the
extend
method, you may switch to the new
driver in your config/auth.php
configuration file.
The User Provider Contract
The Illuminate\Contracts\Auth\UserProvider
implementations are only responsible for fetching a
Illuminate\Contracts\Auth\Authenticatable
implementation out of a persistent storage system, such
as MySQL, Riak, etc. These two interfaces allow the
Laravel authentication mechanisms to continue
functioning regardless of how the user data is stored or
what type of class is used to represent it.
Let's take a look at the
Illuminate\Contracts\Auth\UserProvider
contract:
<?php
namespace Illuminate\Contracts\Auth;
interface UserProvider {
public function retrieveById($identifier);
public function retrieveByToken($identifier, $token);
public function updateRememberToken(Authenticatable $user, $token);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);
}
The retrieveById
function typically receives
a key representing the user, such as an
auto-incrementing ID from a MySQL database. The
Authenticatable
implementation matching the
ID should be retrieved and returned by the method.
The retrieveByToken
function retrieves a
user by their unique $identifier
and
"remember me" $token
, stored in a
field remember_token
. As with the previous
method, the Authenticatable
implementation
should be returned.
The updateRememberToken
method updates the
$user
field remember_token
with the new $token
. The new token can be
either a fresh token, assigned on a successful
"remember me" login attempt, or a null when
the user is logged out.
The retrieveByCredentials
method receives
the array of credentials passed to the
Auth::attempt
method when attempting to
sign into an application. The method should then
"query" the underlying persistent storage for
the user matching those credentials. Typically, this
method will run a query with a "where"
condition on $credentials['username']
. The
method should then return an implementation of
UserInterface
. 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 might compare the
$user->getAuthPassword()
string to a
Hash::make
of
$credentials['password']
. This method
should only validate the user's credentials and return a
boolean.
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, the
provider should return implementations of this interface
from the retrieveById
and
retrieveByCredentials
methods:
<?php
namespace Illuminate\Contracts\Auth;
interface Authenticatable {
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}
This interface is simple. The
getAuthIdentifier
method should return the
"primary key" of the user. In a MySQL
back-end, again, this would be the auto-incrementing
primary key. The getAuthPassword
should
return the user's hashed password. This interface allows
the authentication system to work with any User class,
regardless of what ORM or storage abstraction layer you
are using. By default, Laravel includes a
User
class in the app
directory which implements this interface, so you may
consult this class for an implementation example.
Events
Laravel raises a variety of events during the
authentication process. You may attach listeners to
these events in your
EventServiceProvider
:
/**
* Register any other events for your application.
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
{
parent::boot($events);
// Fired on each authentication attempt...
$events->listen('auth.attempt', function ($credentials, $remember, $login) {
//
});
// Fired on successful logins...
$events->listen('auth.login', function ($user, $remember) {
//
});
// Fired on logouts...
$events->listen('auth.logout', function ($user) {
//
});
}