Multi-vendor authentication for Laravel 13 — Blade UI, REST API, roles, OTP, and email/phone verification.
- PHP
^8.3 - Laravel
^12.0 - laravel/sanctum
^4.0(API tokens) - spatie/laravel-translatable
^6.14(installed automatically with this package)
- Registration, login, logout (web session + API Sanctum tokens)
- Email/password and phone/password (configurable per project)
- OTP via phone or email (login, register, password reset, verification)
- Roles:
super_admin,admin,vendor,vendor_staff,customer,delivery - Enum roles (default,
rolecolumn) or Spatie Permission (role_driver=spatie) - Guest locale switcher on auth pages (
en/ar) - Swappable SMS provider for OTP (
SmsSenderInterface)
After the package is published:
composer require kango/authAdd the repository to the host app composer.json, then require the package:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/your-org/kango-auth"
}
],
"minimum-stability": "stable",
"prefer-stable": truecomposer require kango/auth:^1.0Use a tagged release (e.g. v1.0.0). The @dev constraint is only for local monorepo development.
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrateThis creates Sanctum’s personal_access_tokens table (required for API auth).
php artisan vendor:publish --tag=kango-auth-configAvailable publish tags:
| Tag | Purpose |
|---|---|
kango-auth-config |
config/auth-package.php |
kango-auth-migrations |
Copy migrations into database/migrations (only if you need to customize them) |
kango-auth-views |
Copy Blade views into resources/views/vendor/kango-auth |
By default, migrations and views are loaded from the package — publishing is optional.
The package registers migrations for:
users(withrole,phone,vendor_id, verification timestamps, soft deletes)auth_package_otpsauth_package_password_reset_tokens
Important: If your Laravel app already has a default
create_users_tablemigration, remove or skip it before runningphp artisan migrateto avoid a duplicateuserstable error. This package owns theusersschema for auth.
Then migrate:
php artisan migrateCreate or update app/Models/User.php:
<?php
namespace App\Models;
use Kango\Auth\Models\User as BaseUser;
class User extends BaseUser
{
//
}Point the user provider at your application model:
use App\Models\User;
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => User::class,
],
],Add to .env:
AUTH_PACKAGE_USER_MODEL=App\Models\User
AUTH_PACKAGE_ROLE_DRIVER=enum
# Auth methods (enable what you need)
AUTH_PACKAGE_EMAIL_PASSWORD=false
AUTH_PACKAGE_PHONE_PASSWORD=true
AUTH_PACKAGE_PHONE_OTP=false
AUTH_PACKAGE_EMAIL_OTP=false
# Verification gates (API + web)
AUTH_PACKAGE_EMAIL_VERIFICATION_REQUIRED=true
AUTH_PACKAGE_PHONE_VERIFICATION_REQUIRED=true
# OTP rate limiting
AUTH_PACKAGE_OTP_THROTTLE_SECONDS=60
AUTH_PACKAGE_OTP_THROTTLE_MAX=1
# Optional: custom SMS driver (must implement Kango\Auth\Contracts\SmsSenderInterface)
# AUTH_PACKAGE_SMS_SENDER=App\\Services\\YourSmsSenderRegister the verification middleware alias and optional guest redirect:
use Kango\Auth\Http\Middleware\EnsureVerified;
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'verified' => EnsureVerified::class,
]);
$middleware->redirectGuestsTo(fn () => route('kango.auth.login'));
})Protect routes that require a verified user:
Route::middleware(['auth', 'verified'])->group(function () {
// ...
});php artisan config:clearMain file: config/auth-package.php (merged automatically; publish to override).
| Key | Env | Description |
|---|---|---|
user_model |
AUTH_PACKAGE_USER_MODEL |
Eloquent user class |
role_driver |
AUTH_PACKAGE_ROLE_DRIVER |
enum or spatie |
methods.email_password |
AUTH_PACKAGE_EMAIL_PASSWORD |
Email + password login |
methods.phone_password |
AUTH_PACKAGE_PHONE_PASSWORD |
Phone + password login |
methods.phone_otp |
AUTH_PACKAGE_PHONE_OTP |
Phone OTP flows |
methods.email_otp |
AUTH_PACKAGE_EMAIL_OTP |
Email OTP flows |
verification.email_required |
AUTH_PACKAGE_EMAIL_VERIFICATION_REQUIRED |
Block until email verified |
verification.phone_required |
AUTH_PACKAGE_PHONE_VERIFICATION_REQUIRED |
Block until phone verified |
sms.sender |
AUTH_PACKAGE_SMS_SENDER |
SMS implementation class |
web.prefix |
— | URL prefix for Blade routes (default: auth) |
api.prefix / api.version |
— | API base: /api/v1/... |
Disable web or API routes by setting clients.web / clients.api to false in the published config.
composer require spatie/laravel-permissionAUTH_PACKAGE_ROLE_DRIVER=spatieuse Kango\Auth\Models\User as BaseUser;
use Spatie\Permission\Traits\HasRoles;
class User extends BaseUser
{
use HasRoles;
}Run Spatie’s migrations and seed roles that match config('auth-package.roles').
Base URL: /api/v1/auth
Protected routes require Authorization: Bearer {token} (Sanctum).
| Method | Endpoint | Auth |
|---|---|---|
| POST | /register |
Guest |
| POST | /login |
Guest |
| POST | /otp/send |
Guest (throttled) |
| POST | /otp/verify |
Guest |
| POST | /password/forgot |
Guest (throttled) |
| POST | /password/reset |
Guest |
| POST | /logout |
Sanctum |
| POST | /email/send-verification |
Sanctum (throttled) |
| POST | /email/verify |
Sanctum |
| POST | /phone/send-verification |
Sanctum (throttled) |
| POST | /phone/verify |
Sanctum |
| GET | /me |
Sanctum + verified |
JSON responses use the package’s standard success/error envelope.
Prefix: /auth (configurable via auth-package.web.prefix).
| Method | Path | Route name | Access |
|---|---|---|---|
| GET | /locale/{locale} |
kango.auth.locale |
Guest |
| GET | /register |
kango.auth.register |
Guest |
| POST | /register |
kango.auth.register.store |
Guest |
| GET | /login |
kango.auth.login |
Guest |
| POST | /login |
— | Guest |
| GET | /password/forgot |
kango.auth.password.forgot |
Guest |
| POST | /password/forgot |
kango.auth.password.forgot.store |
Guest |
| GET | /password/reset/{token} |
kango.auth.password.reset |
Guest |
| POST | /password/reset |
kango.auth.password.reset.store |
Guest |
| GET | /password/reset-phone |
kango.auth.password.reset-phone |
Guest |
| POST | /password/reset-phone |
kango.auth.password.reset-phone.store |
Guest |
| GET | /verify |
kango.auth.verify |
Auth |
| POST | /verify/email |
kango.auth.verify.email |
Auth |
| POST | /verify/phone |
kango.auth.verify.phone |
Auth |
| POST | /verify/email/resend |
kango.auth.verify.email.resend |
Auth |
| POST | /verify/phone/resend |
kango.auth.verify.phone.resend |
Auth |
| GET | /profile |
kango.auth.profile |
Auth + verified |
| POST | /logout |
kango.auth.logout |
Auth |
Role-based redirects after login are configured under auth-package.redirects.roles.
Implement Kango\Auth\Contracts\SmsSenderInterface and register the class:
AUTH_PACKAGE_SMS_SENDER=App\\Services\\YourSmsSenderIf unset, OTP codes are written to the log via LogSmsSender (local development only).
- Package installed via Composer (Packagist or tagged VCS release)
- Sanctum installed and migrated
- No duplicate Laravel
usersmigration -
App\Models\Userextends package base user -
config/auth.phpprovider usesApp\Models\User -
.envauth method and verification flags set for your product -
AUTH_PACKAGE_SMS_SENDERconfigured (do not rely on log driver in production) -
verifiedmiddleware registered; guest redirect configured if needed -
php artisan config:cacherun in deployment pipeline after env is set - HTTPS enabled for session cookies and Sanctum tokens
MIT