ssntpl/neev
Composer 安装命令:
composer require ssntpl/neev
包简介
Enterprise-grade user authentication, team management, and multi-tenancy for Laravel SaaS applications.
关键字:
README 文档
README
Neev is a comprehensive Laravel package that provides enterprise-grade user authentication, team management, and security features for SaaS applications, eliminating the need to build complex user management systems from scratch. The package is headless by default — the API, OAuth/SSO, and email flows work standalone for SPA/API frontends — with an optional Blade starter kit whose pages are ejected into your app at install and are yours to edit.
Table of Contents
- Features
- Quick Start
- Authentication Methods
- API Reference
- Web Routes
- Multi-Factor Authentication
- Team Management
- Multi-Tenancy
- Security Features
- Configuration
- Console Commands
- Database Schema
- Detailed Documentation
Features
Authentication Methods
- Password-based login with strong password policies
- Magic link authentication (passwordless login via email)
- Passkey/WebAuthn support (biometric authentication, hardware keys)
- OAuth/Social login (Google, GitHub, Microsoft, Apple)
- Tenant SSO (Microsoft Entra ID, Google Workspace, Okta)
Multi-Factor Authentication
- TOTP authenticator apps (Google Authenticator, Authy, 1Password)
- Email OTP (6-digit codes via email)
- Recovery codes (single-use backup codes)
Team Management
- Create and manage teams/organizations
- Invite members via email
- Role-based access control
- Domain-based auto-joining (federation)
- Team switching for multi-team users
Security Features
- Brute force protection with progressive delays (exponential backoff)
- Password history to prevent reuse
- Password expiry policies
- Login attempt tracking with GeoIP
- Session management
- Suspicious login detection
Multi-Tenancy
- Domain-based tenant resolution (
X-Tenantheader or host lookup) - Custom domain support with DNS verification
- Per-tenant authentication configuration
- Per-tenant SSO integration
Quick Start
1. Install via Composer
composer require ssntpl/neev
2. Run the Installation Command
php artisan neev:install
The wizard asks three questions: multi-tenant isolation (yes/no), team support (yes/no), and which frontend starter kit you want — blade ejects ready-made pages into resources/views/vendor/neev/ (app-owned), none keeps the package headless. Email templates are ejected to your app either way. You can eject a kit later with php artisan neev:ui blade.
3. Configure Environment
NEEV_JWT_SECRET="secret-for-mfa-jwts" # optional, falls back to APP_KEY MAXMIND_LICENSE_KEY="your-maxmind-key" # optional, for GeoIP login tracking
The post-login redirect is controlled by the home key in config/neev.php (defaults to /dashboard).
4. Run Migrations
php artisan migrate
5. Update Your User Model
Extend Neev's User model to inherit all traits (including BelongsToTenant for automatic tenant scoping):
use Ssntpl\Neev\Models\User as NeevUser; class User extends NeevUser { // Add your custom fields, relationships, and methods }
Then update config/neev.php:
'user_model' => App\Models\User::class,
Authentication Methods
Password Authentication
# Register curl -X POST https://yourapp.com/neev/register \ -H "Content-Type: application/json" \ -d '{ "name": "John Doe", "email": "john@example.com", "password": "SecurePass123!", "password_confirmation": "SecurePass123!" }' # Login curl -X POST https://yourapp.com/neev/login \ -H "Content-Type: application/json" \ -d '{ "email": "john@example.com", "password": "SecurePass123!" }'
Response:
{
"auth_state": "authenticated",
"token": "1|abc123def456...",
"expires_in": 1440,
"mfa_options": null,
"email_verified": true
}
expires_in is returned in minutes (defaults from login_token_expiry_minutes and mfa_jwt_expiry_minutes).
Response (with MFA enabled):
{
"auth_state": "mfa_required",
"token": "jwt_mfa_token...",
"expires_in": 30,
"mfa_options": [
"authenticator",
"email"
],
"email_verified": true
}
Magic Link (Passwordless)
# Send login link curl -X POST https://yourapp.com/neev/sendLoginLink \ -d '{"email": "john@example.com"}' # Login via link curl -X GET "https://yourapp.com/neev/loginUsingLink?id=1&signature=..."
Passkey / WebAuthn
# Get registration options curl -X GET https://yourapp.com/neev/passkeys/register/options \ -H "Authorization: Bearer {token}" # Register passkey curl -X POST https://yourapp.com/neev/passkeys/register \ -H "Authorization: Bearer {token}" \ -d '{"attestation": "{...}", "name": "My MacBook"}' # Login with passkey curl -X POST https://yourapp.com/neev/passkeys/login \ -d '{"email": "john@example.com", "assertion": "{...}"}'
OAuth / Social Login
Enable in configuration:
// config/neev.php 'oauth' => ['google', 'github', 'microsoft', 'apple'],
Redirect URLs:
GET /neev/oauth/{service}- Redirect to providerGET /neev/oauth/{service}/callback- Handle callback
API Reference
All API routes are prefixed with /neev — the prefix is configurable via route_prefix in config/neev.php (env NEEV_ROUTE_PREFIX). Include the Bearer token for authenticated endpoints.
Authentication Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /neev/register |
Register new user | No |
| POST | /neev/login |
Login with credentials | No |
| POST | /neev/sendLoginLink |
Send magic link | No |
| GET | /neev/loginUsingLink |
Login via magic link | No |
| POST | /neev/logout |
Logout current session | Yes |
| POST | /neev/logoutAll |
Logout all other sessions | Yes |
| POST | /neev/forgotPassword |
Send password reset link | No |
| POST | /neev/resetPassword |
Reset password (signed URL) | No |
Email Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /neev/email/send |
Resend verification email | Yes |
| GET | /neev/email/verify |
Verify email address | Yes |
| POST | /neev/email/change |
Request email change | Yes |
| POST | /neev/email/change/verify |
Verify email change (signed URL) | No |
MFA Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/mfa |
List enabled MFA methods | Yes |
| POST | /neev/mfa/add |
Enable MFA method | Yes |
| PUT | /neev/mfa/preferred |
Set preferred MFA method | Yes |
| DELETE | /neev/mfa/delete |
Disable MFA method | Yes |
| POST | /neev/mfa/otp/verify |
Verify MFA code | MFA JWT |
| POST | /neev/recoveryCodes |
Generate recovery codes | Yes |
Passkey Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/passkeys |
List user's passkeys | Yes |
| GET | /neev/passkeys/register/options |
Get registration options | Yes |
| POST | /neev/passkeys/register |
Register passkey | Yes |
| GET | /neev/passkeys/login/options |
Get login options | No |
| POST | /neev/passkeys/login |
Login with passkey | No |
| PUT | /neev/passkeys |
Update passkey name | Yes |
| DELETE | /neev/passkeys |
Delete passkey | Yes |
User Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/users |
Get current user | Yes |
| PUT | /neev/users |
Update user profile | Yes |
| DELETE | /neev/users |
Delete user account | Yes |
| PUT | /neev/changePassword |
Change password | Yes |
| GET | /neev/sessions |
Get active sessions | Yes |
| GET | /neev/loginAttempts |
Get login history | Yes |
API Token Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/apiTokens |
List API tokens | Yes |
| POST | /neev/apiTokens |
Create API token | Yes |
| PUT | /neev/apiTokens |
Update API token | Yes |
| DELETE | /neev/apiTokens |
Delete API token | Yes |
| DELETE | /neev/apiTokens/deleteAll |
Delete all API tokens | Yes |
Team Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/teams |
List user's teams | Yes |
| GET | /neev/teams/invitations |
Get user's invitations and join requests | Yes |
| PUT | /neev/teams/default |
Set default team | Yes |
| GET | /neev/teams/{id} |
Get team details | Yes |
| POST | /neev/teams |
Create team | Yes |
| PUT | /neev/teams |
Update team | Yes |
| DELETE | /neev/teams |
Delete team | Yes |
| POST | /neev/changeTeamOwner |
Transfer ownership | Yes |
| POST | /neev/teams/inviteUser |
Invite member | Yes |
| PUT | /neev/teams/inviteUser |
Accept/reject invitation | Yes |
| PUT | /neev/teams/leave |
Leave team | Yes |
| POST | /neev/teams/request |
Request to join | Yes |
| PUT | /neev/teams/request |
Accept/reject request | Yes |
| PUT | /neev/role/change |
Change member role | Yes |
Domain Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/domains |
List team domains | Yes |
| POST | /neev/domains |
Add domain | Yes |
| PUT | /neev/domains |
Update/verify domain | Yes |
| DELETE | /neev/domains |
Delete domain | Yes |
| GET | /neev/domains/rules |
Get domain rules | Yes |
| PUT | /neev/domains/rules |
Update domain rules | Yes |
| PUT | /neev/domains/primary |
Set primary domain | Yes |
Tenant Domain Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /neev/tenant-domains |
List tenant domains | Yes |
| POST | /neev/tenant-domains |
Add custom domain | Yes |
| GET | /neev/tenant-domains/current |
Get current tenant | Yes |
| GET | /neev/tenant-domains/{id} |
Get domain details | Yes |
| DELETE | /neev/tenant-domains/{id} |
Delete domain | Yes |
| POST | /neev/tenant-domains/{id}/verify |
Verify domain | Yes |
| POST | /neev/tenant-domains/{id}/regenerate-token |
Regenerate verification token | Yes |
| POST | /neev/tenant-domains/{id}/primary |
Set as primary | Yes |
Web Routes
The Blade page routes below (everything except the OAuth/SSO endpoints) register only when the Blade starter kit is installed ('ui' => 'blade' in config/neev.php) — headless installs use the API instead.
Public Routes
| Method | Route | Name | Description |
|---|---|---|---|
| GET | /register |
register |
Registration form |
| POST | /register |
- | Process registration |
| GET | /login |
login |
Login form |
| PUT | /login |
login.password |
Show password form |
| POST | /login |
- | Process login |
| POST | /login/link |
login.link.send |
Send magic link |
| GET | /login/{id} |
login.link |
Login via magic link |
| GET | /forgot-password |
password.request |
Forgot password form |
| POST | /forgot-password |
password.email |
Send reset link |
| GET | /update-password/{id}/{hash} |
reset.request |
Reset password form |
| POST | /update-password |
user-password.update |
Process reset |
| GET | /otp/mfa/{method} |
otp.mfa.create |
MFA verification |
| POST | /otp/mfa |
otp.mfa.store |
Verify MFA code |
| GET | /neev/oauth/{service} |
oauth.redirect |
OAuth redirect |
| GET | /neev/oauth/{service}/callback |
oauth.callback |
OAuth callback |
| GET | /neev/sso/redirect |
sso.redirect |
Tenant SSO redirect |
| GET | /neev/sso/callback |
sso.callback |
Tenant SSO callback |
Authenticated Routes (neev:web middleware)
| Method | Route | Name | Description |
|---|---|---|---|
| GET | /email/verify |
verification.notice |
Verification pending |
| GET | /email/send |
email.verification.send |
Resend verification |
| GET | /email/change |
email.change |
Show change email form |
| PUT | /email/change |
email.update |
Request email change |
| POST | /logout |
logout |
Logout |
Account Routes (/account prefix)
| Method | Route | Name | Description |
|---|---|---|---|
| GET | /account/profile |
account.profile |
Profile page |
| GET | /account/security |
account.security |
Security settings |
| GET | /account/tokens |
account.tokens |
API tokens |
| GET | /account/teams |
account.teams |
Teams list |
| GET | /account/sessions |
account.sessions |
Active sessions |
| GET | /account/loginAttempts |
account.loginAttempts |
Login history |
| PUT | /account/profileUpdate |
profile.update |
Update profile |
| POST | /account/change-password |
password.change |
Change password |
| POST | /account/multiFactorAuth |
multi.auth |
Add MFA |
| PUT | /account/multiFactorAuth |
multi.preferred |
Set preferred MFA |
| GET | /account/recovery/codes |
recovery.codes |
View recovery codes |
| POST | /account/recovery/codes |
recovery.generate |
Generate new codes |
| POST | /account/passkeys/register/options |
passkeys.register.options |
Passkey options |
| POST | /account/passkeys/register |
passkeys.register |
Register passkey |
| DELETE | /account/passkeys |
passkeys.delete |
Delete passkey |
| POST | /account/logoutSessions |
logout.sessions |
Logout other sessions |
Team Routes (/teams prefix)
| Method | Route | Name | Description |
|---|---|---|---|
| GET | /teams/create |
teams.create |
Create team form |
| POST | /teams/create |
teams.store |
Store new team |
| GET | /teams/{team}/profile |
teams.profile |
Team profile |
| GET | /teams/{team}/members |
teams.members |
Team members |
| GET | /teams/{team}/domain |
teams.domain |
Domain settings |
| GET | /teams/{team}/settings |
teams.settings |
Team settings |
| PUT | /teams/switch |
teams.switch |
Switch team |
| PUT | /teams/update |
teams.update |
Update team |
| DELETE | /teams/delete |
teams.delete |
Delete team |
| PUT | /teams/members/invite |
teams.invite |
Invite member |
| PUT | /teams/members/invite/action |
teams.invite.action |
Accept/reject |
| DELETE | /teams/members/leave |
teams.leave |
Leave team |
| POST | /teams/members/request |
teams.request |
Request to join |
| PUT | /teams/members/request/action |
teams.request.action |
Accept/reject request |
| PUT | /teams/owner/change |
teams.owner.change |
Transfer ownership |
| PUT | /teams/roles/change |
teams.roles.change |
Change role |
Multi-Factor Authentication
Enable Authenticator App
// Returns QR code and secret $result = $user->addMultiFactorAuth('authenticator'); // $result['qr_code'] - SVG QR code // $result['secret'] - TOTP secret
Enable Email OTP
$user->addMultiFactorAuth('email');
Verify MFA
if ($user->verifyMFAOTP('authenticator', '123456')) { // MFA verified }
Recovery Codes
// Generate 8 recovery codes $codes = $user->generateRecoveryCodes(); // Store these securely - shown only once!
API Usage
# Enable MFA curl -X POST https://yourapp.com/neev/mfa/add \ -H "Authorization: Bearer {token}" \ -d '{"auth_method": "authenticator"}' # Verify MFA during login curl -X POST https://yourapp.com/neev/mfa/otp/verify \ -H "Authorization: Bearer {mfa_jwt_token}" \ -d '{"auth_method": "authenticator", "otp": "123456"}'
Team Management
Create Team
$team = Team::create([ 'name' => 'My Company', 'user_id' => auth()->id(), 'is_public' => false, ]);
User's Teams
$user->teams; // Teams user belongs to $user->ownedTeams; // Teams user owns $user->teamRequests; // Pending invitations $user->setDefaultTeam($team); // Set default team for next login
Team Relationships
$team->owner; // Team owner $team->users; // Team members $team->invitedUsers; // Pending invitations $team->joinRequests; // Join requests $team->domains; // Federated domains
API Usage
# Create team curl -X POST https://yourapp.com/neev/teams \ -H "Authorization: Bearer {token}" \ -d '{"name": "My Team", "public": false}' # Invite member curl -X POST https://yourapp.com/neev/teams/inviteUser \ -H "Authorization: Bearer {token}" \ -d '{"team_id": 1, "email": "user@example.com", "role": "member"}' # Accept invitation curl -X PUT https://yourapp.com/neev/teams/inviteUser \ -H "Authorization: Bearer {token}" \ -d '{"team_id": 1, "action": "accept"}'
Multi-Tenancy
Enable Tenant Isolation
// config/neev.php 'tenant' => true, // isolate users per tenant 'team' => true, // optional team sub-grouping
Tenant context is resolved on each request from the X-Tenant header or by looking up the request host in the domains table — subdomains and verified custom domains both work.
Tenant SSO
Per-tenant authentication and SSO are stored per tenant/team (in the tenant_auth_settings / team_auth_settings tables) rather than in config. Manage them via Artisan:
php artisan neev:auth:configure # Configure auth method / SSO for a tenant or team php artisan neev:auth:show # Show current auth settings
Get Tenant Auth Config
curl -X GET https://acme.yourapp.com/neev/tenant/auth
Response:
{
"auth_method": "sso",
"sso_enabled": true,
"sso_provider": "entra",
"sso_redirect_url": "https://acme.yourapp.com/neev/sso/redirect"
}
Middleware Groups
| Middleware | Description |
|---|---|
neev:web |
Web (session) authentication with tenant/team resolution |
neev:api |
API (token) authentication with tenant/team resolution |
neev:login |
Temporary MFA JWT authentication (during MFA verification) |
neev:tenant |
Tenant resolution from domain, tenant required (no auth) |
Middleware Aliases
| 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 |
neev:ensure-sso |
Enforces SSO-only access for the current context |
neev:password-not-expired |
Forces password change when password has expired |
neev:verified-email |
Requires a verified email address |
Security Features
Brute Force Protection
Progressive exponential backoff — there is no hard lockout:
// config/neev.php 'login_throttle' => [ 'delay_after' => 3, // Failed attempts before delays kick in 'max_delay_seconds' => 300, // Exponential backoff caps here ],
Password Policies
// config/neev.php 'password' => [ 'required', 'confirmed', Password::min(8)->max(72)->letters()->mixedCase()->numbers()->symbols(), PasswordHistory::notReused(5), PasswordUserData::notContain(['name', 'email']), ], 'password_expiry_days' => 90, // 0 = disabled
Password expiry is enforced by applying the opt-in neev:password-not-expired middleware alias to your routes.
Login Tracking
Each login attempt records:
- Login method (password, passkey, sso, etc.)
- MFA method used
- IP address and geolocation
- Browser, platform, device
- Success/failure status
GeoIP Setup
# Get MaxMind license key from maxmind.com # Add to .env: MAXMIND_LICENSE_KEY=your-key # Download database php artisan neev:download-geoip
Configuration
Feature Toggles
// config/neev.php 'tenant' => false, // Multi-tenant isolation (users scoped to tenant) 'team' => false, // Team management 'support_username' => false, // Username login
Email verification is enforced by applying the opt-in neev:verified-email middleware alias to your routes.
Post-Auth Redirect
'home' => '/dashboard', // Redirect after login (Blade flows)
MFA
'multi_factor_auth' => ['authenticator', 'email'], 'recovery_codes' => 8, 'otp_length' => 6, // 4, 6, or 8 digits 'otp_expiry_time' => 15, // minutes
OAuth Providers
'oauth' => [ 'google', 'github', 'microsoft', 'apple', ],
Token Expiry
'login_token_expiry_minutes' => 1440, // Login access tokens 'mfa_jwt_expiry_minutes' => 30, // Temporary MFA JWTs 'url_expiry_time' => 60, // Magic links, reset links 'otp_expiry_time' => 15, // OTP codes
Console Commands
Setup
php artisan neev:install # Interactive setup (asks: tenants? teams? starter kit?) php artisan neev:ui blade # Eject the Blade starter kit (or `none` for headless) php artisan neev:download-geoip # Download GeoIP database
Tenant & Team Management
php artisan neev:tenant:create # Create a tenant or team php artisan neev:tenant:list # List tenants php artisan neev:tenant:show # Show tenant details php artisan neev:team:activate # Activate a waitlisted team
Domains & Members
php artisan neev:domain:add # Add a domain php artisan neev:domain:verify # Verify a domain php artisan neev:domain:list # List domains php artisan neev:member:add # Add a member php artisan neev:member:remove # Remove a member php artisan neev:member:list # List members
Auth Settings
php artisan neev:auth:configure # Configure tenant/team auth & SSO php artisan neev:auth:show # Show tenant/team auth settings
Maintenance
php artisan neev:clean-login-attempts # Clean old login records
Scheduled Tasks
// routes/console.php use Illuminate\Support\Facades\Schedule; Schedule::command('neev:clean-login-attempts')->daily(); Schedule::command('neev:download-geoip')->monthly();
Database Schema
Core Tables
| Table | Description |
|---|---|
users |
User accounts (includes password and password history) |
otp |
One-time passwords |
passkeys |
WebAuthn credentials |
multi_factor_auths |
MFA configurations |
recovery_codes |
MFA backup codes |
access_tokens |
API and login tokens |
login_attempts |
Login history |
Team Tables
| Table | Description |
|---|---|
teams |
Teams/organizations |
team_user |
Team-user membership pivot table |
team_invitations |
Pending invitations |
domains |
Email domain federation |
domain_rules |
Domain security rules |
Tenant Tables
| Table | Description |
|---|---|
tenants |
Tenant organizations (isolated identity mode) |
domains |
Custom tenant domains and domain federation |
team_auth_settings |
Per-team auth/SSO config |
tenant_auth_settings |
Per-tenant auth/SSO config (isolated mode) |
Detailed Documentation
For comprehensive documentation, see the docs folder:
| Document | Description |
|---|---|
| Installation | Complete setup guide |
| Configuration | All configuration options |
| Authentication | Auth flows and methods |
| API Reference | Complete API documentation |
| Web Routes | All web route details |
| MFA | Multi-factor authentication |
| Teams | Team management guide |
| Multi-Tenancy | SaaS multi-tenant setup |
| Security | Security features & best practices |
| Architecture | Identity strategy, tenancy & team design |
| Architecture Internals | Interfaces, patterns & coding standards |
Requirements
- PHP 8.3+
- Laravel 12.x
- MySQL, PostgreSQL, or SQLite
Contributing
See CONTRIBUTING.md for setup instructions, coding standards, and how to submit pull requests.
Report security vulnerabilities following the process in SECURITY.md.
License
MIT License. See LICENSE for details.
Credits
Created and maintained by Abhishek Sharma at SSNTPL.
Ready to get started? Run composer require ssntpl/neev and php artisan neev:install!
ssntpl/neev 适用场景与选型建议
ssntpl/neev 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 117 次下载、GitHub Stars 达 2, 最近一次更新时间为 2026 年 02 月 14 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「Authentication」 「oauth」 「SSO」 「laravel」 「saas」 「rbac」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 ssntpl/neev 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 ssntpl/neev 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 ssntpl/neev 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
WeChat OAuth SDK
Automatically logs-in users if they are already authenticated by a remote source. (e.g. environment variable REMOTE_USER)
GraphQL authentication for your headless Craft CMS applications.
Ory-Hydra OAuth 2.0 Client Provider for The PHP League OAuth2-Client
Library for ORCID web services
A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.
统计信息
- 总下载量: 117
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 46
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-02-14