# Laravel User Verification: token based email checks and the two columns they need

> jrean/laravel-user-verification adds a token, a verification flag and a set of routes to a Laravel app, but it expects you to own the registration controller and the mail template. It suits teams that want the plumbing without the framework defaults for verification.

**jrean/laravel-user-verification** — PHP package built for Laravel to easily handle a user email verification and validate the email

- Repository: https://github.com/jrean/laravel-user-verification
- Stars: 861 · Forks: 111
- Language: PHP
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/jrean-laravel-user-verification

## A token column, a flag column and a verification route

The scope here is narrow on purpose. The feature list is short: generate and store verification tokens for registered users, send or queue verification emails with token links, handle the token verification process, set users as verified, and relaunch the verification process at any time. There is no user model, no registration form and no frontend. The package assumes you already have a Laravel application with a registration flow, and it bolts a token column, a boolean column and a controller trait onto it. The mechanism is easy to follow once you know the three moving parts. A user record gains two columns, `verified` and `verification_token`, and the package's own migration adds them for you. When a user registers, `generate()` writes a token against that user, and the token travels in a link that hits a route named `email-verification.check`, which carries the token in the path. The route points at a method on your own registration controller, and the `VerifiesUsers` trait is what implements the handling. The token is then compared against the stored value and the user is marked verified. The whole design assumes a token stored in the database row and delivered out of band by email, which is why the send and verify halves of the flow are separable.

## Installing the package and registering the provider

Installation is the standard Composer plus Artisan flow. First pull the package into your project:

```bash
composer require jrean/laravel-user-verification
```

Then register the service provider in `config/app.php`, and the documentation is specific about placement, saying to make sure it sits above the `RouteServiceProvider`:

```php
'providers' => [
    // ...
    Jrean\UserVerification\UserVerificationServiceProvider::class,
    // ...
    App\Providers\RouteServiceProvider::class,
],
```

The facade is optional, and if you want the shorter call style you can alias it:

```php
'aliases' => [
    // ...
    'UserVerification' => Jrean\UserVerification\Facades\UserVerification::class,
],
```

That ordering requirement is the first hint that this package has to be registered before the router resolves your routes, which matters if you have ever fought a route that only appears in some environments.

## Two columns, one migration path, and the option to edit it

The schema requirement is explicit: the users table needs `verified` and `verification_token`. The package ships a migration you can run straight from the vendor directory:

```bash
php artisan migrate --path="/vendor/jrean/laravel-user-verification/src/resources/migrations"
```

If you would rather own the file, publish it and edit it:

```bash
php artisan vendor:publish --provider="Jrean\UserVerification\UserVerificationServiceProvider" --tag="migrations"
```

The same publish mechanism handles the config file, the email views and the translation strings, each under its own tag such as `config`, `views` and `translations`. That symmetry is worth noting, because it means every file the package relies on is available for editing once published, which is the normal way to make a package fit an existing codebase rather than fight it.

## Gating routes with the isVerified middleware

Verification only matters if something depends on it, and the package provides the gate. You register the included middleware in `app/Http/Kernel.php` under the `isVerified` key:

```php
protected $routeMiddleware = [
    // ...
    'isVerified' => \Jrean\UserVerification\Middleware\IsVerified::class,
];
```

Then you wrap the routes that require a confirmed address in a group:

```php
Route::group(['middleware' => ['isVerified']], function () {
    // Protected routes...
});
```

What the middleware does when the user is not verified is not described in the README, so the failure path, the redirect target and the HTTP status are yours to define by wrapping it. The documentation shows how to generate your own middleware class if you want different behaviour, and the package supports that route rather than insisting on its own. This is the right place to put your product decisions about what an unverified account can still do.

## Sending the token: immediate, queued or delayed

Email delivery is where the package offers more than a single path, and the three methods are the same call with different timing semantics. Send now, queue for the background worker, or send later after a delay in seconds:

```php
// Send immediately
UserVerification::send($user, 'Email Verification');

// Queue for sending
UserVerification::sendQueue($user, 'Email Verification');

// Send later
UserVerification::sendLater($seconds, $user, 'Email Verification');
```

A basic Blade template is included, and the view receives a `$user` variable holding the user details and the verification token. To change it, publish the views:

```bash
php artisan vendor:publish --provider="Jrean\UserVerification\UserVerificationServiceProvider" --tag="views"
```

They land in `resources/views/vendor/laravel-user-verification/`. If you prefer Markdown over Blade, the config file has an `email` key with a `type` option:

```php
'email' => [
    'type' => 'markdown',
],
```

