Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

marsuch's avatar

Laravel requires user authentication but still logs in immediately after registration

Hi, do I have to change anything during registration if I need the user to verify? In the route I have this:

Auth::routes([
    'verify' => true,
]);

The user model looks like this

<?php

namespace App\Models;

use App\Models\Pivot\UserRole;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var string[]
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class, 'user_role')->using(UserRole::class);
    }

    public function hasRole(string $slug): bool
    {
        return $this->roles()->where('slug', $slug)->exists();
    }

    public function assignRoles(array $slugs): void
    {
        $newRoles = Role::whereIn('slug', $slugs)->pluck('id')->toArray();
        $this->roles()->syncWithoutDetaching($newRoles);
    }

    public function sendEmailVerificationNotification(): void
    {
        VerifyEmail::toMailUsing(static function ($notifiable, string $verificationUrl){
            return (new MailMessage)
                ->subject(__('notifications.user_account_activation.subject'))
                ->line(__('notifications.user_account_activation.line1'))
                ->action(__('notifications.user_account_activation.action'), $verificationUrl)
                ->line(__('notifications.user_account_activation.line2'));
        });

        parent::sendEmailVerificationNotification();
    }
}

And the register controller looks like this

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        $user = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);

        $user->assignRoles(['user']);

        return $user;
    }
}

After registration, I will be sent an email with a link through which I will verify the user. Which is fine. But there is one problem immediately after registration, the user logs in and he can use the system normally. Which is something I don't want and I want the system not to allow login until the user is authenticated.

0 likes
3 replies
Snapey's avatar

This is standard behaviour. You will need to actively log the user out if you want this behaviour, but bear in mind that the user will need to login again before they can verify their account.

The expected use is that you wrap all routes where a user might (for instance) create some data in the verify middleware

marsuch's avatar

@Snapey Yes, you're right, I figured out that in a way it can be solved with the help of middleware verified, which is actively redirected to email / verify if the account is not verified.

Personally, it comes to me as bullshit, and the whole concept of user verifiactionsomehow loses its meaning, however, with the use of middleware verified, it can be taken into account

Please or to participate in this conversation.