Skip to main content

Overview

LaraCMS implements a complete authentication system using Laravel’s built-in authentication with Livewire components. The system includes user registration, login, email verification, password reset, and rate limiting for security.

User Registration

New users can register through the Livewire registration component with built-in security features.

Registration Flow

The registration process is handled by app/Livewire/Auth/Register.php:31:
public function register(): void
{
    $validated = $this->validate([
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class],
        'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
        'turnstile' => ['required', new Turnstile],
    ]);

    $validated['password'] = Hash::make($validated['password']);

    event(new Registered(($user = User::create($validated))));

    // Assign the 'user' role after the user is created
    $user->assignRole('user');

    Auth::login($user);

    $this->redirect(route('home', absolute: false), navigate: true);
}
All new users are automatically assigned the ‘user’ role upon registration. This is the base role for all authenticated accounts with no special permissions.

Cloudflare Turnstile Protection

LaraCMS uses Cloudflare Turnstile (a CAPTCHA alternative) to prevent automated bot registrations:
'turnstile' => ['required', new Turnstile],
This validation rule ensures that every registration request passes Cloudflare’s anti-bot verification.
Turnstile provides better user experience than traditional CAPTCHAs while maintaining strong bot protection.

User Login

The login system includes rate limiting and session management for security.

Login Process

Login is handled by app/Livewire/Auth/Login.php:29:
public function login(): void
{
    $this->validate();

    $this->ensureIsNotRateLimited();

    if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
        RateLimiter::hit($this->throttleKey());

        throw ValidationException::withMessages([
            'email' => __('auth.failed'),
        ]);
    }

    RateLimiter::clear($this->throttleKey());
    Session::regenerate();

    $this->redirectIntended(default: route('home', absolute: false), navigate: true);
}

Rate Limiting

LaraCMS implements rate limiting to prevent brute-force attacks:
protected function ensureIsNotRateLimited(): void
{
    if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
        return;
    }

    event(new Lockout(request()));

    $seconds = RateLimiter::availableIn($this->throttleKey());

    throw ValidationException::withMessages([
        'email' => __('auth.throttle', [
            'seconds' => $seconds,
            'minutes' => ceil($seconds / 60),
        ]),
    ]);
}
Login attempts are limited to 5 attempts per email/IP combination. After exceeding this limit, users must wait before trying again. The throttle key combines email and IP address for security.

Remember Me Functionality

Users can choose to stay logged in across sessions:
public bool $remember = false;
When enabled, Laravel creates a “remember_token” that keeps users authenticated.

Email Verification

LaraCMS requires email verification for new accounts, implementing the MustVerifyEmail contract.

User Model Configuration

The User model implements email verification at app/Models/User.php:17:
class User extends Authenticatable implements MustVerifyEmail, HasMedia
{
    use HasFactory, HasRoles, Notifiable, InteractsWithMedia;
}

Verification Process

Email verification is handled by app/Livewire/Auth/VerifyEmail.php:17:
public function sendVerification(): void
{
    if (Auth::user()->hasVerifiedEmail()) {
        $this->redirectIntended(default: route('profile', absolute: false), navigate: true);
        return;
    }

    Auth::user()->sendEmailVerificationNotification();

    Session::flash('status', 'verification-link-sent');
}

Protected Routes

Verified email is required for certain routes:
Route::prefix('admin')
    ->middleware('auth', 'verified', 'permission:access.admin.panel')
    ->group(function () {
        // Admin routes
    });
The verified middleware ensures users have verified their email before accessing protected areas like the admin panel.

Password Reset

LaraCMS provides a secure password reset flow using Laravel’s password reset tokens.

Forgot Password

Users can request a password reset link via app/Livewire/Auth/ForgotPassword.php:17:
public function sendPasswordResetLink(): void
{
    $this->validate([
        'email' => ['required', 'string', 'email'],
    ]);

    Password::sendResetLink($this->only('email'));

    session()->flash('status', __('A reset link will be sent if the account exists.'));
}
The generic success message (“A reset link will be sent if the account exists”) prevents email enumeration attacks by not revealing whether an account exists.

Reset Password

The password reset is handled by app/Livewire/Auth/ResetPassword.php:40:
public function resetPassword(): void
{
    $this->validate([
        'token' => ['required'],
        'email' => ['required', 'string', 'email'],
        'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
    ]);

    $status = Password::reset(
        $this->only('email', 'password', 'password_confirmation', 'token'),
        function ($user) {
            $user->forceFill([
                'password' => Hash::make($this->password),
                'remember_token' => Str::random(60),
            ])->save();

            event(new PasswordReset($user));
        }
    );

    if ($status != Password::PasswordReset) {
        $this->addError('email', __($status));
        return;
    }

    Session::flash('status', __($status));
    $this->redirectRoute('login', navigate: true);
}

Token Security

The reset token is locked to prevent tampering:
#[Locked]
public string $token = '';
The #[Locked] attribute prevents the token from being modified by client-side requests, ensuring the integrity of the password reset process.

Session Management

After successful login, sessions are regenerated for security:
Session::regenerate();
This prevents session fixation attacks by creating a new session ID.

Authentication Middleware

LaraCMS uses multiple middleware layers for authentication:

Basic Authentication

Route::prefix('profile')->middleware('auth', 'auth.session')->group(function () {
    Route::get('/', [ProfileController::class, 'profile'])->name('profile');
});

Verified Users Only

Route::get('/subscribers', function () {
    return view('subscribers');
})->middleware('auth', 'verified', 'permission:access.subscriber.area');

Admin Access

Route::prefix('admin')
    ->middleware('auth', 'verified', 'permission:access.admin.panel')
    ->group(function () {
        // Admin routes
    });
Admin routes require three conditions: authenticated user, verified email, and the access.admin.panel permission.

User Model Attributes

The User model defines core authentication attributes at app/Models/User.php:27:
protected $fillable = [
    'name',
    'email',
    'password',
];

protected $hidden = [
    'password',
    'remember_token',
];

protected function casts(): array
{
    return [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];
}

Password Hashing

Passwords are automatically hashed when set:
'password' => 'hashed',
This ensures passwords are never stored in plain text.

Security Best Practices

Critical Security Features:
  • Passwords are automatically hashed using bcrypt
  • Rate limiting prevents brute-force attacks (5 attempts max)
  • Session regeneration prevents session fixation
  • Email verification required for sensitive operations
  • Cloudflare Turnstile prevents automated registrations
  • Remember tokens are randomly generated 60-character strings

Next Steps

Roles & Permissions

Learn about role-based access control with Spatie Permission

User Profiles

Managing user profiles, avatars, and media uploads

Build docs developers (and LLMs) love