Using this Laravel Custom Authentication example tutorial, you can implement your own authentication logic instead of relying on the built-in authentication system provided by Laravel. This can be useful when you have specific requirements or need to integrate with an external authentication provider. In this tutorial you will learn how to create custom login, registeration, forgot password, and reset password functionality in the Laravel application without auth.
Here’s a step-by-step guide on how to implement custom authentication in Laravel:
Step 1 – Download Laravel App
First, 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 we will process the custom registration functionality in laravel without auth. 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
Next, generate a register controller using the following command.
php artisan make:controller Auth/RegisterController
Now, 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, create 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>
Next, 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
Now, we will create laravel custom Login without auth funcationality.
So, same as the registration process we will create the login routes in the routes/web.php along with 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
For generating the login controller you need to run the below command on it.
php artisan make:controller Auth/LoginController
After that open the 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 the views/auth directory and create a login.blade.php file. After that open your resources/views/auth/login.blade.php file 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">{{ __('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
Next, navigate the resources/views directory and create a new file named as home.blade.php file. 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
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
So, the Laravel custom authentication example is completed. You have learned today custom login, registration, forget, and reset the password without Laravel auth step by step.
return view(‘auth.password.reset’, [‘token’ => $token]); what this line does what is password.reset
displaying the password reset form
I’m sorry but in step 11, it should be:
return back()->with(‘status’, ‘We have e-mailed your password reset link!’);
Because you declared ‘status’ variable in the view
Illuminate\Contracts\Container\BindingResolutionException
Target class [Auth\RegisterController] does not exist.
How to fix?
Please use the the controllers file if you are using 6+ version laravel app
web.php file
name(‘register’);
I will create new article for laravel 6+ app