Laravel 9 Custom Authentication – Create Login, Register, Forgot & Reset Password
Table of contents
No headings in the article.
Laravel makes implementing authentication very simple which is we describe you before how to use laravel auth in a project, But more then time we don’t use the laravel auth for user authentication functionality in our project. So here we create create custom signin, Signup, forgot password pages in laravel without auth command.
laravel 7 Custom Login and Registration Example Tutorial Laravel 8 Custom Login Register Forgot Reset Password Example Tutorial Laravel Custom Login registration forget password without auth
Step 1: Install Laravel Project First Install a laravel project to run below command
composer create-project --prefer-dist laravel/laravel customlalravelauth
Step 2: Setup Database Credentials Create a new database custom auth and now open you .env file and add your database credentials.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=#Your database name
DB_USERNAME=root #Your database username
DB_PASSWORD=#Your database password
Now run the migration command and generate table in database.
php artisan migrate Step 3: Create Register Page Routes Now go in your routes>web.php file and crate two routes here.
routes/web.php
Route::get('register', 'Auth\RegisterController@register');
Route::post('register', 'Auth\RegisterController@store')->name('register');
Step 4: Create Register Page Controller Now create a new controller RegisterController to adding below code in your terminal.
php artisan make:controller Auth/RegisterController
After creating register controller add below code on it.
app\Http\Controllers\Auth\RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use Hash;
class RegisterController extends Controller
{
public function register()
{
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 you need to create your blades files. First create new folder layouts in your resources>views directory, then create a new file app.blade.php in layout folder same like below.
resources\views\layouts\app.blade.php
<!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() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- 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" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</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') }}
</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>
Now create a new folder auth in your resources>views directory and add a new file register.blade.php then add below code on it.
resources\views\auth\register.blade.php
@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') }}" required 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') }}" required 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" required 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" required 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
You can run your register functionality run perfect in your browser. Now we learn how to work login functionality in laravel without auth.
Step 6: Add Login Routes
Route::get('login', 'Auth\LoginController@login')->name('login');
Route::post('login', 'Auth\LoginController@authenticate');
Route::get('logout', 'Auth\LoginController@logout')->name('logout');
Step 7: Create Login Controller
Now create your LoginController to add below command in your terminal and add below code on it.
php artisan make:controller Auth/LoginController
The controller show in your App\Http\Controllers directory.
app\Http\Controllers\Auth\LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Auth;
class LoginController extends Controller
{
public function login()
{
return view('auth.login');
}
public function authenticate(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');
}
}
Step 8: Create Login Blade File
After creating login controller to showing login view just create login page inside auth folder and add below code.
resources/views/auth/login.blade.php
@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
<div class="card-body">
<form method="POST" action="{{ route('login') }}">
@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') }}" required 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" required 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
Step 9: Add Home Funcationlity
Add Route
Route::get('home', 'HomeController@home')->name('home');
Add Controller
php artisan make:controller HomeController
Now add the below code in your HomeContoller .
app\Http\Controllers\HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function home()
{
return view('home');
}
}
After successfully login you will be redirected to the home page, so you have to create a new page in your resources/views directory and add below code on it. This page show after you have successfully login a user.
resources/views/home.blade.php
@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">
You are successfully logged in!
</div>
</div>
</div>
</div>
</div>
@endsection
After custom registration and login functionality in laravel now we learn how to create custom forgot and reset password functionality in laravel. First create forgot password functionality in laravel. Create two routes in your web.php file.
Step 10: Create Forget Password Routes
routes/web.php
Route::get('forget-password', 'Auth\ForgotPasswordController@getEmail');
Route::post('forget-password', 'Auth\ForgotPasswordController@postEmail');
Step 11: Create Forget Password Controller
Now you need to create a ForgotPasswordController just run below command.
php artisan make:controller Auth/ForgotPasswordController After creating the controller now add the below code on it.
app/Http/Controllers/Auth/ForgotPasswordController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use DB;
use Carbon\Carbon;
use Mail;
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('email@example.com');
$message->to($request->email);
$message->subject('Reset Password Notification');
});
return back()->with('message', 'We have e-mailed your password reset link!');
}
}
Step 12: Create Forget Password Migration
If you add your gmail in your forget password input then your send a link via mail function using controller function so here you need to add a Forget password migration to running just below command.
php artisan make:migration create_password_resets_table
After creating passowrd reset table add below code on it.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
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');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('password_resets');
}
}
Now inserting it on database run below command.
php artisan migrate
Step 13: Forget Password View File
In your Auth folder now create a password folder and then create email.blade.php file and then add below code on it.
resources\views\auth\password\email.blade.php
@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('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<form method="POST" action="/forget-password">
@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
Now if you add an email to forget password option and send then its go in your mailtrap where you can click the link and update your password easily.First add your mailtrap details in your .env file. If you have not any mailtrap account then please create first to go mailtrap.io. Mailtrap is a free mail testing website.
Step 14: Add Mailtrap Details in .env File
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=331e7bae#####
MAIL_PASSWORD=25a1052b#####
MAIL_ENCRYPTION=null
Now Checkout mail trap where your received an email. Below create a blade file to sending email in your views>auth directory this file go in your mailtrap inbox.
Step 15: Create Verify Blade
resources/views/auth/password/verify.blade.php
<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>
Now click the link which is received in your inbox now you redirect a link where your update your new password checkout how its work.
Step 16: Create Reset Password Routes
Route::get('reset-password/{token}', 'Auth\ResetPasswordController@getPassword');
Route::post('reset-password', 'Auth\ResetPasswordController@updatePassword');
Step 17: Create Reset Password Controller
After create reset password routes now you need to create a new controller
ResetPasswordController in your App>Http directory.
php artisan make:controller Auth\ResetPasswordController
Now add below code in this controller.
app\Http\Controllers\Auth\ResetPasswordController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use DB;
use App\User;
use Hash;
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',
]);
$updatePassword = DB::table('password_resets')
->where(['email' => $request->email, 'token' => $request->token])
->first();
if(!$updatePassword)
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 18: Create Reset Password Blade File
Now create to showing reset password option blade file in your views>authdirectory.
resources\views\auth\password\reset.blade.php
@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="/reset-password">
@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