The practical limit is that the shipped template is described as basic. It carries no branding and no layout, so a real product still has to write that mail.

## Your controller does the registration work

The clearest statement of where responsibility sits comes from the integration example. The trait is mixed into a controller that already extends the framework's own controller:

```php
use Jrean\UserVerification\Traits\VerifiesUsers;

class RegisterController extends Controller
{
    use RegistersUsers, VerifiesUsers;
    
    // ...
}
```

And the register method calls the package only after the account is created and the user is logged in:

```php
public function register(Request $request)
{
    $this->validator($request->all())->validate();

    $user = $this->create($request->all());

    event(new Registered($user));

    $this->guard()->login($user);

    UserVerification::generate($user);
    UserVerification::send($user, 'Please Verify Your Email');

    return $this->registered($request, $user)
                    ?: redirect($this->redirectPath());
}
```

Two routes are also yours to wire, since they point at your controller rather than at one inside the package:

```php
Route::get('email-verification/error', 'Auth\RegisterController@getVerificationError')->name('email-verification.error');
Route::get('email-verification/check/{token}', 'Auth\RegisterController@getVerification')->name('email-verification.check');
```

If you prefer the user to be logged in as soon as the token checks out, there is an `auto-login` switch in the config:

```php
'auto-login' => true,
```

Read the code above as a contract. Every verification decision still lands in your controller, and the package supplies the token lifecycle around it.

## Version churn and what the licence actually says

The release history explains a lot about who this package is for. The tag list runs from v2.2 for Laravel 5.0 through 5.2, then one release per Laravel generation, with v14.0.0 published on 2026-04-28 for Laravel 13.0, after v13.0.0 in 2025-03-25 and v12.0.0 in 2024-07-03. A new major version per Laravel release is predictable, and it means an upgrade usually involves a version bump rather than a redesign. The repository is not archived and the last push was on 2026-04-28, so the code is being kept in step with framework releases. Licensing is the murkiest part: GitHub classifies it as Other, a custom licence the platform cannot map to a standard identifier, so read the LICENSE file before you depend on it commercially.

## Where the package stops and Laravel starts

The honest comparison is not with other verification packages but with what the framework already offers. Laravel ships its own verification routes and notifications, and this package exists for teams that have already replaced the built-in registration controller, for example with a social login flow or a custom API, and want to keep a token check in that new code. The difference in approach is that the framework path is opinionated and self contained, while this one is a trait, a middleware and a facade you place by hand. The cost of that choice is visible in the setup: two columns to add, a provider to register in a specific position, three publish tags, two routes to declare, and a mail template to write. Nothing here is hard. It is just several integration points, and each one is a place where the framework default would have given you less work and more convention.

## Conclusion

Adopt laravel-user-verification when your Laravel application already owns its own registration controller and wants a pluggable token check rather than the framework defaults. Do not adopt it if you need a package that ships its own registration flow, CAPTCHA, or a mail design you do not write yourself. Before installing, confirm that adding `verified` and `verification_token` to your `users` table fits your existing schema, and check the LICENSE file yourself, since GitHub classifies it as a custom licence rather than a standard one.

## FAQ

### How do I install laravel-user-verification in a Laravel project?

Run `composer require jrean/laravel-user-verification`, then register `Jrean\UserVerification\UserVerificationServiceProvider::class` in the `providers` array of `config/app.php` above the `RouteServiceProvider`.

### Which database columns does laravel-user-verification need?

The package requires two columns on the users table, `verified` and `verification_token`. Its own migration can be run with `php artisan migrate --path="/vendor/jrean/laravel-user-verification/src/resources/migrations"`, or published and edited.

### How do I send the verification email now, later, or in the queue?

The facade exposes `UserVerification::send($user, 'Email Verification')`, `UserVerification::sendQueue($user, 'Email Verification')` and `UserVerification::sendLater($seconds, $user, 'Email Verification')` for immediate, queued and delayed delivery.

### Which Laravel versions does the package support?

The compatibility table maps each Laravel release to a package version, from 2.2 for Laravel 5.0 through 5.2 up to 14.0.0 for Laravel 13.0. Releases for older Laravel versions live on their own tagged branches, while the master branch covers 7.0 and above.

## Sources

- [Issues](https://github.com/jrean/laravel-user-verification/issues)
- [jrean/laravel-user-verification on GitHub](https://github.com/jrean/laravel-user-verification)
- [README](https://github.com/jrean/laravel-user-verification/blob/master/README.md)
- [Releases](https://github.com/jrean/laravel-user-verification/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jrean-laravel-user-verification
