Laravel Projects Examples

Laravel Auth with SMS OTP (no email)

You may use the default Laravel login/registration logic using phone number instead of email, with SMS one-time passwords.

For this example, the authentication system uses phone numbers and SMS OTPs via Vonage.

The User Model is updated to store phone and OTP-related fields:

app/Models/User.php:

use Illuminate\Notifications\Notification;
 
class User extends Authenticatable
{
protected $fillable = [
'name',
'phone',
'password',
'verified_at',
'otp_code',
'otp_expires_at',
];
 
protected $hidden = [
'password',
'remember_token',
'otp_code',
];
 
protected function casts(): array
{
return [
'verified_at' => 'datetime',
'otp_expires_at' => 'datetime',
'password' => 'hashed',
];
}
 
public function routeNotificationForVonage(Notification $notification): string
{
return $this->phone;
}
}

Registration Flow

  • User submits name, phone, and password
  • Input is validated (using PhoneNumber rule)
  • User is created
  • OTP is generated and saved to otp_code and otp_expires_at
  • OTP is sent via Vonage SMS
  • User is logged in and redirected to phone verification page

app/Http/Controllers/Auth/RegisteredUserController.php:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\URL;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\RedirectResponse;
use Illuminate\Validation\Rules\Password;
use App\Notifications\SendOtpNotification;
 
class RegisteredUserController extends Controller
{
// ...
 
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'phone_full' => ['required', 'numeric', Rule::unique('users', 'phone')],
'password' => ['required', 'confirmed', Password::defaults()],
]);
 
$user = User::create([
'name' => $request->name,
'phone' => $request->phone_full,
'password' => Hash::make($request->password),
]);
 
$otp = rand(100000, 999999);
 
$user->update([
'otp_code' => $otp,
'otp_expires_at' => now()->addMinutes(10),
]);
 
$user->notify(new SendOtpNotification($otp));
 
Auth::login($user);
 
return redirect(URL::signedRoute('verification.notice'));
}
}

The notification class for...

Want to get the access to GitHub repository?

Become a Premium Member for $129/year or $29/month