Integrate 2FA with Twilio in Laravel.
Two-Factor Authentication (2FA) is an essential security feature that adds an extra layer of protection to user accounts. Twilio is a cloud communications platform that provides various APIs for sending and receiving SMS, voice calls, and other communication channels. In this answer, we will discuss how to integrate 2FA with Twilio in Laravel.
To implement 2FA with Twilio in Laravel, we will use the following packages:
- Laravel-Nexmo: A Laravel wrapper for Twilio API.
- Laravel-OTP: A Laravel package for generating and validating One-Time Passwords (OTP).
Let's get started with the setup.
Step 1: Install Laravel-Nexmo package
First, we need to install the Laravel-Nexmo package using composer. Run the following command in your terminal:
composer require nexmo/client:^3.0
Next, publish the configuration file by running:
php artisan vendor:publish --provider="Nexmo\Laravel\NexmoServiceProvider"
Open the .env
file and add your Twilio account SID, auth token, and phone number:
TWILIO_SID=your_account_sid
TWILIO_TOKEN=your_auth_token
TWILIO_FROM=your_twilio_number
Step 2: Install Laravel-OTP package
Install the Laravel-OTP package using composer:
composer require yadakhovskyy/otp-laravel
Publish the configuration file:
php artisan vendor:publish --provider="Yadakhovskyy\OTPLaravel\OTPLaravelServiceProvider"
Open the .env
file and add your OTP secret key:
OTP_SECRET=your_secret_key
Step 3: Create OTP model
Create a new model called OTP
using the following command:
php artisan make:model OTP
Open the OTP.php
file and add the following code:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Yadakhovskyy\OTPLaravel\Contracts\OTP as OTPContract;
class OTP extends Model implements OTPContract
{
protected $table = 'otps';
protected $fillable = ['user_id', 'code', 'expires_at'];
public function user()
{
return $this->belongsTo(config('auth.models.user'));
}
}
Step 4: Create OTP controller
Create a new controller called OTPController
using the following command:
php artisan make:controller OTPController
Open the OTPController.php
file and add the following code:
namespace App\Http\Controllers;
use App\Models\OTP;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Yadakhovskyy\OTPLaravel\Facades\OTP as OTPFacade;
class OTPController extends Controller
{
public function send(Request $request)
{
$user = Auth::user();
$code = OTPFacade::generate($user->email);
OTP::create([
'user_id' => $user->id,
'code' => $code,
'expires_at' => now()->addMinutes(5),
]);
$message = "Your 2FA code is: {$code}";
$nexmo = app('Nexmo\ClientProvider')->createClient();
$response = $nexmo->message()->send([
'to' => $user->phone_number,
'from' => config('app.name'),
'text' => $message,
]);
if ($response->status == '0') {
return response()->json(['message' => 'OTP sent successfully']);
} else {
return response()->json(['message' => 'Failed to send OTP'], 500);
}
}
public function verify(Request $request)
{
$user = Auth::user();
$code = $request->input('code');
$otp = OTP::where('user_id', $user->id)
->where('code', $code)
->where('expires_at', '>', now())
->first();
if ($otp) {
$otp->delete();
return response()->json(['message' => 'OTP verified successfully']);
} else {
return response()->json(['message' => 'Invalid OTP'], 401);
}
}
}
Step 5: Create routes
Add the following routes in the routes/web.php
file:
Route::post('send-otp', 'OTPController@send')->name('send-otp');
Route::post('verify-otp', 'OTPController@verify')->name('verify-otp');
Step 6: Implement 2FA in Laravel
To implement 2FA in Laravel, we need to modify the LoginController
. Open the LoginController.php
file and add the following code:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\OTPController;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm()
{
return view('auth.login');
}
public function login(Request $request)
{
$this->validateLogin($request);
if ($this->hasTwoFactorEnabled()) {
return $this->sendOTP($request);
}
if ($this->attemptLogin($request)) {
return $this->authenticated($request, $this->guard()->user()) ?: redirect()->intended($this->redirectPath());
}
return $this->sendFailedLoginResponse($request);
}
protected function hasTwoFactorEnabled()
{
return Auth::user()->two_factor_enabled;
}
protected function sendOTP(Request $request)
{
$otpController = app(OTPController::class);
return $otpController->send($request);
}
protected function authenticated($request, $user, $authenticated = true)
{
if ($authenticated && $user->two_factor_enabled) {
return redirect()->route('verify-otp');
}
return parent::authenticated($request, $user, $authenticated);
}
}
Step 7: Enable 2FA for users
To enable 2FA for users, you can add a checkbox in the registration or profile form. When the user checks the checkbox, update the user's two_factor_enabled
field to true.
Step 8: Testing
Now, you can test the 2FA implementation by registering a new user with 2FA enabled and logging in using the OTP.
That's it! You have successfully integrated 2FA with Twilio in Laravel.