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
andotp_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...