Greetings! I'm Aneesh Sreedharan, CEO of 2Hats Logic Solutions. At 2Hats Logic Solutions, we are dedicated to providing technical expertise and resolving your concerns in the world of technology. Our blog page serves as a resource where we share insights and experiences, offering valuable perspectives on your queries.
We talk about how to implement Dual or 2factor authentication in Laravel using username and password followed by email. This is purely for programmers. First, the user enters his/her email address and password, after validating that, a token is generated which then gets sent to his email address. The user can log in only by using this token in the next step.
Laravel ships with a default authentication method for login. But here we cannot depend on the default authentication method. Let’s look at it in more detail.
First, we are going to define the action from login in routes.
1 | Route::post('login', 'LoginController@authenticate'); |
When the submit button from the login screen is clicked, the action goes to the authenticate function in LoginController which we are going to define.
Run the following command to create the LoginController.
1 | php artisan make:controller LoginController |
Now we are going to define our function
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 36 37 38 39 40 41 42 43 44 45 | public function authenticate(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required', ]); $email = $request->email; $password = $request->password; $auth = User::authenticate($email)->first(); if (!empty($auth) && Hash::check($password, $auth->password)) { $auth->update(['email_token' => bin2hex(openssl_random_pseudo_bytes(4))]); Notification::send($auth, new AuthenticateUser($auth)); return view('auth.login-verify'); } return redirect(route('login')) ->withInput($request->only('email', 'remember')) ->withErrors([ 'password' => 'Invalid Credentials', ]); } |
The function first validates for proper email and password fields.
Then you can find the following line.
1 | $auth = User::authenticate($email)->first(); |
At the top of the page, you should call the user model
1 | use AppUser; |
The authenticate is a function that should be defined in the User model
1 2 3 4 | public function scopeAuthenticate($query, $email) { return $query->where('email', '=', $email); } |
The function checks whether the email address exists in the user table
Now going to the authenticate function in our LoginController, the $auth variable now will have the user details.
Now we can check the following line.
1 | if (!empty($auth) && Hash::check($password, $auth->password)) |
Here it checks if the $auth is not empty and the password matches the one for the user.
You should call the Hash facade on top of the page.
1 2 3 | use Hash; $auth->update(['email_token' => bin2hex(openssl_random_pseudo_bytes(4))]); |
You should add the email_token field to the user migration.
Here we update the field email_token in our users’ table with a random token generated using the bin2hex(openssl_random_pseudo_bytes(4)) function.
openssl_random_pseudo_bytes($length) function generates a string of pseudo-random bytes, with the number of bytes determined by the length parameter.
The bin2hex($string) function converts a string of ASCII characters to hexadecimal values.
The above function generates an 8 digit code.
Now let’s send this code to the user’s email using
1 | Notification::send($auth, new AuthenticateUser($auth)); |
You should call
1 | use AppNotificationsAuthenticateUser; |
on top of the page.
For this, to work we should create an AuthenticateUser class for notification
Run the following command to create this class
1 | php artisan make:notification AuthenticateUser |
Now we should have a class AuthenticateUser with some functions already created inside it.
Inside the function toMail($notifiable) which will be already there
Update to the following
1 2 3 4 | return (new MailMessage) ->line('Here is your email token') ->line('To login, enter the code in the web page where you requested it.') ->line($notifiable->email_token') ; |
You can customize the above to generate the email in the way you want. Now coming to our LoginController authenticate function, after sending the email token the function will return to a view to enter the email token.
1 | return view('auth.login-verify'); |
You can have a text box and a submit button to a form in the view, with action to the following route which we should define in routes file.
1 | Route::post('/verify', 'LoginController@emailVerify')->name('email-verify'); |
Now let’s define the emailVerify function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public function emailVerify() { $token = request('email_token'); if (!$token) { return redirect('login')->withErrors(['email' => 'Email Verification Token not provided!']); } $user = User::where('email_token', $token)->first(); if (!$user) { return redirect('login')->withErrors(['flash-error' => 'Invalid Email Verification Token!']); } Auth::login($user); return redirect('home'); } |
In this function, we check whether the email_token is valid and on success, login using the Auth::login($user) function.
You should call ‘use Auth;’ facade on top of the page. You have now successfully created dual authentication using email. As a Laravel Application Development Company, we adopt these ways to get it done easily.