laravel-auth maintained by laraverse
laraverse/laravel-auth
Laravel Sanctum token APIs with 6-digit OTP email verification, OTP password reset, soft-deleted accounts, and JSON-driven RBAC (Spatie Permission).
Requirements
- PHP 8.2+
- Laravel 11, 12, or 13
- laravel/sanctum ^4 or ^5
- spatie/laravel-permission ^6, ^7, or ^8
Those packages are required by this library and must be installed in the host app.
Install
composer require laraverse/laravel-auth
php artisan publish:sanctum-auth --force
php artisan migrate
php artisan db:seed --class=Database\\Seeders\\LaravelAuthSeeder
composer remove laraverse/laravel-auth
publish:sanctum-auth
Copies all Sanctum auth and RBAC source into the host app (namespaces become App\...) so the code lives in your project. After this, you can remove the package and the APIs still work.
php artisan publish:sanctum-auth --force
php artisan publish:sanctum-auth --force --migrate --seed
--force overwrites existing files (including app/Models/User.php). --migrate / --seed run after publishing.
Duplicate *personal_access_tokens* files in database/migrations are deleted; Sanctum creates that table from vendor.
php artisan publish:session-auth currently forwards to publish:sanctum-auth (session/web auth is not implemented).
This publishes:
| Destination | What |
|---|---|
app/Http/Controllers/Auth/ |
Register, login, logout, email OTP, password, profile |
app/Http/Requests/ |
Form requests |
app/Http/Resources/UserResource.php |
API user resource |
app/Http/Middleware/ |
RoleMiddleware, PermissionMiddleware |
routes/auth.php |
Auth API routes (/api/auth/...) |
app/Services/ |
AuthService, OtpService, PasswordService, ProfileService, RoleAndPermissionService |
app/Notifications/ |
Email verification and password-reset OTP mails |
app/Traits/ApiResponse.php |
JSON response helper |
app/Concerns/HasUserPermissions.php |
Direct-permission checks |
app/Enums/ |
UserRole, OtpPurpose |
app/Models/ |
User, Role, Permission, Otp |
app/Docs/roles_and_permissions.json |
RBAC JSON |
app/Console/Commands/PermissionAssignCommand.php |
permission:assign |
database/migrations/ |
Users (if missing), permissions/roles, soft deletes, otps |
database/seeders/ |
PermissionSeeder, RoleSeeder, LaravelAuthSeeder |
database/factories/UserFactory.php |
User factory |
config/laravel-auth.php |
App User model; load_package_routes is false |
app/Providers/AuthApiServiceProvider.php |
Loads routes/auth.php, middleware, Spatie models |
postman/Laravel-Auth.postman_collection.json |
Postman collection for all auth APIs |
It also registers AuthApiServiceProvider in bootstrap/providers.php. After this command, package routes are disabled so only the published files handle auth.
Then seed with:
php artisan db:seed --class=Database\\Seeders\\LaravelAuthSeeder
--force overwrites app/Models/User.php. Review that file after publishing.
Remove the package after publishing
Yes — the app can keep working without laraverse/laravel-auth once the code is published.
publish:sanctum-auth copies auth/RBAC into app/ and routes/auth.php, registers AuthApiServiceProvider, and adds laravel/sanctum and spatie/laravel-permission to the host composer.json (so Composer does not delete them when you remove this package).
Then:
composer remove laraverse/laravel-auth
Do not remove Sanctum or Spatie. Auth APIs, OTP, and RBAC then run only from your published files.
User model
If you do not run publish:sanctum-auth, add these traits to your User model:
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Sanctum\HasApiTokens;
use Laraverse\LaravelAuth\Concerns\HasUserPermissions;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmailContract
{
use HasApiTokens, HasRoles, SoftDeletes, HasUserPermissions, MustVerifyEmail;
}
After publish:sanctum-auth, use the published App\Models\User (traits come from App\Concerns).
Auth guard
In config/auth.php, use a Sanctum guard (this package defaults laravel-auth.guard to sanctum):
'guards' => [
'sanctum' => [
'driver' => 'sanctum',
'provider' => 'users',
],
],
Set LARAVERSE_AUTH_GUARD=sanctum in .env if you override the default.
Point the users provider at App\Models\User after publishing, or at the package model:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\Models\User::class,
],
],
Seed roles and permissions before registering users.
API
Prefix: api/auth (LARAVERSE_AUTH_PREFIX). Guest routes need no token. Protected routes use Authorization: Bearer {token}.
Routes live in routes/auth.php after publish:sanctum-auth.
| Method | Path | Body | Auth |
|---|---|---|---|
| POST | /api/auth/register |
name, email, password, password_confirmation |
Guest |
| POST | /api/auth/email/verify |
email, otp |
Guest |
| POST | /api/auth/email/resend |
email |
Guest |
| POST | /api/auth/login |
email, password |
Guest (verified users only) |
| POST | /api/auth/logout |
— | Sanctum (revokes current token) |
| POST | /api/auth/forgot-password |
email |
Guest |
| POST | /api/auth/reset-password |
email, otp, password, password_confirmation |
Guest |
| PUT | /api/auth/password |
current_password, password, password_confirmation |
Sanctum |
| GET | /api/auth/profile |
— | Sanctum + view-profile |
| PUT | /api/auth/profile |
name, email |
Sanctum + update-profile |
| DELETE | /api/auth/account |
— | Sanctum (soft delete) |
Register creates an unverified user, assigns the default user role, and emails an OTP. No token is issued until login after verification.
Login returns a Sanctum token and user resource. Unverified users get 403. Soft-deleted users cannot log in.
Changing profile email clears email_verified_at and sends a new verification OTP.
OTP
- 6-digit numeric codes, emailed (never returned in JSON)
- Stored hashed (
Hash::make) - Default TTL 10 minutes (
laravel-auth.otp.ttl_minutes) - Purposes: email verification (register) and password reset (forgot-password)
- Resend invalidates unused codes for the same email + purpose
- Failed verifies increment attempts (max 5)
Soft delete
DELETE /api/auth/account sets deleted_at, revokes all tokens, and prefixes the email with deleted_{id}_ so the original address can register again. Soft-deleted users cannot log in.
RBAC
Published JSON: app/Docs/roles_and_permissions.json (package source: resources/rbac/roles_and_permissions.json). Override path with laravel-auth.rbac_json_path.
| Role | Permissions |
|---|---|
admin |
dashboard, view-profile, update-profile |
user |
dashboard, view-profile, update-profile |
Re-sync a role’s users after JSON changes:
php artisan permission:assign admin
Example responses
Success (ApiResponse::successResponse):
{
"success": true,
"message": "Logged in successfully",
"data": {
"token": "1|plainTextToken",
"token_type": "Bearer",
"user": {
"id": 1,
"name": "Jane Doe",
"email": "jane@example.com"
}
}
}
Error (ApiResponse::errorResponse):
{
"success": false,
"message": "Given data is invalid",
"errors": {
"email": ["The email field is required."]
}
}
Postman
After publish:sanctum-auth, import:
postman/Laravel-Auth.postman_collection.json
In Postman: Import → File and select that JSON.
Collection variables: base_url (default http://localhost:8000), email, password, otp, token. Login saves token automatically. Put OTP codes from storage/logs/laravel.log when MAIL_MAILER=log.