PHPackages                             ssntpl/neev - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. ssntpl/neev

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

ssntpl/neev
===========

Enterprise-grade user authentication, team management, and multi-tenancy for Laravel SaaS applications.

v0.5.0(1mo ago)2139[2 PRs](https://github.com/ssntpl/neev/pulls)MITPHPPHP ^8.3CI passing

Since Oct 17Pushed 1mo agoCompare

[ Source](https://github.com/ssntpl/neev)[ Packagist](https://packagist.org/packages/ssntpl/neev)[ Docs](https://github.com/ssntpl/neev)[ GitHub Sponsors](https://github.com/ssntpl)[ RSS](/packages/ssntpl-neev/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (49)Versions (32)Used By (0)

Neev - Enterprise User Management for Laravel
=============================================

[](#neev---enterprise-user-management-for-laravel)

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.

[![Latest Version](https://camo.githubusercontent.com/0dfdc5186570557f234b1880a54aee313046a1aa364985586417b8dcb8d0b4bf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73736e74706c2f6e6565762e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ssntpl/neev)[![License](https://camo.githubusercontent.com/1dcca75639424a17e2d8025d2ca88ba8f5a69de3d73b2832b3881c50bf15768d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f73736e74706c2f6e6565762e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ssntpl/neev)[![Code Style](https://github.com/ssntpl/neev/actions/workflows/code-style.yml/badge.svg)](https://github.com/ssntpl/neev/actions/workflows/code-style.yml)[![Static Analysis](https://github.com/ssntpl/neev/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/ssntpl/neev/actions/workflows/static-analysis.yml)[![Tests](https://github.com/ssntpl/neev/actions/workflows/tests.yml/badge.svg)](https://github.com/ssntpl/neev/actions/workflows/tests.yml)[![Coverage](https://camo.githubusercontent.com/9ad211f67e3c0ccbb27332af97903534576a0bf48face54a011b6e35b7c6f308/68747470733a2f2f636f6465636f762e696f2f67682f73736e74706c2f6e6565762f6272616e63682f6d61696e2f67726170682f62616467652e737667)](https://codecov.io/gh/ssntpl/neev)[![PHP Version](https://camo.githubusercontent.com/ca3e8d03ce876475efb2630ff4011c85472f73ccaa76e059581824cbfbeafcd1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f73736e74706c2f6e6565762f7068703f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ssntpl/neev)[![Total Downloads](https://camo.githubusercontent.com/63476cf385b0a1c1f73823a6d01805d51e651410107d3b1d01044e199ee16a63/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73736e74706c2f6e6565762e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ssntpl/neev)

---

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Quick Start](#quick-start)
- [Authentication Methods](#authentication-methods)
- [API Reference](#api-reference)
- [Web Routes](#web-routes)
- [Multi-Factor Authentication](#multi-factor-authentication)
- [Team Management](#team-management)
- [Multi-Tenancy](#multi-tenancy)
- [Security Features](#security-features)
- [Configuration](#configuration)
- [Console Commands](#console-commands)
- [Database Schema](#database-schema)
- [Detailed Documentation](#detailed-documentation)

---

Features
--------

[](#features)

### Authentication Methods

[](#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

[](#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

[](#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

[](#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

[](#multi-tenancy)

- Domain-based tenant resolution (`X-Tenant` header or host lookup)
- Custom domain support with DNS verification
- Per-tenant authentication configuration
- Per-tenant SSO integration

---

Quick Start
-----------

[](#quick-start)

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require ssntpl/neev
```

### 2. Run the Installation Command

[](#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

[](#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

[](#4-run-migrations)

```
php artisan migrate
```

### 5. Update Your User Model

[](#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
----------------------

[](#authentication-methods-1)

### Password Authentication

[](#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)

[](#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

[](#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

[](#oauth--social-login)

Enable in configuration:

```
// config/neev.php
'oauth' => ['google', 'github', 'microsoft', 'apple'],
```

Redirect URLs:

- `GET /neev/oauth/{service}` - Redirect to provider
- `GET /neev/oauth/{service}/callback` - Handle callback

---

API Reference
-------------

[](#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

[](#authentication-endpoints)

MethodEndpointDescriptionAuthPOST`/neev/register`Register new userNoPOST`/neev/login`Login with credentialsNoPOST`/neev/sendLoginLink`Send magic linkNoGET`/neev/loginUsingLink`Login via magic linkNoPOST`/neev/logout`Logout current sessionYesPOST`/neev/logoutAll`Logout all other sessionsYesPOST`/neev/forgotPassword`Send password reset linkNoPOST`/neev/resetPassword`Reset password (signed URL)No### Email Endpoints

[](#email-endpoints)

MethodEndpointDescriptionAuthPOST`/neev/email/send`Resend verification emailYesGET`/neev/email/verify`Verify email addressYesPOST`/neev/email/change`Request email changeYesPOST`/neev/email/change/verify`Verify email change (signed URL)No### MFA Endpoints

[](#mfa-endpoints)

MethodEndpointDescriptionAuthGET`/neev/mfa`List enabled MFA methodsYesPOST`/neev/mfa/add`Enable MFA methodYesPUT`/neev/mfa/preferred`Set preferred MFA methodYesDELETE`/neev/mfa/delete`Disable MFA methodYesPOST`/neev/mfa/otp/verify`Verify MFA codeMFA JWTPOST`/neev/recoveryCodes`Generate recovery codesYes### Passkey Endpoints

[](#passkey-endpoints)

MethodEndpointDescriptionAuthGET`/neev/passkeys`List user's passkeysYesGET`/neev/passkeys/register/options`Get registration optionsYesPOST`/neev/passkeys/register`Register passkeyYesGET`/neev/passkeys/login/options`Get login optionsNoPOST`/neev/passkeys/login`Login with passkeyNoPUT`/neev/passkeys`Update passkey nameYesDELETE`/neev/passkeys`Delete passkeyYes### User Endpoints

[](#user-endpoints)

MethodEndpointDescriptionAuthGET`/neev/users`Get current userYesPUT`/neev/users`Update user profileYesDELETE`/neev/users`Delete user accountYesPUT`/neev/changePassword`Change passwordYesGET`/neev/sessions`Get active sessionsYesGET`/neev/loginAttempts`Get login historyYes### API Token Endpoints

[](#api-token-endpoints)

MethodEndpointDescriptionAuthGET`/neev/apiTokens`List API tokensYesPOST`/neev/apiTokens`Create API tokenYesPUT`/neev/apiTokens`Update API tokenYesDELETE`/neev/apiTokens`Delete API tokenYesDELETE`/neev/apiTokens/deleteAll`Delete all API tokensYes### Team Endpoints

[](#team-endpoints)

MethodEndpointDescriptionAuthGET`/neev/teams`List user's teamsYesGET`/neev/teams/invitations`Get user's invitations and join requestsYesPUT`/neev/teams/default`Set default teamYesGET`/neev/teams/{id}`Get team detailsYesPOST`/neev/teams`Create teamYesPUT`/neev/teams`Update teamYesDELETE`/neev/teams`Delete teamYesPOST`/neev/changeTeamOwner`Transfer ownershipYesPOST`/neev/teams/inviteUser`Invite memberYesPUT`/neev/teams/inviteUser`Accept/reject invitationYesPUT`/neev/teams/leave`Leave teamYesPOST`/neev/teams/request`Request to joinYesPUT`/neev/teams/request`Accept/reject requestYesPUT`/neev/role/change`Change member roleYes### Domain Endpoints

[](#domain-endpoints)

MethodEndpointDescriptionAuthGET`/neev/domains`List team domainsYesPOST`/neev/domains`Add domainYesPUT`/neev/domains`Update/verify domainYesDELETE`/neev/domains`Delete domainYesGET`/neev/domains/rules`Get domain rulesYesPUT`/neev/domains/rules`Update domain rulesYesPUT`/neev/domains/primary`Set primary domainYes### Tenant Domain Endpoints

[](#tenant-domain-endpoints)

MethodEndpointDescriptionAuthGET`/neev/tenant-domains`List tenant domainsYesPOST`/neev/tenant-domains`Add custom domainYesGET`/neev/tenant-domains/current`Get current tenantYesGET`/neev/tenant-domains/{id}`Get domain detailsYesDELETE`/neev/tenant-domains/{id}`Delete domainYesPOST`/neev/tenant-domains/{id}/verify`Verify domainYesPOST`/neev/tenant-domains/{id}/regenerate-token`Regenerate verification tokenYesPOST`/neev/tenant-domains/{id}/primary`Set as primaryYes---

Web Routes
----------

[](#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

[](#public-routes)

MethodRouteNameDescriptionGET`/register``register`Registration formPOST`/register`-Process registrationGET`/login``login`Login formPUT`/login``login.password`Show password formPOST`/login`-Process loginPOST`/login/link``login.link.send`Send magic linkGET`/login/{id}``login.link`Login via magic linkGET`/forgot-password``password.request`Forgot password formPOST`/forgot-password``password.email`Send reset linkGET`/update-password/{id}/{hash}``reset.request`Reset password formPOST`/update-password``user-password.update`Process resetGET`/otp/mfa/{method}``otp.mfa.create`MFA verificationPOST`/otp/mfa``otp.mfa.store`Verify MFA codeGET`/neev/oauth/{service}``oauth.redirect`OAuth redirectGET`/neev/oauth/{service}/callback``oauth.callback`OAuth callbackGET`/neev/sso/redirect``sso.redirect`Tenant SSO redirectGET`/neev/sso/callback``sso.callback`Tenant SSO callback### Authenticated Routes (neev:web middleware)

[](#authenticated-routes-neevweb-middleware)

MethodRouteNameDescriptionGET`/email/verify``verification.notice`Verification pendingGET`/email/send``email.verification.send`Resend verificationGET`/email/change``email.change`Show change email formPUT`/email/change``email.update`Request email changePOST`/logout``logout`Logout### Account Routes (/account prefix)

[](#account-routes-account-prefix)

MethodRouteNameDescriptionGET`/account/profile``account.profile`Profile pageGET`/account/security``account.security`Security settingsGET`/account/tokens``account.tokens`API tokensGET`/account/teams``account.teams`Teams listGET`/account/sessions``account.sessions`Active sessionsGET`/account/loginAttempts``account.loginAttempts`Login historyPUT`/account/profileUpdate``profile.update`Update profilePOST`/account/change-password``password.change`Change passwordPOST`/account/multiFactorAuth``multi.auth`Add MFAPUT`/account/multiFactorAuth``multi.preferred`Set preferred MFAGET`/account/recovery/codes``recovery.codes`View recovery codesPOST`/account/recovery/codes``recovery.generate`Generate new codesPOST`/account/passkeys/register/options``passkeys.register.options`Passkey optionsPOST`/account/passkeys/register``passkeys.register`Register passkeyDELETE`/account/passkeys``passkeys.delete`Delete passkeyPOST`/account/logoutSessions``logout.sessions`Logout other sessions### Team Routes (/teams prefix)

[](#team-routes-teams-prefix)

MethodRouteNameDescriptionGET`/teams/create``teams.create`Create team formPOST`/teams/create``teams.store`Store new teamGET`/teams/{team}/profile``teams.profile`Team profileGET`/teams/{team}/members``teams.members`Team membersGET`/teams/{team}/domain``teams.domain`Domain settingsGET`/teams/{team}/settings``teams.settings`Team settingsPUT`/teams/switch``teams.switch`Switch teamPUT`/teams/update``teams.update`Update teamDELETE`/teams/delete``teams.delete`Delete teamPUT`/teams/members/invite``teams.invite`Invite memberPUT`/teams/members/invite/action``teams.invite.action`Accept/rejectDELETE`/teams/members/leave``teams.leave`Leave teamPOST`/teams/members/request``teams.request`Request to joinPUT`/teams/members/request/action``teams.request.action`Accept/reject requestPUT`/teams/owner/change``teams.owner.change`Transfer ownershipPUT`/teams/roles/change``teams.roles.change`Change role---

Multi-Factor Authentication
---------------------------

[](#multi-factor-authentication-1)

### Enable Authenticator App

[](#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

[](#enable-email-otp)

```
$user->addMultiFactorAuth('email');
```

### Verify MFA

[](#verify-mfa)

```
if ($user->verifyMFAOTP('authenticator', '123456')) {
    // MFA verified
}
```

### Recovery Codes

[](#recovery-codes)

```
// Generate 8 recovery codes
$codes = $user->generateRecoveryCodes();
// Store these securely - shown only once!
```

### API Usage

[](#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
---------------

[](#team-management-1)

### Create Team

[](#create-team)

```
$team = Team::create([
    'name' => 'My Company',
    'user_id' => auth()->id(),
    'is_public' => false,
]);
```

### User's Teams

[](#users-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-relationships)

```
$team->owner;          // Team owner
$team->users;          // Team members
$team->invitedUsers;   // Pending invitations
$team->joinRequests;   // Join requests
$team->domains;        // Federated domains
```

### API Usage

[](#api-usage-1)

```
# 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
-------------

[](#multi-tenancy-1)

### Enable Tenant Isolation

[](#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

[](#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

[](#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-groups)

MiddlewareDescription`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

[](#middleware-aliases)

AliasDescription`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
-----------------

[](#security-features-1)

### Brute Force Protection

[](#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

[](#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

[](#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

[](#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
-------------

[](#configuration)

### Feature Toggles

[](#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

[](#post-auth-redirect)

```
'home' => '/dashboard',  // Redirect after login (Blade flows)
```

### MFA

[](#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-providers)

```
'oauth' => [
    'google',
    'github',
    'microsoft',
    'apple',
],
```

### Token Expiry

[](#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
----------------

[](#console-commands)

### Setup

[](#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 &amp; Team Management

[](#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 &amp; Members

[](#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

[](#auth-settings)

```
php artisan neev:auth:configure       # Configure tenant/team auth & SSO
php artisan neev:auth:show            # Show tenant/team auth settings
```

### Maintenance

[](#maintenance)

```
php artisan neev:clean-login-attempts # Clean old login records
```

### Scheduled Tasks

[](#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
---------------

[](#database-schema)

### Core Tables

[](#core-tables)

TableDescription`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

[](#team-tables)

TableDescription`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

[](#tenant-tables)

TableDescription`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
----------------------

[](#detailed-documentation)

For comprehensive documentation, see the [docs folder](./docs/):

DocumentDescription[Installation](./docs/installation.md)Complete setup guide[Configuration](./docs/configuration.md)All configuration options[Authentication](./docs/authentication.md)Auth flows and methods[API Reference](./docs/api-reference.md)Complete API documentation[Web Routes](./docs/web-routes.md)All web route details[MFA](./docs/mfa.md)Multi-factor authentication[Teams](./docs/teams.md)Team management guide[Multi-Tenancy](./docs/multi-tenancy.md)SaaS multi-tenant setup[Security](./docs/security.md)Security features &amp; best practices[Architecture](./docs/architecture.md)Identity strategy, tenancy &amp; team design[Architecture Internals](./docs/architecture-internals.md)Interfaces, patterns &amp; coding standards---

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 12.x
- MySQL, PostgreSQL, or SQLite

---

Contributing
------------

[](#contributing)

See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, coding standards, and how to submit pull requests.

Report security vulnerabilities following the process in [SECURITY.md](SECURITY.md).

---

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

---

Credits
-------

[](#credits)

Created and maintained by [Abhishek Sharma](https://ssntpl.com) at [SSNTPL](https://ssntpl.com).

---

**Ready to get started?** Run `composer require ssntpl/neev` and `php artisan neev:install`!

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance92

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 56% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~18 days

Recently: every ~28 days

Total

13

Last Release

48d ago

PHP version history (3 changes)v0.1.0PHP \*

v0.1.2PHP ^8.1

v0.2.0PHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/6224763?v=4)[Sword Software N Technologies Pvt. Ltd.](/maintainers/ssntpl)[@ssntpl](https://github.com/ssntpl)

---

Top Contributors

[![Abhishek5Sharma](https://avatars.githubusercontent.com/u/160742025?v=4)](https://github.com/Abhishek5Sharma "Abhishek5Sharma (108 commits)")[![sambhav-aggarwal](https://avatars.githubusercontent.com/u/4591834?v=4)](https://github.com/sambhav-aggarwal "sambhav-aggarwal (84 commits)")[![JYOTSANASHARMAA](https://avatars.githubusercontent.com/u/116160861?v=4)](https://github.com/JYOTSANASHARMAA "JYOTSANASHARMAA (1 commits)")

---

Tags

authenticationlaravelmfamulti-tenancyoauthpasskeysrbacsaasssostarter-kitteamswebauthnlaravelAuthenticationSSOoauthrbacwebauthnsaasmulti-tenancyMFATeamspasskeys

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/ssntpl-neev/health.svg)

```
[![Health](https://phpackages.com/badges/ssntpl-neev/health.svg)](https://phpackages.com/packages/ssntpl-neev)
```

###  Alternatives

[statamic/cms

The Statamic CMS Core Package

4.9k3.8M1.2k](/packages/statamic-cms)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3915.5k](/packages/rawilk-profile-filament-plugin)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)[ellaisys/aws-cognito

Laravel Authentication using AWS Cognito (Web and API)

121269.8k1](/packages/ellaisys-aws-cognito)[contao/core-bundle

Contao Open Source CMS

1301.7M3.1k](/packages/contao-core-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
