PHPackages                             bspdx/keystone - 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. bspdx/keystone

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

bspdx/keystone
==============

Complete authentication package for Laravel with Fortify, Passkeys, TOTP 2FA, and RBAC

v0.9.0(3w ago)029MITPHPPHP ^8.2.0CI passing

Since Jan 25Pushed 3w agoCompare

[ Source](https://github.com/TheBootstrapParadox/Keystone)[ Packagist](https://packagist.org/packages/bspdx/keystone)[ RSS](/packages/bspdx-keystone/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (37)Versions (10)Used By (0)

BSPDX Keystone
==============

[](#bspdx-keystone)

[![Latest Version on Packagist](https://camo.githubusercontent.com/56eee7b5cb738ef740e64e77ca59c0feae6c34190cb1d162f21b7c7c9d6085c8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f62737064782f6b657973746f6e652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bspdx/keystone)[![Total Downloads](https://camo.githubusercontent.com/d8c816027f193f878694b0b6101bca654ae37e500cdb87bd712f8858cc34e90b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f62737064782f6b657973746f6e652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bspdx/keystone)[![License](https://camo.githubusercontent.com/be2dadbb61545b3f530fa6e202360e1bdfac4c97bb6ca8aa77ea7a2a7f8f0056/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f62737064782f6b657973746f6e652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bspdx/keystone)A comprehensive, production-ready authentication package for Laravel with an **API-first architecture**. Keystone combines the power of Laravel Fortify, Sanctum, and Spatie Laravel Passkeys to provide a full-featured auth system with:

- 🔐 **Standard Authentication** - Powered by Laravel Fortify
- 👥 **Role-Based Access Control (RBAC)** - Clean service layer API
- 📱 **TOTP Two-Factor Authentication** - Google Authenticator, Authy, etc.
- 🔑 **Passkey Authentication** - Modern WebAuthn/FIDO2 login
- 🚦 **Brute-Force Protection** - Configurable rate limiting on login, 2FA, and passkey attempts
- 🎨 **Optional Blade UI Components** - Pre-built views for Laravel projects
- 🌐 **API-First Design** - Works with React, Vue, mobile apps, or any frontend
- 🏢 **Multi-Tenancy Ready** - Optional tenant scoping

Frontend Flexibility
--------------------

[](#frontend-flexibility)

**Keystone works with any frontend framework:**

- ✅ **React, Vue, Angular, Svelte** - Use the JSON API endpoints
- ✅ **Mobile Apps** - iOS, Android, React Native, Flutter
- ✅ **Laravel Blade** - Optional pre-built UI components included
- ✅ **Inertia.js** - Perfect for hybrid approaches

All controllers return JSON when requested, making Keystone truly framework-agnostic at the API level.

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

[](#table-of-contents)

- [Frontend Flexibility](#frontend-flexibility)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
    - [User Model Setup](#user-model-setup)
    - [Service Layer](#service-layer-new-in-v030)
    - [Blade Components (Optional)](#blade-components-optional)
    - [Routes](#routes)
    - [Middleware](#middleware)
    - [API Usage](#api-usage)
- [Architecture](#architecture)
- [HTTPS Setup](#https-setup)
- [Multi-Tenancy](#multi-tenancy)
- [Testing](#testing)
- [Credits](#credits)
- [License](#license)

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

[](#requirements)

- PHP 8.2+
- Laravel 12.x or 13.x
- MySQL 5.7+ / PostgreSQL 9.6+ / SQLite 3.8.8+

Installation
------------

[](#installation)

### Step 1: Install via Composer

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

```
composer require bspdx/keystone
```

### Step 2: Publish Configuration &amp; Assets

[](#step-2-publish-configuration--assets)

```
# Publish the essentials: configuration and migrations
php artisan vendor:publish --tag=keystone-config --tag=keystone-migrations

# Publish Blade views (optional - only if you want to customize)
php artisan vendor:publish --tag=keystone-views

# Publish example routes
php artisan vendor:publish --tag=keystone-routes

# Publish database seeders
php artisan vendor:publish --tag=keystone-seeders
```

### Step 3: Run Migrations

[](#step-3-run-migrations)

```
php artisan migrate
```

This will create tables for:

- Two-factor authentication columns in `users` table
- Roles and permissions (custom RBAC)
- Passkeys
- Personal access tokens (Sanctum)

### Step 4: Seed Demo Data (Optional)

[](#step-4-seed-demo-data-optional)

```
php artisan db:seed --class=KeystoneSeeder
```

This creates:

- 4 default roles: `super-admin`, `admin`, `editor`, `user`
- Common permissions for each role
- 4 demo users (all with password: `password`)
    - `superadmin@example.com` - Super Admin
    - `admin@example.com` - Admin
    - `editor@example.com` - Editor
    - `user@example.com` - Regular User

### Step 5: Configure Fortify

[](#step-5-configure-fortify)

In your `config/fortify.php`, ensure these features are enabled:

```
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::updateProfileInformation(),
    Features::updatePasswords(),
    Features::twoFactorAuthentication([
        'confirm' => true,
        'confirmPassword' => true,
    ]),
],
```

Configuration
-------------

[](#configuration)

The package configuration is located at `config/keystone.php`. Key settings:

### Enable/Disable Features

[](#enabledisable-features)

```
'features' => [
    // Two-factor authentication (TOTP via Fortify)
    'two_factor' => true,

    // Passkey authentication (WebAuthn/FIDO2)
    'passkeys' => true,

    // Passkey as a second factor (reserved — not yet implemented)
    'passkey_2fa' => false,

    // Account deletion endpoint (reserved — not yet implemented)
    'account_deletion' => false,

    // Allow users to configure passwordless login options
    'passwordless_login' => true,

    // Show roles and permissions on the profile page
    'show_permissions' => true,

    // Enable multi-tenant mode (adds tenant_id column to users, roles, and permissions tables)
    'multi_tenant' => env('KEYSTONE_MULTI_TENANT', false),
],
```

> **Note:** Standard auth features — registration, email verification, password reset, profile/password updates, and API tokens — are provided by Laravel Fortify and Sanctum, and are configured in `config/fortify.php` (see [Step 5](#step-5-configure-fortify)). The `keystone.features` array only toggles Keystone-specific functionality.

When `multi_tenant` is enabled, Keystone will add a nullable `tenant_id` column to users, roles, permissions, and pivot tables. Keystone uses **global scopes** for automatic tenant isolation (not Spatie's teams feature).

**Key Features:**

- **Automatic Filtering** - Authenticated users only see roles/permissions for their tenant
- **Global Roles/Permissions** - Set `tenant_id = NULL` for cross-tenant access
- **UUID Support** - Works with both UUID and bigint tenant IDs
- **Super-Admin Bypass** - Use `::withoutTenant()` for cross-tenant operations

**Example:**

```
use BSPDX\Keystone\Models\KeystoneRole;

// Create global role (accessible to all tenants)
$superAdmin = KeystoneRole::withoutTenant()->create([
    'name' => 'super_administrator',
    'tenant_id' => null,
]);

// Create tenant-specific role (auto-scoped)
Auth::login($userInTenantA);
$manager = KeystoneRole::create(['name' => 'manager']);
// tenant_id automatically populated from auth()->user()->tenant_id
```

See [Multi-Tenancy Documentation](docs/multi-tenancy.md) for detailed architecture, usage examples, and migration guides.

### RBAC Settings

[](#rbac-settings)

```
'rbac' => [
    // Cache expiration time for roles and permissions (in seconds)
    'cache_expiration' => 60 * 60 * 24, // 24 hours

    // Default role assigned to new users (null = no default role)
    'default_role' => 'user',

    // Super admin role that bypasses all permission checks
    'super_admin_role' => 'super-admin',
],
```

### Passkey Settings

[](#passkey-settings)

```
'passkey' => [
    // Relying Party name (your application name)
    'rp_name' => env('APP_NAME', 'Laravel'),

    // Relying Party ID — derived from APP_URL host, falls back to 'localhost'
    'rp_id' => env('APP_URL') ? parse_url(env('APP_URL'), PHP_URL_HOST) : 'localhost',

    // Timeout for passkey operations (in milliseconds)
    'timeout' => 60000,

    // User verification: 'required', 'preferred', or 'discouraged'
    'user_verification' => 'preferred',

    // Attestation conveyance: 'none', 'indirect', or 'direct'
    'attestation' => 'none',

    'allow_multiple' => true,
    'required_for_roles' => [
        // 'admin',
    ],
],
```

### Two-Factor Settings

[](#two-factor-settings)

```
'two_factor' => [
    'qr_code_size' => 200,
    'recovery_codes_count' => 8,

    // Window of time to accept TOTP codes (in periods, 1 period = 30 seconds)
    'window' => 1,

    'required_for_roles' => [
        // 'admin',
    ],
],
```

### Rate Limiting

[](#rate-limiting)

Keystone throttles authentication attempts to protect against brute-force attacks. Attempts are keyed by action, identifier (authenticated user or submitted email), and client IP.

```
'rate_limiting' => [
    // Maximum login attempts before lockout
    'max_login_attempts' => 5,

    // Lockout duration in minutes
    'lockout_duration' => 1,

    // Maximum 2FA attempts
    'max_2fa_attempts' => 3,

    // Maximum passkey attempts
    'max_passkey_attempts' => 3,
],
```

When a limit is exceeded, JSON requests receive a `429 Too Many Attempts` response with the remaining lockout time.

### Profile Page Settings

[](#profile-page-settings)

```
'profile' => [
    // URI path where the profile page is accessible
    'path' => '/profile',

    // Middleware applied to profile routes
    'middleware' => ['web', 'auth'],

    // Require password confirmation before sensitive operations
    'require_password_confirm' => true,

    // Layout view to extend (set to null for component-only mode)
    'layout' => 'layouts.app',
],
```

Usage
-----

[](#usage)

### User Model Setup

[](#user-model-setup)

**New project?** Use the built-in `KeystoneUser` model and skip this setup entirely. See [User Model Configuration](docs/USER_MODEL.md) for a full comparison and setup instructions.

Add the `HasKeystone` trait to your existing `User` model:

```
