In today's article, I am showing you how to implement custon authentication system in Laravel. Laravel has it's own in-built auth scaffolding which we can roll out with a single command but in here we don't use it here.

Default Auth

Note:

Below Version 6 : You can roll out it by running below command:
1
php artisan make:auth

Above Version 6 : We have to use two commands, which provides the routes and layouts(views) for authentication endpoints.

1
2
3
composer require laravel/ui

php artisan ui vue --auth

Initialize project

First, you need to setup your project directory. Go to your project directory and run below command to create fresh Laravel project:
1
laravel new <your-application-name>

Then you need to run:

1
2
3
4
5
composer require laravel/ui  // ui scaffolding package

php artisan ui bootstrap // *optional - adding bootstrap

npm install && npm run dev

After that you can start your development server using below command:

1
php artisan serve

Make Migration

In here, we don't need to create new Schema. We can use the default User schema which is inside the database/create_users_table.php TO migrate our Database, run below command in your terminal:
1
php artisan migrate

Create routes

Now, we need to configure our routes for showing up Login & Signup views. To configure them open your routes/web.php and paste below code in it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Show Register Page & Login Page
Route::get('/login', 'LoginController@show')->name('login')->middleware('guest');
Route::get('/register', 'RegistrationController@show')
->name('register')
->middleware('guest');


// Register & Login User
Route::post('/login', 'LoginController@authenticate');
Route::post('/register', 'RegistrationController@register');


// Protected Routes - allows only logged in users
Route::middleware('auth')->group(function () {
Route::get('/', 'DashboardController@index');

Route::post('/logout', 'LoginController@logout');
});

Hashing password

For the better security we need to hash our password before store it in database. To do it add this method to User model.
1
2
3
4
5
6
use Illuminate\Support\Facades\Hash;  // Import Hash facade

public function setPasswordAttribute($password)
{
$this->attributes['password'] = Hash::make($password);
}

Create Controllers

Run below command to create controllers for Login, Register and Dashboard:
1
2
3
php artisan make:controller LoginController
php artisan make:controller RegistrationController
php artisan make:controller DashboardController

Now we need to work with our logic to display registration page and registering users. Open RegistrationController.php and paste below code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegistrationController extends Controller
{

public function show()
{
return view('register');
}

public function register(Request $request)
{
$validator = $request->validate([
'name' => 'required|min:1',
'email' => 'required',
'password' => 'required|min:6'
]);

\App\User::create($validator);

return redirect('/login');
}

}

Then, we need to work with our logic to display login page and login users. Open LoginController.php and paste below code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;

class LoginController extends Controller
{
public function show()
{
return view('login');
}

public function authenticate(Request $request)
{
$validator = $request->validate([
'email' => 'required',
'password' => 'required|min:6'
]);

if (Auth::attempt($validator)) {
return redirect()->route('dashboard');
}
}

public function logout()
{
Session::flush()
Auth::logout();
return back();
}

}

Refactor code

In here, we are going to separate out the validation logic from register method in RegistrationController.php and separate out the validation logic from authenticate method in LoginController.php. Run below command in your terminal:
1
php artisan make:request RegistrationRequest

It will create a file called RegistrationRequest.php underApp/Http/Requests directory. Now you need to paste below code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
public function authorize()
{
return true; // Set this to "true" else Unauthorized error will be thrown
}

public function rules()
{
return [
'name' => ['required', 'min:3'],
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string', 'min:6'],
];
}

To create LoginRequest.php. Run below command in your terminal:

1
php artisan make:request LoginRequest

It will create a file called LoginRequest.php underApp/Http/Requests directory. Now you need to paste below code in it:

1
2
3
4
5
6
7
8
9
10
11
12
public function authorize()
{
return true; // Set this to "true" else Unauthorized error will be thrown
}

public function rules()
{
return [
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string', 'min:6'],
];
}

Now we need to inject RegistrationRequest into our register and login methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/ RegisterController.php

use App\Http\Requests\RegistrationRequest; // Don't forget to import

public function register(RegistrationRequest $requestFields) // injected Request class
{

// This will throw an error, since data passed to create method
// must be an array, but $requestFileds contains an object.
// We will fix it in next section
\App\User::create($requestFields);

return redirect('/login');
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/ LoginController.php

use App\Http\Requests\LoginRequest; // Don't forget to import

public function authenticate(LoginRequest $requestFields)
{
// Returned validated fields also contain the csrf token,
// therefore, we pick only email and password.
$attributes = $requestFields->only(['email', 'password']);

if (Auth::attempt($attributes)) {
return redirect()->route('dashboard');
}
}

Then we need to create a folder called Traits inside app folder and create a file RegisterUser.php and paste beloe code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Traits;

trait RegisterUser
{
public function registerUser($fields)
{
$user = \App\User::create([
'name' => $fields->name,
'email' => $fields->email,
'password' => $fields->password
]);
return $user;
}
}

Now we need to use this Trait in our RegistrationController.php. Move on to you RegistrationController.php and paste below code:

1
2
3
4
5
use App\Traits\RegisterUser;  // Don't forget to import

class RegistrationController extends Controller
{
use RegisterUser; // call RegisterUser class here

Now, you need to change your your register method as mentioned below:

1
2
3
4
5
public function register(RegistrationRequest $requestFields)
{
$user = $this->registerUser($requestFields);
return redirect('/login');
}

Final code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- LoginController.php -->

<?php

namespace App\Http\Controllers;

use App\Http\Requests\LoginRequest;

class LoginController extends Controller
{
public function authenticate(LoginRequest $requestFields)
{
$attributes = $requestFields->only(['email', 'password']);
if (Auth::attempt($attributes)) {
return redirect()->route('dashboard');
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- RegistrationController.php -->

<?php

namespace App\Http\Controllers;

use App\Traits\RegisterUser;
use App\Http\Requests\RegistrationRequest;

class RegistrationController extends Controller
{
use RegisterUser;

public function register(RegistrationRequest $requestFields)
{
$user = $this->registerUser($requestFields);
return redirect('/login');
}
}

Conclusion

In this tutorial, we obtain how can we implement custon authentication in Laravel. You can obtain complete source code for this tutorial from this GitHub repository.

Happy Coding