You can nudge your life in a new direction every day.

Building Authentication with Laravel Fortify

Submitted by admin on Sat, 02/20/2021 - 18:05

My goal here is to simply get authentication up and running the slimmest way possible but also following best practices

 

After installing Bootstrap from scratch, I wanted to build my registration, login and other authentication features but it was daunting. 

A fresh install of Laravel has the following routes:

 php artisan route:list
+--------+----------+----------+------+---------+------------+
| Domain | Method   | URI      | Name | Action  | Middleware |
+--------+----------+----------+------+---------+------------+
|        | GET|HEAD | /        |      | Closure | web        |
|        | GET|HEAD | api/user |      | Closure | api        |
|        |          |          |      |         | auth:api   |
+--------+----------+----------+------+---------+------------+

You can see all the routes currently registered by Laravel using php artisan route:list comman.

 

The starter kits have code bloat I don't want, and although I enjoy the Laravel UI project, the author considers it now outdated.

composer require laravel/fortify

This should build out all the authentication routes. This a lot to build and write so glad we used a package.

 

php artisan route:list
+--------+----------+---------------------------------+---------------------------------+---------------------------------------------------------------------------------+--------------+
| Domain | Method   | URI                             | Name                            | Action                                                                          | Middleware   |
+--------+----------+---------------------------------+---------------------------------+---------------------------------------------------------------------------------+--------------+
|        | GET|HEAD | /                               |                                 | Closure                                                                         | web          |
|        | GET|HEAD | api/user                        |                                 | Closure                                                                         | api          |
|        |          |                                 |                                 |                                                                                 | auth:api     |
|        | POST     | email/verification-notification | verification.send               | Laravel\Fortify\Http\Controllers\EmailVerificationNotificationController@store  | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        |          |                                 |                                 |                                                                                 | throttle:6,1 |
|        | GET|HEAD | email/verify                    | verification.notice             | Laravel\Fortify\Http\Controllers\EmailVerificationPromptController@__invoke     | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | GET|HEAD | email/verify/{id}/{hash}        | verification.verify             | Laravel\Fortify\Http\Controllers\VerifyEmailController@__invoke                 | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        |          |                                 |                                 |                                                                                 | signed       |
|        |          |                                 |                                 |                                                                                 | throttle:6,1 |
|        | GET|HEAD | forgot-password                 | password.request                | Laravel\Fortify\Http\Controllers\PasswordResetLinkController@create             | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | forgot-password                 | password.email                  | Laravel\Fortify\Http\Controllers\PasswordResetLinkController@store              | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | login                           |                                 | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@store           | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | GET|HEAD | login                           | login                           | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@create          | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | logout                          | logout                          | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@destroy         | web          |
|        | POST     | register                        |                                 | Laravel\Fortify\Http\Controllers\RegisteredUserController@store                 | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | GET|HEAD | register                        | register                        | Laravel\Fortify\Http\Controllers\RegisteredUserController@create                | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | reset-password                  | password.update                 | Laravel\Fortify\Http\Controllers\NewPasswordController@store                    | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | GET|HEAD | reset-password/{token}          | password.reset                  | Laravel\Fortify\Http\Controllers\NewPasswordController@create                   | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | two-factor-challenge            |                                 | Laravel\Fortify\Http\Controllers\TwoFactorAuthenticatedSessionController@store  | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | GET|HEAD | two-factor-challenge            | two-factor.login                | Laravel\Fortify\Http\Controllers\TwoFactorAuthenticatedSessionController@create | web          |
|        |          |                                 |                                 |                                                                                 | guest        |
|        | POST     | user/confirm-password           |                                 | Laravel\Fortify\Http\Controllers\ConfirmablePasswordController@store            | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | GET|HEAD | user/confirm-password           | password.confirm                | Laravel\Fortify\Http\Controllers\ConfirmablePasswordController@show             | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | GET|HEAD | user/confirmed-password-status  | password.confirmation           | Laravel\Fortify\Http\Controllers\ConfirmedPasswordStatusController@show         | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | PUT      | user/password                   | user-password.update            | Laravel\Fortify\Http\Controllers\PasswordController@update                      | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | PUT      | user/profile-information        | user-profile-information.update | Laravel\Fortify\Http\Controllers\ProfileInformationController@update            | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | POST     | user/two-factor-authentication  |                                 | Laravel\Fortify\Http\Controllers\TwoFactorAuthenticationController@store        | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | DELETE   | user/two-factor-authentication  |                                 | Laravel\Fortify\Http\Controllers\TwoFactorAuthenticationController@destroy      | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | GET|HEAD | user/two-factor-qr-code         |                                 | Laravel\Fortify\Http\Controllers\TwoFactorQrCodeController@show                 | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | GET|HEAD | user/two-factor-recovery-codes  |                                 | Laravel\Fortify\Http\Controllers\RecoveryCodeController@index                   | web          |
|        |          |                                 |                                 |                                                                                 | auth         |
|        | POST     | user/two-factor-recovery-codes  |                                 | Laravel\Fortify\Http\Controllers\RecoveryCodeController@store                   | web          |
|        |          |                                 |                                 |                                                                                 | auth
$ php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"


