Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Verification Code Laravel Package

wotz/laravel-verification-code

Laravel package for generating and validating verification codes with configurable length, expiry, attempt limits, and rate limiting. Supports email or SMS delivery, custom storage drivers, and simple APIs for sending and checking codes.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and its migrations:

composer require wotz/laravel-verification-code
php artisan vendor:publish --provider="Wotz\VerificationCode\VerificationCodeServiceProvider"
php artisan migrate

Publishing typically exposes a verification.php config file and a migration for a verification_codes table. The first place to look is the config file—code length, expiry, and notification channel are usually defined there.

Add the package trait to any authenticatable model (usually App\Models\User):

use Wotz\VerificationCode\Traits\HasVerificationCodes;

class User extends Authenticatable
{
    use HasVerificationCodes;
}

The first practical use case is passwordless login or phone verification: a user submits a phone number or email, your app sends a short code, the user submits the code, and you log them in (or mark the contact as verified). Start by wiring a single endpoint to send a code and another to verify it—then expand to 2FA or registration flows.

Implementation Patterns

Sending and verifying codes
The package usually exposes methods on the trait or a facade. Typical day-to-day calls:

// Send a code over the configured channel (sms, email, etc.)
$user->sendVerificationCode();

// Verify a submitted code
if ($user->verifyCode($request->code)) {
    Auth::login($user);
}

If the package provides a facade, you may also see VerificationCode::send($user) and VerificationCode::verify($user, $code). Keep the send and verify logic in a dedicated controller or action class so you can rate-limit and log attempts.

Passwordless login flow

  1. POST /auth/code – validate identifier, find or create user, call sendVerificationCode().
  2. POST /auth/verify – validate code, call verifyCode(), then Auth::login($user) and regenerate the session.
  3. Optionally consume the code so it cannot be reused.

Two-factor authentication
After a successful password check, don’t log the user in immediately. Instead, store a temporary “2FA pending” session flag, send a code, and only call Auth::login() after verifyCode() succeeds. This keeps the package focused on code generation while you own the auth state.

Custom notifications
Most packages let you swap the notification class in config. Point it to your own class that extends the package’s notification or implements Laravel’s ShouldQueue and via() methods. This is where you integrate Twilio, Nexmo, or a local SMS gateway.

// config/verification.php
'notification' => App\Notifications\CustomVerificationCode::class,

Rate limiting and throttling
Wrap send and verify endpoints with Laravel’s throttle middleware. For finer control, use RateLimiter::attempt() keyed by user ID or IP. A common pattern is 1 send per minute and 5 verify attempts per 10 minutes.

Multi-guard and multi-model
Because the trait is model-agnostic, you can use it on User, Admin, or any authenticatable model. If you use multiple models, ensure the verification_codes table uses a morph relation (or separate tables) and that your verification logic scopes codes to the correct model instance.

Testing
Use Notification::fake() to assert the code notification was sent, and Carbon::setTestNow() to test expiry. If the package stores a hashed code, you can’t assert the plain code from the database—assert the notification payload instead.

Gotchas and Tips

  • Config caching: After changing config/verification.php, run php artisan config:clear. In production, always config:cache after deployment.
  • Migration conflicts: The published migration may create a table name that clashes with an existing one. Rename the table in the migration and update the package config if it supports a custom table name.
  • Code cleanup: Expired codes accumulate. Schedule a cleanup command (either the package’s own or a custom VerificationCode::where('expires_at', '<', now())->delete()) in app/Console/Kernel.php.
  • Security: Never return the code in an API response. Always rate-limit both send and verify endpoints. If the package uses a plain-text code in the database, consider hashing it via a custom code generator or model mutator.
  • Reuse prevention: After a successful verification, delete or mark the code as used. Most packages do this by default, but verify the behaviour—especially if you allow multiple active codes.
  • Notification channel setup: The package sends via Laravel notifications, so your User model must have the correct routeNotificationForSms() or routeNotificationForMail() method. Missing this is the most common “code never arrives” bug.
  • Testing time: Use Carbon::setTestNow() to fast-forward expiry. If the package uses now() internally, this works; if it uses time(), you may need to freeze time differently.
  • Extension points: Look for bindings in the service provider—custom code generators, custom notification classes, and custom model bindings are typical. If the package doesn’t expose what you need, extend the VerificationCode model or wrap the trait methods in your own service.
  • Version compatibility: This is a small package (58 stars). Check the composer.json constraints against your Laravel and PHP versions. If it lags behind a new Laravel release, you may need to fork or override the service provider.
  • Don’t over-rely on routes: If the package ships routes, they’re often minimal. For production, define your own routes and controllers so you control middleware, validation, and response shapes.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels