PHPackages                             stevie-mccomb/warden - 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. stevie-mccomb/warden

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

stevie-mccomb/warden
====================

A capabilities-based role system for Laravel.

00PHP

Since Jul 25Pushed 1y ago1 watchersCompare

[ Source](https://github.com/stevie-mccomb/warden)[ Packagist](https://packagist.org/packages/stevie-mccomb/warden)[ RSS](/packages/stevie-mccomb-warden/feed)WikiDiscussions trunk Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![Laravel](https://camo.githubusercontent.com/52e42c51e158ab1bdf25794235cfe6778b5f340d9be11599125cb2ced881a7aa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312e782d464632443230)](https://camo.githubusercontent.com/52e42c51e158ab1bdf25794235cfe6778b5f340d9be11599125cb2ced881a7aa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312e782d464632443230)[![Code Coverage: 100%](https://camo.githubusercontent.com/13ef3334241a7a1f5552ead234dff1b6ec70d2ef4e84d3b533785251019c2538/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f6465253230436f7665726167652d3130302532352d677265656e "Code Coverage: 100%")](https://camo.githubusercontent.com/13ef3334241a7a1f5552ead234dff1b6ec70d2ef4e84d3b533785251019c2538/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f6465253230436f7665726167652d3130302532352d677265656e)[![SemVer](https://camo.githubusercontent.com/4c64f33d2c6eb90c150f7852dd9b22df255344fc2930f2cb1306576abbbbc65d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53656d5665722d302e312e302d626c7565)](https://camo.githubusercontent.com/4c64f33d2c6eb90c150f7852dd9b22df255344fc2930f2cb1306576abbbbc65d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53656d5665722d302e312e302d626c7565)

[![Warden](https://raw.githubusercontent.com/stevie-mccomb/warden/trunk/assets/warden-logo.webp "Warden")](https://raw.githubusercontent.com/stevie-mccomb/warden/trunk/assets/warden-logo.webp)

Capabilities-based security system for Laravel.
-----------------------------------------------

[](#capabilities-based-security-system-for-laravel)

Easily generate a set of roles and capabilities from a config file and then assign them to your users via database relations. Useful for building web apps that support custom roles that are editable via UI.

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

[](#installation)

```
composer require stevie-mccomb/warden

```

Publish Assets
--------------

[](#publish-assets)

```
php artisan vendor:publish --tag=warden

```

This will publish the built-in migrations and config file. The files that will be published are:

```
// Migrations
database/migrations/{date}_create_capabilities_table.php
database/migrations/{date}_create_roles_tables.php
database/migrations/{date}_create_capability_capability_tables.php
database/migrations/{date}_create_capability_role_tables.php

// Config
config/warden.php
```

Quick-start / Basic Usage
-------------------------

[](#quick-start--basic-usage)

1. Run the built-in migrations.

```
php artisan migrate
```

2. Configure your capabilities and roles.

```
// config/warden.php

'capabilities' => [
    [ 1, 'Manage Users', 'manage-users' ],
    [ 2, 'Create Posts', 'create-posts' ],
    [ 3, 'Publish Posts', 'publish-posts' ],
    [ 4, 'Archive Posts', 'archive-posts' ],
],

'roles' => [
    [ 1, 'Administrator', 'admin' ],
    [ 2, 'Editor', 'editor' ],
],

'capability_role_map' => [
    'admin' => '*', // grant all capabilities
    'editor' => [ // grant specific capabilities
        'create-posts',
        'publish-posts',
        'archive-posts',
    ],
],
```

3. Update your database with your configured capabilities/roles.

```
php artisan warden:update

```

4. Add the `Stevie\Warden\HasRoles` trait to your `App\Models\User` model.

```
use Stevie\Warden\Traits\HasRoles;

class User
{
    use HasRoles;
}
```

5. Assign roles to your users.

```
use Stevie\Warden\Models\Role;

$user->roles()->sync(
    Role::where('slug', 'editor')->pluck('id')
);
```

6. Check user capabilities.

```
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController
{
    public function publish(Request $request)
    {
        // Using a gate:
        if (!Gate::allows('publish-posts')) {
            abort(403);
        }

        // Using Laravel's user capability method:
        if (!$request->user()->can('publish-posts')) {
            abort(403);
        }

        // Or manually, if complex logic is needed:
        if (!$request->user()->capabilities()->where('slug', 'publish-posts')->exists()) {
            abort(403);
        }

        // ...
    }
}
```

> Note: Warden is not a replacement for Laravel's [Policies](https://laravel.com/docs/authorization#creating-policies) and is instead meant to be used alongside them. You can use Warden's global security [Gate](https://laravel.com/docs/authorization#gates) by itself, or inside of your [Policy](https://laravel.com/docs/authorization#creating-policies) methods. Check the [usage examples](#usage-examples) section for examples of both use-cases.

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

[](#configuration)

```
php artisan vendor:publish --tag=warden

```

This will publish a config file at `config/warden.php` that can be edited to control the behavior of Warden. The starter config file contains the following fields:

### Capabilities

[](#capabilities)

You can define the list of capabilities that you would like to grant to your application's users. Warden provides a global security [Gate](https://laravel.com/docs/authorization#gates) that can be used to check if an authenticated user has access to perform some action.

### Roles

[](#roles)

Use this option to define the roles that act as a wrapper around a group of capabilities. This role-based system is the heart of Warden, and makes it easy to group a set of capabilities together and assign them to users en masse. It also makes it easy to update a given group of users' capabilities later by simply updating their role when new capabilities are created.

### Capability/Role Map

[](#capabilityrole-map)

This config option tracks the relationship between capabilities and roles. Use this to determine which roles grant which capabilities to your users.

### Capability Dependency Map

[](#capability-dependency-map)

This is an optional feature that allows you to assign capabilities as dependencies for other capabilities. While this doesn't do anything on the surface in a default installation, you can use this feature within your own UI or back-end code to control the granting of necessary capabilities that may depend on each other.

For example, let's say your application has a dedicated admin panel where all administrative pages live. One of the administrative operations of your application may be user management. You may have a `view-admin` capability and a `manage-users` capability, but you can't manage users without accessing the admin area, so it makes sense for `manage-users` to depend on `view-admin` and for your application to automatically grant that dependency when `manage-users` is granted.

If you want to make use of this feature when syncing capabilities to roles in your own logic, there is a helper method called `syncWithDependencies` on the relation returned from `Role::capabilities` which makes it easy to sync capabilities *and* their dependencies without having all of the dependencies selected in the UI, though it's recommended you still select the dependencies in the UI for a better UX and to avoid user confusion. See example below for usage of `syncWithDependencies`:

```
// config/warden.php
'capability_dependency_map' => [
    'update-posts' => [
        'index-posts',
    ],
],

---

// Controller
use Stevie\Warden\Models\Capability;
use Stevie\Warden\Models\Role;

$capabilities = Capability::where('slug', 'update-posts')->value('id');

$role = Role::where('slug', 'example-role')->first();

$role->capabilities()->syncWithDependencies($capabilities);

dd($role->capabilities->toArray()); // [ 'view-posts', 'update-posts' ]
```

### Database Tables

[](#database-tables)

You can change the names of Warden's default tables, if desired. The keys of this array should not be changed as those are Warden's internal identifiers for the tables; the values are the table names.

### Class Map

[](#class-map)

If you want to override or replace a subset of functionality within the package, you can replace one of the class paths in this class map with your own class. At runtime, Warden will use the config file class map for determining which classes should be handling its features.

### Broadcasting Channels

[](#broadcasting-channels)

The two built-in Laravel [Models](https://laravel.com/docs/eloquent) (Capability and Role) utilize all of the [model events](https://laravel.com/docs/11.x/eloquent#events) defined in Laravel's documentation and automatically dispatch these events whenever the models are retrieved, updated, deleted, etc. You can make use of these events in two ways:

1. Bind your own [Listeners](https://laravel.com/docs/events#defining-listeners) to them.
2. Listen for them on the front-end with [Laravel Echo](https://laravel.com/docs/broadcasting).

In the event that you would like to utilize [Laravel Echo](https://laravel.com/docs/broadcasting), you can configure this option to use whatever broadcast channel your application prefers.

For a full list of events that your app can listen for, check the package's [src/Events](https://github.com/stevie-mccomb/warden/tree/trunk/src/Events) directory.

Usage Examples
--------------

[](#usage-examples)

- [Assigning roles to your users](#assigning-roles-to-your-users)
- [Checking user capabilities with a gate](#checking-user-capabilities-with-a-gate)
- [Checking user capabilities via Laravel can method](#checking-user-capabilities-via-laravel-can-method)
- [Checking user capabilities manually](#checking-user-capabilities-manually)
- [Checking user capabilities inside a policy](#checking-user-capabilities-inside-a-policy)

### Assigning roles to your users

[](#assigning-roles-to-your-users)

```
use Illuminate\Http\Request;

class ExampleController
{
    public function updateUserRoles(Request $request, User $user)
    {
        $rolesTable = config('warden.tables.roles');

        $safe = $request->validate([
            'roles' => 'required|array',
            'roles.*' => "required|exists:$rolesTable,id",
        ]);

        $user->roles()->sync($safe['roles']);
    }
}
```

### Checking user capabilities with a gate

[](#checking-user-capabilities-with-a-gate)

```
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class ExampleController
{
    public function example(Request $request)
    {
        if (!Gate::allows('example-capability')) {
            abort(403);
        }

        // ...
    }
}
```

### Checking user capabilities via Laravel can method

[](#checking-user-capabilities-via-laravel-can-method)

```
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class ExampleController
{
    public function example(Request $request)
    {
        if (!$request->user()->can('example-capability')) {
            abort(403);
        }

        // ...
    }
}
```

### Checking user capabilities manually

[](#checking-user-capabilities-manually)

```
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class ExampleController
{
    public function example(Request $request)
    {
        if (
            !$request->user()->capabilities()
                ->where('slug', 'example-capability')
                ->exists()
        ) {
            abort(403);
        }

        // ...
    }
}
```

### Checking user capabilities inside a policy

[](#checking-user-capabilities-inside-a-policy)

```
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

class PostPolicy
{
    public function publish(User $user, Post $post): bool
    {
        return $user->can('publish-posts') && $user->is($post->user);
    }
}
```

### Allow user-defined roles in your application

[](#allow-user-defined-roles-in-your-application)

First, override the built-in role seeders to prevent user-defined roles from being overwritten in future database updates. You will need to define your own logic for how you want to seed these tables (or even just make empty seeders that do nothing if you don't plan on having any built-in roles).

```
// config/warden.php

'class_map' => [
    'seeders' => [
        // ...
        'roles' => \Database\Seeders\RolesTableSeeder::class,
        'capability_role' => \Database\Seeders\CapabilityRoleTableSeeder::class,
    ],

    // ...
],
```

A common approach is to have reserved role names like "Super Administrator" or "Client Administrator" which you seed in your back-end and have special logic within the application, while allowing some users (maybe those Client Administrators, for example) to define their own roles.

This way, your seeders can seed your application's reserved roles while your users can create their own roles and they can both co-exist while using Warden's logic internally. See example custom seeder below.

```
use Illuminate\Support\Database\Schema;

class ExampleRolesTableSeeder
{
    public function run()
    {
        $roles = config('warden.tables.roles');

        DB::statement("
            INSERT INTO
                $roles (`name`, `slug`)
            VALUES
                (1, 'Super Administrator', 'super-administrator'),
                (2, 'Client Administrator', 'client-administrator')
            ON DUPLICATE KEY UPDATE
                `name` = VALUES(`name`),
                `slug` = VALUES(`slug`),
                `updated_at` = CURRENT_TIMESTAMP;
        ");
    }
}
```

In the example above, these two roles with ID 1 and 2 can be added into your application early on, before users can define their own roles and they'll be seeded when you run the `artisan warden:update` command. If you wanted to prevent users from defining their own roles with the same names, you could do that in your validation logic.

Next, create routes and controllers for defining roles and attaching them to your users.

```
// e.g. POST /admin/roles
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Stevie\Warden\Models\Role;

class RoleController
{
    /**
     * Create a new role with the given capabilities
     * and attach it to the given users.
     */
    public function store(Request $request): RedirectResponse
    {
        // Validate the input.
        $capabilitiesTable = config('warden.tables.capabilities');
        $rolesTable = config('warden.tables.roles');
        $safe = $request->validate([
            'name' => "required|string|max:255|unique:$rolesTable",
            'slug' => "required|string|max:255|unique:$rolesTable",
            'capabilities' => 'nullable|array',
            'capabilities.*' => "required|integer|exists:$capabilitiesTable",
            'users' => 'nullable|array',
            'users.*' => 'required|integer|exists:users',
        ]);

        // Create the role.
        $role = Role::create([
            'name' => $safe['name'],
            'slug' => $safe['slug'],
        ]);

        // Attach the capabilities to the role.
        $role->capabilities()->sync($safe['capabilities']);

        // Attach the role to the given users.
        $role->users()->sync($safe['users']);

        // Redirect.
        return to_route('roles.index')
            ->with('success', 'Role successfully created.');
    }
}
```

###  Health Score

13

—

LowBetter than 1% of packages

Maintenance28

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity17

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/6c23a33f828eba94fcc4a5eb4ce4a4036781e2a9ed10428d8c5001f0c0e05594?d=identicon)[stevie-mccomb](/maintainers/stevie-mccomb)

---

Top Contributors

[![stevie-mccomb](https://avatars.githubusercontent.com/u/4782720?v=4)](https://github.com/stevie-mccomb "stevie-mccomb (8 commits)")

### Embed Badge

![Health badge](/badges/stevie-mccomb-warden/health.svg)

```
[![Health](https://phpackages.com/badges/stevie-mccomb-warden/health.svg)](https://phpackages.com/packages/stevie-mccomb-warden)
```

###  Alternatives

[namshi/jose

JSON Object Signing and Encryption library for PHP.

1.8k99.6M101](/packages/namshi-jose)[league/oauth1-client

OAuth 1.0 Client Library

99698.8M106](/packages/league-oauth1-client)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k2.9M88](/packages/bezhansalleh-filament-shield)[gesdinet/jwt-refresh-token-bundle

Implements a refresh token system over Json Web Tokens in Symfony

70516.4M35](/packages/gesdinet-jwt-refresh-token-bundle)[league/oauth2-google

Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client

41721.2M118](/packages/league-oauth2-google)[illuminate/auth

The Illuminate Auth package.

9327.3M1.0k](/packages/illuminate-auth)

PHPackages © 2026

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