Documentation

Laravel Authentication

Laravel Authentication

This guide covers the Laravel authentication system included with UltraViolet Pro. The authentication is built with Laravel Breeze and provides a complete user management solution with login, registration, password reset, and email verification.

Overview

UltraViolet Pro's authentication system includes:

  • Laravel Breeze - Minimal, simple authentication scaffolding
  • User Registration - New user sign up
  • User Login - Session-based authentication
  • Password Reset - Email-based password recovery
  • Email Verification - Verify user email addresses
  • Remember Me - Persistent login sessions
  • Profile Management - Update user information
  • CSRF Protection - Security against cross-site attacks

Authentication Pages Preview

UltraViolet includes beautiful, pre-styled authentication pages with multiple design variants. See the Page Templates guide for more design options.

What's Included

Pre-built Features

Registration - Users can create accounts ✅ Login/Logout - Session management ✅ Password Reset - Forgot password flow ✅ Email Verification - Optional email confirmation ✅ Remember Me - Long-term sessions ✅ Profile Updates - Edit user information ✅ Password Updates - Change password ✅ Account Deletion - Delete user account

Authentication Routes

// Authentication routes (defined in routes/auth.php)

// Registration
GET  /register           - Show registration form
POST /register           - Handle registration

// Login
GET  /login             - Show login form
POST /login             - Handle login
POST /logout            - Handle logout

// Password Reset
GET  /forgot-password   - Show forgot password form
POST /forgot-password   - Send reset link email
GET  /reset-password    - Show reset password form
POST /reset-password    - Handle password reset

// Email Verification
GET  /verify-email      - Email verification notice
GET  /verify-email/{id}/{hash} - Verify email
POST /email/verification-notification - Resend verification

// Profile
GET  /profile           - Show profile edit form
PATCH /profile          - Update profile
DELETE /profile         - Delete account

Setup Instructions

Already Installed

If you followed the Laravel Setup Guide, authentication is already installed and configured!

Manual Installation (if needed)

If starting fresh or reinstalling:

# Install Laravel Breeze
composer require laravel/breeze --dev

# Install Breeze scaffolding
php artisan breeze:install blade

# Install dependencies
npm install

# Build assets
npm run build

# Run migrations
php artisan migrate

Using Authentication

Registering Users

Registration Page

Via Web Interface

  1. Visit /register in your browser
  2. Fill out the registration form:
    • Name
    • Email
    • Password (min 8 characters)
    • Password Confirmation
  3. Click "Register"
  4. User is automatically logged in

Programmatically

use App\Models\User;
use Illuminate\Support\Facades\Hash;

$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'password' => Hash::make('password123'),
]);

Logging In Users

Via Web Interface

  1. Visit /login
  2. Enter email and password
  3. Optionally check "Remember Me"
  4. Click "Login"

Programmatically

use Illuminate\Support\Facades\Auth;

// Attempt login
if (Auth::attempt(['email' => $email, 'password' => $password])) {
    // Authentication passed
    return redirect()->intended('admin-dashboard.html');
}

// With remember me
Auth::attempt($credentials, $remember = true);

// Login by user ID
Auth::loginUsingId(1);

// Login without credentials check (e.g., after registration)
Auth::login($user);

Logging Out

use Illuminate\Support\Facades\Auth;

Auth::logout();
request()->session()->invalidate();
request()->session()->regenerateToken();

return redirect('/login');

Checking Authentication

In Controllers

use Illuminate\Support\Facades\Auth;

// Check if user is logged in
if (Auth::check()) {
    // User is authenticated
}

// Get current user
$user = Auth::user();

// Get user ID
$id = Auth::id();

// Check for guest
if (Auth::guest()) {
    // User is not authenticated
}

In Blade Templates

@auth
    <!-- User is logged in -->
    <p>Welcome, {{ auth()->user()->name }}!</p>
@endauth

@guest
    <!-- User is not logged in -->
    <a href="route-login.html">Login</a>
@endguest

<!-- Get current user -->
{{ auth()->user()->email }}
{{ auth()->id() }}

Protecting Routes

Middleware

use Illuminate\Support\Facades\Route;

// Single route
Route::get('admin-dashboard.html', [DashboardController::class, 'index'])
    ->middleware('auth');

// Route group
Route::middleware(['auth'])->group(function () {
    Route::get('admin-dashboard.html', [DashboardController::class, 'index']);
    Route::get('admin-profile.html', [ProfileController::class, 'edit']);
    Route::get('admin-settings.html', [SettingsController::class, 'index']);
});

// Multiple middleware
Route::middleware(['auth', 'verified'])->group(function () {
    // These routes require authentication AND email verification
    Route::get('admin-dashboard.html', [DashboardController::class, 'index']);
});

// Guest only (not logged in)
Route::middleware(['guest'])->group(function () {
    Route::get('/login', [AuthController::class, 'showLogin']);
    Route::get('/register', [AuthController::class, 'showRegister']);
});

In Controllers

