Using this Laravel Custom Authentication Example Tutorial you will learn how to create Custom Login, Register, Forgot and Reset Password functionality in Laravel without auth. By default, Laravel provides us with inbuild authentication but many times we need to add our custom authentication without auth. We have added step by step Custom authentication system process same as the Laravel provides us.
Custom Login, Register, Forgot & Reset Password in Laravel
Basically, Laravel provides us with default authentication Functionality we just need to run the auth command but sometimes we need to make a custom login, register, forgot and reset the password without auth.
Step 1 – Download Laravel App
First, you need to download a fresh laravel application using the following command.
composer create-project --prefer-dist laravel/laravel laravel-custom-authentication
Next, go into your project directory:
cd laravel-custom-authentication
Step 2 – Setup Database Credentials
Next, open your .env file and update your database credentials such as database name, username, password, etc.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_custom_auth
DB_USERNAME=root
DB_PASSWORD=
After updating the database credentials run the migration command.
php artisan migrate
Step 3 – Create Registration Page Routes
Now, it’s time to start Laravel custom authentication by creating the routes. First, we will create custom registration functionality in laravel, so open your routes/web.php file and create two register routes just like below.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\RegisterController;
Route::get('/', function () {
return view('welcome');
});
Route::get('register', [RegisterController::class, 'index']);
Route::post('register', [RegisterController::class, 'store'])->name('register');
Step 4 – Create Register Controller
Now, generate a register controller using the following command. This controller file has only custom registration type code.
php artisan make:controller Auth/RegisterController
After that open app/Http/Controllers/Auth/RegisterController.php and update the following code on it.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
class RegisterController extends Controller
{
public function index()
{
return view('auth.register');
}
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
'password_confirmation' => 'required',
]);
User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
return redirect('login');
}
}
Step 5 – Create Register Blade Files
Now it’s time to create blade files for custom authentication in Laravel. First, create a new folder layouts in your resources/views directory, then create a new file app.blade.php inside the layouts folder same as below.
Next, open the resources/views/layouts/app.blade.php file and update the below code on it.
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <!-- Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> <!-- Styles --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> <div class="container"> <a class="navbar-brand" href="{{ url('/') }}"> {{ config('app.name', 'Laravel Custom Authentication') }} </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!-- Left Side Of Navbar --> <ul class="navbar-nav mr-auto"></ul> <!-- Right Side Of Navbar --> <ul class="navbar-nav ml-auto"> <!-- Authentication Links --> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> </li> @if (Route::has('register')) <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @endif @else <li class="nav-item dropdown"> <a class="dropdown-item" href="{{ route('logout') }}"> {{ __('Logout') }} </a> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> </body> </html>
After creating the layouts and app blade files, Now create a new folder auth in your resources/views directory and add a new file register.blade.php inside the auth directory.
Now, open the resources/views/auth/register.blade.php file and update the below code on it.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Register') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="form-group row">
<label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
<div class="col-md-6">
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" autocomplete="name" autofocus>
@error('name')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" autocomplete="email">
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" autocomplete="new-password">
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Register') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Step 6 – Update Login and Logout Routes
After custom registration in Laravel functionality, Now we will teach you how to use custom Login functionality in the Laravel app.
So, same as register process we will create the login routes in the routes/web.php file. We also update the logout and home routes as well.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\LoginController;
Route::get('login', [LoginController::class, 'login']);
Route::post('login', [LoginController::class, 'store'])->name('login');
Route::get('logout', [LoginController::class, 'logout'])->name('logout');
Route::get('home', [LoginController::class, 'home'])->name('home');
Step 7 – Create Login Controller
Next, generate a login controller for making the custom login functionality in laravel. So open your terminal and run the below command on it.
php artisan make:controller Auth/LoginController
After that open app/Http/Controllers/Auth/LoginController.php file and update the below code.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class LoginController extends Controller
{
public function login()
{
return view('auth.login');
}
public function store(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
return redirect()->intended('home');
}
return redirect('login')->with('error', 'Oppes! You have entered invalid credentials');
}
public function logout()
{
Auth::logout();
return redirect('login');
}
public function home()
{
return view('home');
}
}
Step 8 – Create Login View Page
Now, navigate views/auth directory and create login.blade.php file. After that open your resources/views/auth/login.blade.php file and upadte the following code on it.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
@if(session()->has('error'))
<div class="alert alert-danger">
{{ session()->get('error') }}
</div>
@endif
@if (session('message'))
{{ session('message') }}
@endif
<div class="card-body">
<form action="{{ route('login') }}" method="POST">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
</label>
</div>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
<a class="btn btn-link" href="/forget-password">
Forgot Your Password?
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
After user successfully login we need to redirected the user to home page, so you have to create a new page in your resources/views directory. So, resources/views/home.blade.php file and update the below code.
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Dashboard</div> <div class="card-body"> @if (session('status')) <div class="alert alert-success" role="alert"> {{ session('status') }} </div> @endif You are logged in! </div> </div> </div> </div> </div> @endsection
Step 9 – Create Forgot Password Route
After Custom Login and Register Functionality now we will implement the Custom Forgot Password in Laravel.
So, same you need to open routes/web.php and update the following routes on it.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\ForgotPasswordController;
Route::get('forget-password', [ForgotPasswordController::class, 'getEmail'])->name('password.request');
Route::post('forget-password', [ForgotPasswordController::class, 'postEmail'])->name('password.email');
Step 10 – Create Forgot Password Controller
Now, create a new controller named as ForgotPasswordController using the following command.
php artisan make:controller Auth/ForgotPasswordController
After successfully creating the controller file now open the app\Http\Controllers\Auth\ForgotPasswordController.php file and update the below code.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Carbon\Carbon;
class ForgotPasswordController extends Controller
{
public function getEmail()
{
return view('auth.password.email');
}
public function postEmail(Request $request)
{
$request->validate([
'email' => 'required|email|exists:users',
]);
$token = Str::random(60);
DB::table('password_resets')->insert(
['email' => $request->email, 'token' => $token, 'created_at' => Carbon::now()]
);
Mail::send('auth.password.verify', ['token' => $token], function($message) use ($request) {
$message->from('admin@example.com')
->to($request->email)
->subject('Reset Password Notification');
});
return back()->with('message', 'We have e-mailed your password reset link!');
}
}
Step 11 – Forgot Password View File
Now create an email.blade.php file in your views/auth/password directory. Now, open resources/views/auth/password/email.blade.php and update the following code on it.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Reset Password</div>
<div class="card-body">
@if (session('message'))
<div class="alert alert-success" role="alert">
{{ session('message') }}
</div>
@endif
<form method="POST" action="{{ route('password.email') }}">
@csrf
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">E-Mail Address</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
Send Password Reset Link
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Step 12 – Create Reset Password Migration
NOTE: If the password_reset table already exists in your database then skip this step.
php artisan make:migration create_password_resets_table
After creating the password_reset table you need to open the database\migrations\2014_10_12_100000_create_password_resets_table.php file and update the below code on it.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePasswordResetsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('password_resets');
}
}
Now you need to generate the migrate command to create the table in your database.
php artisan migrate
Step 13 – Create Mailtrap Account
In the local machine, we mostly use mailtrap for receiving emails in any admin panel. So you just need to open mailtrap.com and create an account there. After that get the below credentials from Mailtrap and update them to your .env file just like below.
MAIL_MAILER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=331e7bae#####
MAIL_PASSWORD=25a1052b#####
MAIL_ENCRYPTION=null
Step 14 – Create Verify Blade
Now create a d verify.blade.php file insdie the resources/views/auth/password directory. After that open resources/views/auth/password/verify.blade.php and put the below code on it.
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Verify Your Email Address</div>
<div class="card-body">
@if (session('resent'))
<div class="alert alert-success" role="alert">
{{ __('A fresh verification link has been sent to your email address.') }}
</div>
@endif
<a href="{{ url('/reset-password/'.$token) }}">Click Here</a>.
</div>
</div>
</div>
</div>
</div>
Step 15 – Create Reset Password Routes
After the forgot password functionality in laravel we will implement the reset password functionality in laravel. The forgot password functionality send a recovery email in your mailtrap account where your can click the reset link. The link will redirect you to a new password updation form.
So, here we will update first the route section for resetting passwords in laravel app. Open your routes/web.php file and update the following routes on it.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Auth\ResetPasswordController;
Route::get('reset-password/{token}', [ResetPasswordController::class, 'getPassword'])->name('password.reset');
Route::post('reset-password', [ResetPasswordController::class, 'updatePassword'])->name('password.update');
Step 16 – Create Reset Password Controller
Next, generate a ResetPasswordController using the following command.
php artisan make:controller Auth/ResetPasswordController
After successfully generating the controller open the app\Http\Controllers\Auth\ResetPasswordController.php file and put the below code on it.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Models\User;
class ResetPasswordController extends Controller
{
public function getPassword($token)
{
return view('auth.password.reset', ['token' => $token]);
}
public function updatePassword(Request $request)
{
$request->validate([
'email' => 'required|email|exists:users',
'password' => 'required|string|min:6|confirmed',
'password_confirmation' => 'required'
]);
$passwordReset = DB::table('password_resets')
->where(['email' => $request->email, 'token' => $request->token])
->first();
if(!$passwordReset)
return back()->withInput()->with('error', 'Invalid token!');
$user = User::where('email', $request->email)
->update(['password' => Hash::make($request->password)]);
DB::table('password_resets')->where(['email'=> $request->email])->delete();
return redirect('/login')->with('message', 'Your password has been changed!');
}
}
Step 17 – Create Reset Password View File
For showing the resetting password form your need to create and reset.blade.php file inside the resources\views\auth\password directory. So open the resources\views\auth\password\reset.blade.php file and put the below code on it.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Reset Password</div>
<div class="card-body">
<form method="POST" action="{{ route('password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group row">
<label for="email" class="col-md-4 col-form-label text-md-right">E-Mail Address</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">Password</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row">
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">Confirm Password</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" autocomplete="new-password">
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
Reset Password
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Step 18 – Run Dev Server and Test
Now, it’s time to test our Laravel Custom Authentication system. For this, you need to run your application using the serve command.
php artisan serve
Now, run the URL in your browser and test the custom login, registration, logout, forgot and reset password functionality in laravel application.
http://localhost:8000/register
I hope you enjoy this tutorial.