Copied File [/vendor/laravel/fortify/stubs/fortify.php] To [/config/fortify.php]
Copied File [/vendor/laravel/fortify/stubs/CreateNewUser.php] To [/app/Actions/Fortify/CreateNewUser.php]
Copied File [/vendor/laravel/fortify/stubs/FortifyServiceProvider.php] To [/app/Providers/FortifyServiceProvider.php]
Copied File [/vendor/laravel/fortify/stubs/PasswordValidationRules.php] To [/app/Actions/Fortify/PasswordValidationRules.php]
Copied File [/vendor/laravel/fortify/stubs/ResetUserPassword.php] To [/app/Actions/Fortify/ResetUserPassword.php]
Copied File [/vendor/laravel/fortify/stubs/UpdateUserProfileInformation.php] To [/app/Actions/Fortify/UpdateUserProfileInformation.php]
Copied File [/vendor/laravel/fortify/stubs/UpdateUserPassword.php] To [/app/Actions/Fortify/UpdateUserPassword.php]
Copied Directory [/vendor/laravel/fortify/database/migrations] To [/database/migrations]
Publishing complete.

This effectively moves code from the Fortify composer package to  your app/Actions directory.

 

Next make sure are a connected to a database

 

then run migrations

 

$ php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (158.74ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (143.70ms)
Migrating: 2014_10_12_200000_add_two_factor_columns_to_users_table
Migrated:  2014_10_12_200000_add_two_factor_columns_to_users_table (81.69ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (156.02ms)

Add to 

 

'providers' => [

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\FortifyServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

    ],

You will need to register your own views and don't forget to import the class!

 

<?php

use Illuminate\Support\Facades\Route;
use Laravel\Fortify\Fortify;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Fortify::loginView(function () {
  return view('auth.login');
});

Fortify::registerView(function () {
  return view('auth.register');
});

Fortify::RequestPasswordResetLinkView(function () {
  return view('password.update');
});

And you have to build your own views!

If you are aren't used to blade syntax this simply means there is both a login.blade.php and register.blade.php within an auth directory within a views directory.

 

resources/views/auth/login.blade.php

resources/views/auth/register.blade.php

 

Now a lot of routes were created with the Fortify package so we want to be intentional about which ones we allow

or else we will get this message everywhere

 

Illuminate\Contracts\Container\BindingResolutionException

Target [Laravel\Fortify\Contracts\RequestPasswordResetLinkViewResponse] is not instantiable.

 

e

/*
    |--------------------------------------------------------------------------
    | Features
    |--------------------------------------------------------------------------
    |
    | Some of the Fortify features are optional. You may disable the features
    | by removing them from this array. You're free to only remove some of
    | these features or you can even remove all of these if you need to.
    |
    */

    'features' => [
        Features::registration(),
        Features::resetPasswords(),
        // Features::emailVerification(),
        Features::updateProfileInformation(),
        Features::updatePasswords(),
        // Features::twoFactorAuthentication([
            //'confirmPassword' => true,
        //]),
    ],

All other routes will need to be set up in routes.php and a view created.