class DashboardController extends Controller
{
    public function __construct()
    {
        // Require authentication for all methods
        $this->middleware('auth');

        // Require authentication except for specific methods
        $this->middleware('auth')->except(['index', 'show']);

        // Require authentication only for specific methods
        $this->middleware('auth')->only(['create', 'store', 'edit', 'update']);
    }
}

Password Reset Flow

User Requests Reset

  1. User visits /forgot-password
  2. Enters their email address
  3. System sends password reset email
  4. User clicks link in email
  5. User enters new password
  6. Password is updated

Customizing Reset Emails

Edit the notification:

// app/Models/User.php

use Illuminate\Auth\Notifications\ResetPassword;

public function sendPasswordResetNotification($token)
{
    $url = url('/reset-password/'.$token.'?email='.$this->email);

    // Send custom notification
    $this->notify(new ResetPassword($url));
}

Or create custom notification:

php artisan make:notification CustomResetPassword
// app/Notifications/CustomResetPassword.php

public function toMail($notifiable)
{
    return (new MailMessage)
        ->subject('Reset Your Password')
        ->line('You requested a password reset.')
        ->action('Reset Password', url(config('app.url').route('password.reset', $this->token, false)))
        ->line('This link will expire in 60 minutes.');
}

Email Verification

Enable Email Verification

  1. Make User model implement MustVerifyEmail:
// app/Models/User.php

use Illuminate\Contracts\Auth\MustVerifyEmail;

class User extends Authenticatable implements MustVerifyEmail
{
    // ...
}
  1. Protect routes with verified middleware:
Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('admin-dashboard.html', [DashboardController::class, 'index']);
});
  1. Users must verify email before accessing protected routes

Customizing Verification Emails

// app/Models/User.php

use Illuminate\Auth\Notifications\VerifyEmail;

public function sendEmailVerificationNotification()
{
    $this->notify(new VerifyEmail);
}

Resending Verification Email

use Illuminate\Http\Request;

public function resend(Request $request)
{
    if ($request->user()->hasVerifiedEmail()) {
        return redirect()->intended('admin-dashboard.html');
    }

    $request->user()->sendEmailVerificationNotification();

    return back()->with('status', 'verification-link-sent');
}

User Profile Management

View Profile

// app/Http/Controllers/ProfileController.php

public function edit(Request $request)
{
    return view('profile.edit', [
        'user' => $request->user(),
    ]);
}

Update Profile

public function update(Request $request)
{
    $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|email|max:255|unique:users,email,'.$request->user()->id,
    ]);

    $request->user()->fill([
        'name' => $request->name,
        'email' => $request->email,
    ]);

    if ($request->user()->isDirty('email')) {
        $request->user()->email_verified_at = null;
    }

    $request->user()->save();

    return back()->with('status', 'profile-updated');
}

Update Password

use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;

public function updatePassword(Request $request)
{
    $validated = $request->validate([
        'current_password' => ['required', 'current_password'],
        'password' => ['required', Password::defaults(), 'confirmed'],
    ]);

    $request->user()->update([
        'password' => Hash::make($validated['password']),
    ]);

    return back()->with('status', 'password-updated');
}

Delete Account

use Illuminate\Support\Facades\Auth;

public function destroy(Request $request)
{
    $request->validate([
        'password' => ['required', 'current_password'],
    ]);

    $user = $request->user();

    Auth::logout();

    $user->delete();

    $request->session()->invalidate();
    $request->session()->regenerateToken();

    return redirect('/');
}

Customizing Authentication

Wallpaper Authentication Variant

UltraViolet includes three authentication design variants. Customize your authentication pages to match your brand. Learn more in the Page Templates guide.

Redirect After Login

Edit app/Providers/RouteServiceProvider.php:

public const HOME = 'admin-dashboard.html';

Or in login controller:

protected function authenticated(Request $request, $user)
{
    if ($user->is_admin) {
        return redirect('admin-dashboard.html');
    }

    return redirect('/dashboard');
}

Custom Login Logic

Create custom authentication:

use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    // Add custom conditions
    $credentials['is_active'] = 1;

    if (Auth::attempt($credentials, $request->filled('remember'))) {
        $request->session()->regenerate();

        // Custom logic after login
        activity()->log('User logged in');

        return redirect()->intended('admin-dashboard.html');
    }

    return back()->withErrors([
        'email' => 'Invalid credentials or account is not active.',
    ])->onlyInput('email');
}

Rate Limiting

Breeze includes rate limiting by default. Customize in app/Http/Controllers/Auth/LoginController.php:

use Illuminate\Support\Facades\RateLimiter;

protected function checkTooManyFailedAttempts(Request $request)
{
    $key = 'login.'.$request->ip();

    if (RateLimiter::tooManyAttempts($key, 5)) {
        $seconds = RateLimiter::availableIn($key);

        throw ValidationException::withMessages([
            'email' => "Too many login attempts. Try again in {$seconds} seconds.",
        ]);
    }
}

Remember Me Duration

Edit config/session.php:

'lifetime' => 120, // Session lifetime in minutes
'expire_on_close' => false,

Or in login controller:

