Neev is an enterprise-grade Laravel package for user authentication, team management, and multi-tenancy in SaaS applications. The package is headless by default — API, OAuth/SSO, and email flows work standalone — with an optional Blade starter kit whose pages are ejected into your app at install (RFC 002). See the main README for a quick overview and getting started guide.
Start here to set up and use Neev in your application.
| Guide | Description |
|---|---|
| Installation | Step-by-step setup: Composer, migrations, environment, publishing assets |
| Configuration | All config/neev.php options with explanations |
| Authentication | Password, magic link, passkey, OAuth, and SSO login flows |
| SPA Authentication | Wiring a same-origin React/Vue SPA to neev: cookie mode, CSRF, CORS, SSO hand-off, troubleshooting |
| MFA | Authenticator apps (TOTP), email OTP, and recovery codes |
| Teams | Team creation, invitations, roles, domain federation |
| Multi-Tenancy | Identity strategy, tenant isolation, subdomain/custom domain, enterprise SSO |
| Security | Brute force protection, password policies, login tracking, session management |
| CLI Commands | All Artisan commands: tenant provisioning, domains, members, auth/SSO, team lifecycle |
Endpoint and route details for building against Neev.
| Reference | Description |
|---|---|
| API Reference | Every REST endpoint with request/response examples |
| Web Routes | All Blade-rendered web routes and view files (require the Blade starter kit, 'ui' => 'blade') |
Design decisions and internal patterns — useful when extending Neev or contributing.
| Document | Description |
|---|---|
| Design Principles | What is enforced vs configurable vs left to the app — the four-layer boundary every PR is judged against |
| Architecture | Identity strategy (shared vs isolated), tenant/team concepts, context lifecycle |
| Architecture Internals | Interfaces, traits, services, coding standards, anti-patterns |
Design proposals and their implementation status.
| Document | Status | Description |
|---|---|---|
| SPA Cookie Mode | Fully implemented (phases 1–4; consumer guide: SPA Authentication) | HttpOnly-cookie auth + signed double-submit CSRF for same-origin SPAs. Additive to the existing bearer-token API. Driven by the TAILLOG web rebuild and otper. |
| RFC 002 — Headless Core + Starter Kits | Phase A implemented | Package is fully headless (Fortify-style); Blade UI ejects into the app as a starter kit at install; email templates app-owned with a documented variable contract; React kit reserved as a future kit. |
| RFC 003 — Per-Group Auth Policies | Proposed (resolves RFC-001 §6) | One tenant, multiple user populations: policy-per-role/domain auth methods, identifier-first routing, platform policies as null-owner rows, migration from tenant/team auth settings. |
| Email Reputation Package | v1 scope decided | Standalone classification-only package (free/disposable/relay/unknown); network tier deferred; neev takes no dependency on it. |
| RFC 004 — Device Authorization Grant | Proposed | RFC 8628 for TVs/consoles/kiosks/CLIs: device shows a code, user approves on their phone through the full neev auth stack, device polls for a normal neev token. |
| RFC 005 — OAuth 2.1 Authorization Server | Proposed (gated behind RFC 004) | Neev as identity provider: auth-code + mandatory PKCE, refresh rotation, client credentials — scopes on neev's own tokens; build-vs-Passport analysis included. |
neev/
├── config/
│ └── neev.php # Configuration file
├── database/
│ ├── factories/ # Model factories (testing)
│ └── migrations/ # Database migrations
├── resources/
│ └── views/
│ └── emails/ # Email templates (headless fallbacks; ejected to the app at install)
├── routes/
│ ├── neev.php # Web and API routes
│ └── sso.php # Tenant SSO routes
├── stubs/
│ └── blade/
│ └── views/ # Blade starter kit page views (ejected via neev:ui blade)
└── src/
├── Commands/ # Artisan commands
├── Contracts/ # Interfaces (ContextContainer, HasMembers, etc.)
├── Events/ # Auth, MFA, team/tenant lifecycle, and domain events
├── Http/
│ ├── Controllers/ # Auth, User, Team, Role, TenantDomain, TenantSSO
│ └── Middleware/ # Auth, tenant, team, context middleware
├── Mail/ # 5 Mailables (verification, OTP, login link, etc.)
├── Models/ # User, Team, Tenant, AccessToken, Domain, etc.
├── Rules/ # PasswordHistory, PasswordUserData
├── Scopes/ # TenantScope, TeamScope
├── Services/ # ContextManager, TenantResolver, TenantSSOManager, etc.
└── Traits/ # HasTeams, HasMultiAuth, BelongsToTenant, BelongsToTeam, etc.
These are pre-composed groups you apply to route groups.
| Group | Pipeline |
|---|---|
neev:web |
TenantMiddleware > ResolveTeamMiddleware > NeevMiddleware (session auth) > EnsureTenantMembership > BindContextMiddleware |
neev:api |
TenantMiddleware > ResolveTeamMiddleware > NeevAPIMiddleware (token auth) > EnsureTenantMembership > BindContextMiddleware |
neev:login |
TenantMiddleware > ResolveTeamMiddleware > JwtLoginMiddleware (MFA JWT auth) > EnsureTenantMembership > BindContextMiddleware |
neev:tenant |
TenantMiddleware (required) > ResolveTeamMiddleware > BindContextMiddleware |
When tenant is disabled, tenant-specific middleware are no-ops.
These can be applied individually to specific routes.
| Alias | Description |
|---|---|
neev:active-team |
Blocks access when team is inactive/waitlisted |
neev:active-tenant |
Blocks access when tenant is inactive |
neev:tenant-member |
Ensures user is a member of the current tenant |
neev:resolve-team |
Resolves team from route parameter (slug or ID) |
neev:ensure-sso |
Enforces SSO-only access for the current context |
neev:password-not-expired |
Blocks access when the user's password has expired |
neev:verified-email |
Blocks access until the user's email is verified |
// Apply a middleware group to your routes
Route::middleware(['neev:web'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
});
// Apply individual middleware aliases after the group
Route::middleware(['neev:web', 'neev:active-team'])->group(function () {
Route::get('/projects', [ProjectController::class, 'index']);
});Ordering: Always place
neev:weborneev:apibefore any alias middleware. Aliases likeneev:active-teamandneev:ensure-ssodepend on context being resolved by the group middleware first.BindContextMiddleware(the last middleware in each group) locks the context as immutable — custom middleware that needs tenant/team/user context should run after the Neev group.
Extend Neev's models with your own, then update the config:
// app/Models/User.php
class User extends \Ssntpl\Neev\Models\User
{
protected $fillable = ['name', 'username', 'active', 'custom_field'];
}// config/neev.php
'user_model' => App\Models\User::class,
'team_model' => App\Models\Team::class,
'tenant_model' => App\Models\Tenant::class,Neev fires Laravel's native auth events where semantics match, and its own events for package concepts.
Laravel native events:
| Event | Fired when |
|---|---|
Illuminate\Auth\Events\Registered |
User registers (web, API, OAuth, SSO auto-provision) |
Illuminate\Auth\Events\PasswordReset |
Password is reset via a reset link (web or API) |
Illuminate\Auth\Events\Lockout |
Login throttle rejects an attempt |
Neev events (Ssntpl\Neev\Events\):
| Event | Payload | Fired when |
|---|---|---|
LoggedIn |
$user |
User logs in (any method) |
LoggedOut |
$user |
User logs out |
PasswordChanged |
$user |
Password changes (including resets) |
EmailVerified |
$user |
Email is verified for the first time |
MfaMethodAdded |
$user, $method |
An MFA method is configured |
MfaMethodRemoved |
$user, $method |
An MFA method is removed |
RecoveryCodesGenerated |
$user |
Recovery codes are (re)generated |
TeamCreated / TeamDeleted |
$team |
A team is created / deleted |
MemberAdded / MemberRemoved |
$team, $user |
Team membership changes |
TenantCreated |
$tenant |
A tenant is created |
SsoUserProvisioned |
$user, $owner |
SSO auto-provisions a new user |
DomainVerified |
$domain |
A domain passes DNS verification for the first time |
DomainReverified |
$domain |
A domain that had been failing re-verification passes again |
DomainVerificationFailed |
$domain |
A previously verified domain first fails re-verification |
The model-lifecycle events (TeamCreated, TeamDeleted, TenantCreated, MemberAdded, MemberRemoved) implement ShouldDispatchAfterCommit, so listeners never observe state from a transaction that later rolls back. EmailVerified is likewise dispatched after commit.
Note: neev's User model deliberately does not implement
MustVerifyEmail. If your custom user model does, Laravel's auto-registeredSendEmailVerificationNotificationlistener will also react toRegistered— disable it or neev's own verification mail to avoid duplicate emails.
// app/Listeners/LogSuccessfulLogin.php
use Ssntpl\Neev\Events\LoggedIn;
class LogSuccessfulLogin
{
public function handle(LoggedIn $event)
{
activity()->log("User {$event->user->name} logged in");
}
}See CLI Commands for full reference with options and examples.
| Command | Description |
|---|---|
neev:install |
Interactive setup wizard (tenant, teams, starter kit) |
neev:ui |
Eject a frontend starter kit (blade/none) and the email templates |
neev:download-geoip |
Download MaxMind GeoLite2 database |
neev:clean-login-attempts |
Remove old login attempt records |
neev:tenant:create |
Create a tenant (isolated) or team (shared) |
neev:tenant:list |
List tenants or teams |
neev:tenant:show |
Show tenant/team details by ID, slug, or domain |
neev:domain:add |
Add a domain to a tenant or team |
neev:domain:verify |
Verify a domain via DNS TXT record |
neev:domain:list |
List domains |
neev:member:add |
Add a user to a team (bypasses invitation) |
neev:member:remove |
Remove a user from a team |
neev:member:list |
List members of a team or tenant |
neev:auth:configure |
Configure auth method (password/SSO) for a tenant or team |
neev:auth:show |
Display auth configuration |
neev:team:activate |
Activate or deactivate a team |
- PHP 8.3+
- Laravel 12.x
- MySQL, PostgreSQL, or SQLite
- MaxMind GeoLite2 account (IP geolocation for login tracking)
- Redis/Memcached (distributed rate limiting)
- Mail server (email verification, OTP, magic links, invitations)
- GitHub Issues
- Email: support@ssntpl.com