quvel/auth

Authentication support for the Quvel framework - handles login, logout, registration, email verification, and OAuth

Installs: 4

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/quvel/auth

v1.0.0 2025-12-21 07:20 UTC

This package is not auto-updated.

Last update: 2025-12-22 05:47:08 UTC


README

API-first authentication package that extends Laravel Fortify with JSON responses, OAuth support, and enhanced features. Uses Fortify 1:1 with minimal overrides via container bindings.

Philosophy

This package wraps Laravel Fortify with quality-of-life improvements:

  • API-First Responses - Returns JSON with user data instead of redirects
  • OAuth/Socialite Integration - Social login with secure nonce-based flow
  • Zero Configuration - Auto-discovers and binds overrides via service provider
  • Fortify Compatible - Use standard config/fortify.php to enable/disable features

Installation

1. Install Fortify and Sanctum

composer require laravel/fortify laravel/sanctum laravel/socialite
php artisan fortify:install
php artisan sanctum:install
php artisan migrate

2. Install Quvel Auth

composer require quvel/auth

That's it. The package auto-discovers and registers its service provider.

3. Configure Fortify

Edit config/fortify.php:

'prefix' => 'auth',  // Routes at /auth/*
'views' => false,    // API-only mode

'features' => [
    Features::registration(),
    Features::resetPasswords(),
    // Features::emailVerification(),
    Features::updateProfileInformation(),
    Features::updatePasswords(),
    Features::twoFactorAuthentication([
        'confirm' => true,
        'confirmPassword' => true,
    ]),
],

4. Publish Migrations (Optional)

php artisan vendor:publish --tag=quvel-auth-migrations
php artisan migrate

How It Works

Quvel Auth uses Laravel's container to override Fortify's default implementations:

// Our AuthServiceProvider automatically binds these:

// Fortify uses our custom CreateNewUser action
$app->singleton(CreatesNewUsers::class, CreateNewUser::class);

// Fortify uses our JSON LoginResponse instead of redirects
$app->singleton(LoginResponseContract::class, LoginResponse::class);

// etc.

When Fortify's controllers run, they resolve these contracts from the container and get our implementations. No route overrides needed.

Routes

Fortify provides core routes (login, register), we provide the rest:

# Fortify Routes (using our container bindings)
POST   /auth/login                              → JSON with user data
POST   /auth/register                           → JSON with user data

# Our Custom Routes
GET    /auth/session                            → Current session info
POST   /auth/logout                             → Logout response

# Password Management
POST   /auth/forgot-password
POST   /auth/reset-password

# Two-Factor Authentication
POST   /auth/two-factor-challenge
POST   /auth/user/two-factor-authentication     → Enable 2FA
DELETE /auth/user/two-factor-authentication     → Disable 2FA
GET    /auth/user/two-factor-qr-code
GET    /auth/user/two-factor-recovery-codes
POST   /auth/user/two-factor-recovery-codes     → Regenerate codes

# Profile Management
PUT    /auth/user/profile-information
PUT    /auth/user/password

# OAuth (Socialite)
GET    /auth/provider/{provider}/redirect
GET    /auth/provider/{provider}/callback
POST   /auth/provider/{provider}/create-nonce
POST   /auth/provider/{provider}/redeem-nonce

API Responses

All responses are JSON with consistent structure:

Login Success (no 2FA):

{
  "message": "Login successful",
  "user": { "id": 1, "name": "...", "email": "..." },
  "two_factor": false
}

Login Requires 2FA:

{
  "message": "Two-factor authentication required",
  "two_factor": true
}

Registration:

{
  "message": "Registration successful",
  "user": { "id": 1, "name": "...", "email": "..." }
}

Configuration

Fortify Features

Enable/disable features in config/fortify.php:

'features' => [
    Features::registration(),           // POST /auth/register
    Features::resetPasswords(),         // POST /auth/forgot-password, etc.
    Features::emailVerification(),      // Email verification routes
    Features::updateProfileInformation(), // PUT /auth/user/profile-information
    Features::updatePasswords(),        // PUT /auth/user/password
    Features::twoFactorAuthentication(), // All 2FA routes
],

Socialite (OAuth)

Configure providers in config/services.php:

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

Disable OAuth in config/quvel-auth.php:

'socialite' => [
    'enabled' => false,
],

Rate Limiting

Automatically configured (5 requests/minute for login and 2FA). Override in your AppServiceProvider if needed:

use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('login', fn ($request) =>
    Limit::perMinute(10)->by($request->email . $request->ip())
);

Customization

Override Response Classes

Create your own response:

// app/Http/Responses/CustomLoginResponse.php
class CustomLoginResponse implements LoginResponseContract
{
    public function toResponse($request): JsonResponse
    {
        return response()->json([
            'user' => $request->user()->load('roles'),
            'permissions' => $request->user()->getAllPermissions(),
        ]);
    }
}

Bind in your AppServiceProvider:

$this->app->singleton(
    \Laravel\Fortify\Contracts\LoginResponse::class,
    \App\Http\Responses\CustomLoginResponse::class
);

Override Actions

Same pattern for actions:

$this->app->singleton(
    \Laravel\Fortify\Contracts\CreatesNewUsers::class,
    \App\Actions\Fortify\CreateNewUser::class
);

Advanced: Publish Routes

For full route customization:

php artisan vendor:publish --tag=quvel-auth-routes

Then disable package routes in config/quvel-auth.php:

'routes' => [
    'enabled' => false,
],

Troubleshooting

Routes not showing?

php artisan route:list --path=auth

Check that Fortify features are enabled and views => false.

Rate limiter errors? Clear config cache:

php artisan config:clear

Need to customize? Check AuthServiceProvider@registerFortifyOverrides() to see all container bindings.

License

MIT