// Remember for 30 days
Auth::login($user, $remember = true);
config(['session.lifetime' => 43200]); // 30 days in minutes

Adding User Roles

Create Roles

php artisan make:migration add_role_to_users_table
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('role')->default('user');
    });
}
php artisan migrate

Check Roles

// In User model
public function isAdmin()
{
    return $this->role === 'admin';
}

public function isModerator()
{
    return $this->role === 'moderator';
}

// In controllers
if (auth()->user()->isAdmin()) {
    // Admin only logic
}

// In Blade
@if(auth()->user()->isAdmin())
    <a href="../uv-vertical/admin-dashboard.html">Admin Panel</a>
@endif

Role Middleware

php artisan make:middleware CheckRole
// app/Http/Middleware/CheckRole.php

public function handle(Request $request, Closure $next, ...$roles)
{
    if (!$request->user() || !in_array($request->user()->role, $roles)) {
        abort(403, 'Unauthorized');
    }

    return $next($request);
}

Register middleware in app/Http/Kernel.php:

protected $middlewareAliases = [
    'role' => \App\Http\Middleware\CheckRole::class,
];

Use in routes:

Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::get('admin-users.html', [UserController::class, 'index']);
});

Route::middleware(['auth', 'role:admin,moderator'])->group(function () {
    Route::get('admin-posts.html', [PostController::class, 'index']);
});

Social Authentication (OAuth)

Install Laravel Socialite

composer require laravel/socialite

Configure Providers

Add to config/services.php:

'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_REDIRECT_URL'),
],

'github' => [
    'client_id' => env('GITHUB_CLIENT_ID'),
    'client_secret' => env('GITHUB_CLIENT_SECRET'),
    'redirect' => env('GITHUB_REDIRECT_URL'),
],

Add to .env:

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URL=http://localhost:8000/auth/google/callback

Create Routes

use Laravel\Socialite\Facades\Socialite;

Route::get('/auth/{provider}', function ($provider) {
    return Socialite::driver($provider)->redirect();
});

Route::get('/auth/{provider}/callback', function ($provider) {
    $socialiteUser = Socialite::driver($provider)->user();

    $user = User::updateOrCreate([
        'email' => $socialiteUser->email,
    ], [
        'name' => $socialiteUser->name,
        'provider_id' => $socialiteUser->id,
        'provider' => $provider,
    ]);

    Auth::login($user);

    return redirect('admin-dashboard.html');
});

Add Buttons to Login Page

<div class="text-center mt-4">
    <p class="text-muted">Or sign in with</p>
    <div class="d-flex gap-2 justify-content-center">
        <a href="url-auth-google.html" class="btn btn-outline-primary">
            <i class="fab fa-google"></i> Google
        </a>
        <a href="url-auth-github.html" class="btn btn-outline-primary">
            <i class="fab fa-github"></i> GitHub
        </a>
    </div>
</div>

Security Best Practices

1. Use Strong Passwords

Configure in app/Providers/AppServiceProvider.php:

use Illuminate\Validation\Rules\Password;

Password::defaults(function () {
    return Password::min(8)
        ->letters()
        ->mixedCase()
        ->numbers()
        ->symbols()
        ->uncompromised();
});

2. Enable HTTPS

In .env:

APP_URL=https://yourdomain.com
SESSION_SECURE_COOKIE=true

3. CSRF Protection

Laravel includes CSRF protection by default. Ensure your forms include:

<form method="POST" action="/login">
    @csrf
    <!-- form fields -->
</form>

4. Rate Limiting

Protect against brute force:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('login', function (Request $request) {
    return Limit::perMinute(5)->by($request->email.$request->ip());
});

5. Session Security

In config/session.php:

'http_only' => true,     // Prevent JavaScript access
'same_site' => 'strict', // CSRF protection
'secure' => env('SESSION_SECURE_COOKIE', false), // HTTPS only

Testing Authentication

Feature Tests

use App\Models\User;
use Tests\TestCase;

class AuthenticationTest extends TestCase
{
    public function test_users_can_authenticate()
    {
        $user = User::factory()->create();

        $response = $this->post('/login', [
            'email' => $user->email,
            'password' => 'password',
        ]);

        $this->assertAuthenticated();
        $response->assertRedirect('admin-dashboard.html');
    }

    public function test_users_cannot_authenticate_with_invalid_password()
    {
        $user = User::factory()->create();

        $this->post('/login', [
            'email' => $user->email,
            'password' => 'wrong-password',
        ]);

        $this->assertGuest();
    }
}

Troubleshooting

Session Not Persisting

# Clear session files
php artisan session:clear

# Check session driver in .env
SESSION_DRIVER=file  # or database, redis

Password Reset Not Working

# Check mail configuration
php artisan config:clear

# Test email
php artisan tinker
Mail::raw('Test email', function($msg) {
    $msg->to('test@example.com')->subject('Test');
});

CSRF Token Mismatch

# Clear application cache
php artisan cache:clear
php artisan config:clear
php artisan view:clear

# Check if @csrf directive is in forms

Next Steps

Support

Need help with Laravel authentication?