PHPackages                             serenity\_technologies/admin-dashboard-guard - 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. serenity\_technologies/admin-dashboard-guard

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

serenity\_technologies/admin-dashboard-guard
============================================

Two-factor passphrase+password admin authentication guard for any admin-restricted Laravel page (Horizon, Telescope, Pulse, custom routes, etc.).

v1.0.1(2w ago)15↓100%MITPHPPHP ^8.1

Since May 24Pushed 2w agoCompare

[ Source](https://github.com/Serenity-Technologies/admin-dashboard-guard)[ Packagist](https://packagist.org/packages/serenity_technologies/admin-dashboard-guard)[ RSS](/packages/serenity-technologies-admin-dashboard-guard/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (3)Used By (0)

admin-dashboard-guard
=====================

[](#admin-dashboard-guard)

A Laravel package that places a **two-factor passphrase + password authentication wall** in front of any admin-restricted page — Horizon, Telescope, Pulse, Filament, or any custom route — with zero extra database tables.

---

How It Works
------------

[](#how-it-works)

Access to a protected page requires **two sequential steps**:

1. **Passphrase step** — The admin provides a short-lived secret passphrase (bcrypt-hashed in the database). On success, a 10-minute session window opens.
2. **Password step** — Within that window, the admin enters their account password to receive a fully-authenticated session (valid for 60 minutes by default).

Each protected page runs its **own independent session**, so authenticating to `/horizon` does not grant access to `/telescope`.

Generating a passphrase via Artisan emails it directly to the admin and schedules automatic revocation after a configurable delay.

---

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

[](#requirements)

RequirementVersionPHP`^8.1`Laravel`^11.0` | `^12.0` | `^13.0`Laravel Sanctum *(optional)*`^3.0` | `^4.0`> **Sanctum** is only needed if you want to accept a bearer-token as an alternative to the session flow. It is listed under `suggest` in `composer.json` and is not required by default.

---

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

[](#installation)

### 1. Require the package

[](#1-require-the-package)

```
composer require serenity_technologies/admin-dashboard-guard
```

The service provider is auto-discovered via `extra.laravel.providers` in `composer.json`.

### 2. Publish the config

[](#2-publish-the-config)

```
php artisan vendor:publish --tag=admin-dashboard-guard-config
```

This creates `config/admin-dashboard-guard.php`.

### 3. Add the `passphrase` column to your admin model

[](#3-add-the-passphrase-column-to-your-admin-model)

```
php artisan make:migration add_passphrase_to_admins_table
```

```
// In the migration:
$table->string('passphrase')->nullable();
```

Run the migration:

```
php artisan migrate
```

### 4. Configure your admin model

[](#4-configure-your-admin-model)

Set the model in `.env`:

```
ADMIN_DASHBOARD_MODEL=App\Models\Admin
```

Your model must implement `Illuminate\Contracts\Auth\Authenticatable` and have both a `passphrase` column (nullable, stores a bcrypt hash) and a `password` column.

### 5. Configure the auth guard

[](#5-configure-the-auth-guard)

Ensure an `admin` guard is defined in `config/auth.php`:

```
'guards' => [
    'admin' => [
        'driver'   => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [
    'admins' => [
        'driver' => 'eloquent',
        'model'  => App\Models\Admin::class,
    ],
],
```

Then set in `.env`:

```
ADMIN_DASHBOARD_GUARD=admin
```

---

Protecting a Page
-----------------

[](#protecting-a-page)

The package registers a named middleware alias for every entry in `protected_pages`. The alias format is `admin.{key}`.

### Horizon

[](#horizon)

In `config/horizon.php`:

```
'middleware' => ['web', 'admin.horizon'],
```

### Telescope

[](#telescope)

In `app/Providers/TelescopeServiceProvider.php`:

```
protected function gate(): void
{
    Gate::define('viewTelescope', fn () => auth('admin')->check());
}
```

And add the middleware to the route group in your telescope service provider or `routes/web.php`:

```
Route::middleware(['web', 'admin.telescope'])->group(function () {
    // Telescope routes
});
```

### Any Custom Route

[](#any-custom-route)

You can protect any route or route group with the `admin.{key}` alias, where `key` matches an entry in `protected_pages`:

```
// Protect Pulse
Route::middleware(['web', 'admin.pulse'])->group(function () {
    Route::get('/pulse', ...);
});

// Protect a custom admin panel
Route::middleware(['web', 'admin.myadmin'])->prefix('admin')->group(function () {
    // your admin routes
});
```

---

Adding a New Protected Page
---------------------------

[](#adding-a-new-protected-page)

Open `config/admin-dashboard-guard.php` and add an entry to `protected_pages`:

```
'protected_pages' => [

    'horizon' => [
        'path'           => 'horizon',
        'gate'           => 'viewHorizon',
        'session_prefix' => 'horizon',
        'passphrase_ttl' => 10,
        'session_ttl'    => 60,
        'theme_color'    => 'purple',
    ],

    'telescope' => [
        'path'           => 'telescope',
        'gate'           => 'viewTelescope',
        'session_prefix' => 'telescope',
        'passphrase_ttl' => 10,
        'session_ttl'    => 60,
        'theme_color'    => 'indigo',
    ],

    // Add any new page here:
    'pulse' => [
        'path'           => 'pulse',
        'gate'           => 'viewPulse',   // set null to skip gate registration
        'session_prefix' => 'pulse',
        'passphrase_ttl' => 10,
        'session_ttl'    => 60,
        'theme_color'    => 'rose',
    ],

],
```

The package automatically:

- Registers an `admin.pulse` middleware alias
- Defines a `viewPulse` gate (or skips it if `gate` is `null`)
- Registers `GET /pulse/password` and `POST /pulse/password` routes for the password step

### `protected_pages` Options

[](#protected_pages-options)

KeyTypeDefaultDescription`path``string`*(key name)*URL path segment (e.g. `'horizon'` → `/horizon`)`gate``string|null``'view{Key}'`Gate name to define. Set `null` to skip.`session_prefix``string`*(key name)*Namespace prefix for session keys`passphrase_ttl``int``10`Minutes the passphrase verification window is valid`session_ttl``int``60`Minutes the fully-authenticated session is valid`theme_color``string``'blue'`Tailwind colour name used in the login views`stealth_mode``bool``false` (global)When `true`, unauthenticated requests receive **404**. Overrides the global default for this page.---

Stealth Mode
------------

[](#stealth-mode)

When stealth mode is enabled the auth wall is completely invisible to unauthenticated requests. The passphrase form is **never shown** — every bare access attempt returns a plain **404 Not Found**, exactly as if the route did not exist.

The only way in is to carry the passphrase directly in the URL query string:

```
https://yourdomain.com/horizon?passphrase=a8Kq2mRvXpLtN4sYdZbWcJeF7hUgOiTy

```

A valid passphrase silently redirects to the password step as normal. A **wrong**passphrase also returns 404 (not 401), so nothing about the auth wall is revealed.

### Enable globally (all protected pages)

[](#enable-globally-all-protected-pages)

```
# .env
ADMIN_DASHBOARD_STEALTH=true
```

Or directly in the published config:

```
'stealth_mode' => true,
```

### Enable per page (overrides the global default)

[](#enable-per-page-overrides-the-global-default)

```
'protected_pages' => [
    'horizon' => [
        // ...
        'stealth_mode' => true,   // Horizon: 404 when unauthenticated
    ],
    'telescope' => [
        // ...
        'stealth_mode' => false,  // Telescope: still shows the passphrase form
    ],
],
```

> **Tip:** Combine stealth mode with a short `--delay` when generating passphrases so the URL is valid only for a small window of time.

---

Artisan Commands
----------------

[](#artisan-commands)

All commands are prefixed with `admin-guard:` to avoid collisions with the host application.

### Generate a passphrase for one admin

[](#generate-a-passphrase-for-one-admin)

```
php artisan admin-guard:generate-passphrase admin@example.com
```

Generates a random passphrase, bcrypt-hashes and saves it to the admin record, emails it to the admin, then queues an auto-removal job after `--delay` hours.

OptionDefaultDescription`--bcc=`—BCC address for the notification email`--length=``32`Passphrase length (minimum 16)`--delay=``1`Hours before the passphrase is automatically revoked**Example output:**

```
Passphrase generated for: John Smith (admin@example.com)
Passphrase : a8Kq2mRvXpLtN4sYdZbWcJeF7hUgOiTy
Auto-removes in 1 hour(s).

```

---

### Generate passphrases for all admins

[](#generate-passphrases-for-all-admins)

```
php artisan admin-guard:generate-passphrases
```

Runs the single-admin flow for every record returned by the configured model. Accepts the same `--bcc`, `--length`, and `--delay` options.

---

### Remove a passphrase for one admin

[](#remove-a-passphrase-for-one-admin)

```
php artisan admin-guard:remove-passphrase admin@example.com
```

Immediately nulls out the `passphrase` column for the given admin, invalidating any active passphrase-step session.

---

### Clear passphrases for all admins

[](#clear-passphrases-for-all-admins)

```
php artisan admin-guard:clear-passphrases
```

Nulls the `passphrase` column for every admin that currently has one set. Prompts for confirmation unless `--force` is passed.

OptionDescription`--force`Skip the confirmation prompt (useful in scripts or CI)> **Incident response tip:** Run `admin-guard:clear-passphrases --force` to instantly revoke all active passphrases if you suspect a passphrase has been compromised.

---

Configuration Reference
-----------------------

[](#configuration-reference)

```
// config/admin-dashboard-guard.php

return [

    // The Laravel auth guard used to authenticate the admin.
    'guard' => env('ADMIN_DASHBOARD_GUARD', 'admin'),

    // Fully-qualified Eloquent model class.
    'model' => env('ADMIN_DASHBOARD_MODEL', null),

    // Column names on the model.
    'passphrase_column' => env('ADMIN_DASHBOARD_PASSPHRASE_COLUMN', 'passphrase'),
    'password_column'   => env('ADMIN_DASHBOARD_PASSWORD_COLUMN', 'password'),

    // Accept a valid Sanctum personal-access token as an alternative to the
    // session flow. Requires laravel/sanctum.
    'sanctum_support' => env('ADMIN_DASHBOARD_SANCTUM', true),

    // Pages to protect — see "Adding a New Protected Page" above.
    'protected_pages' => [ /* ... */ ],

];
```

### Environment Variables

[](#environment-variables)

VariableDefaultDescription`ADMIN_DASHBOARD_GUARD``admin`Auth guard name`ADMIN_DASHBOARD_MODEL``null`Fully-qualified model class`ADMIN_DASHBOARD_PASSPHRASE_COLUMN``passphrase`Column storing the bcrypt passphrase hash`ADMIN_DASHBOARD_PASSWORD_COLUMN``password`Column storing the bcrypt password hash`ADMIN_DASHBOARD_SANCTUM``true`Enable Sanctum bearer-token fallback---

Customising the Views
---------------------

[](#customising-the-views)

Publish the Blade views to override them:

```
php artisan vendor:publish --tag=admin-dashboard-guard-views
```

Files land in `resources/views/vendor/admin-dashboard-guard/`:

ViewPurpose`passphrase-login.blade.php`Step 1 — passphrase entry form`password-login.blade.php`Step 2 — password entry form`emails/admin-passphrase.blade.php`Passphrase notification emailEach view receives `$toolName`, `$toolPath`, and `$themeColor` variables.

---

Customising the Passphrase Email Subject
----------------------------------------

[](#customising-the-passphrase-email-subject)

Pass a custom subject when constructing the mailable directly:

```
use SerenityTechnologies\AdminDashboardGuard\Mail\AdminPassphrase;

Mail::to($admin)->send(new AdminPassphrase($passphrase, 'Your Dashboard Passphrase'));
```

---

Sanctum Bearer Token Fallback
-----------------------------

[](#sanctum-bearer-token-fallback)

When `sanctum_support` is `true` and `laravel/sanctum` is installed, the middleware also accepts a valid personal-access token belonging to an instance of the configured model class. This lets programmatic/API clients access protected pages without going through the browser-based session flow.

---

Security Notes
--------------

[](#security-notes)

- Passphrases are **never stored in plain text** — only a bcrypt hash is saved in the database.
- Each passphrase hash is verified with `Hash::check()` by iterating admin records; no plain-text comparison occurs.
- The passphrase step has a configurable short TTL (10 minutes by default) and is cleared from the session once the password step completes.
- The fully-authenticated session is TTL-scoped per protected page, so sessions for `/horizon` and `/telescope` are completely independent.
- Use `admin-guard:clear-passphrases --force` to invalidate all active passphrases immediately during a security incident.
- The auto-removal delay (`--delay`) is enforced via a queued job so that passphrases can never be left active indefinitely by accident.

---

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance97

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

2

Last Release

16d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/99ddbbb67396f6e60e5e14f1836686788ce5bc6f83f1c44577266cd12dcd29a8?d=identicon)[kwadwokyeremeh](/maintainers/kwadwokyeremeh)

---

Top Contributors

[![kwadwokyeremeh](https://avatars.githubusercontent.com/u/20841644?v=4)](https://github.com/kwadwokyeremeh "kwadwokyeremeh (11 commits)")

### Embed Badge

![Health badge](/badges/serenity-technologies-admin-dashboard-guard/health.svg)

```
[![Health](https://phpackages.com/badges/serenity-technologies-admin-dashboard-guard/health.svg)](https://phpackages.com/packages/serenity-technologies-admin-dashboard-guard)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k14.1M120](/packages/laravel-pulse)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

76318.2M110](/packages/laravel-mcp)[hasinhayder/tyro

Tyro - The ultimate Authentication, Authorization, and Role &amp; Privilege Management solution for Laravel 12 &amp; 13

6753.6k5](/packages/hasinhayder-tyro)[api-platform/laravel

API Platform support for Laravel

59156.3k10](/packages/api-platform-laravel)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1232.2k16](/packages/fleetbase-core-api)

PHPackages © 2026

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