PHPackages                             cerberus-iam/laravel-sdk - 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. cerberus-iam/laravel-sdk

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

cerberus-iam/laravel-sdk
========================

Laravel bridge for the Cerberus IAM platform providing guard, middleware, and HTTP client integration.

116PHPCI passing

Since Nov 8Pushed 6mo agoCompare

[ Source](https://github.com/cerberus-iam/laravel-sdk)[ Packagist](https://packagist.org/packages/cerberus-iam/laravel-sdk)[ RSS](/packages/cerberus-iam-laravel-sdk/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Cerberus IAM | Laravel SDK
==========================

[](#cerberus-iam--laravel-sdk)

A framework-agnostic bridge that lets any Laravel application outsource authentication and user directory responsibilities to the [Cerberus IAM API](../README.md). Instead of maintaining local passwords, session stores, and role logic, you attach this package, configure a guard, and delegate the heavy lifting to Cerberus.

---

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

[](#requirements)

ComponentVersionPHP8.2+Laravel components10.x / 11.xcerberus-iam/apiCompatible REST instancejerome/filterable^2.0 (optional request filtering)> The package is designed for multi-tenant environments. Ensure the API instance you point to has the desired organisations, roles, and OAuth clients configured.

---

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

[](#installation)

```
composer require cerberus-iam/laravel-sdk
php artisan vendor:publish --provider="CerberusIAM\\Providers\\CerberusIamServiceProvider" --tag=config
```

Publishing yields `config/cerberus-iam.php` – the single source of truth for connecting to the IAM platform.

### Environment Variables

[](#environment-variables)

```
CERBERUS_IAM_URL=https://api.cerberus-iam.com
CERBERUS_IAM_CLIENT_ID=
CERBERUS_IAM_CLIENT_SECRET=
CERBERUS_IAM_USERNAME="admin@cerberus-iam.com"
CERBERUS_IAM_PASSWORD="Password123!"
CERBERUS_IAM_REDIRECT_URI="${APP_URL}/cerberus/callback"
CERBERUS_IAM_SCOPES="openid profile email"
CERBERUS_IAM_SESSION_COOKIE=cerb_sid
CERBERUS_IAM_ORG_SLUG=cerberus-iam
CERBERUS_IAM_HTTP_TIMEOUT=10
CERBERUS_IAM_HTTP_RETRY=true
CERBERUS_IAM_HTTP_RETRY_ATTEMPTS=2
CERBERUS_IAM_HTTP_RETRY_DELAY=100
CERBERUS_IAM_PORTAL_URL=https://app.cerberus-iam.com
CERBERUS_IAM_PROFILE_URL=
CERBERUS_IAM_SECURITY_URL=
CERBERUS_IAM_REDIRECT_AFTER_LOGIN=/dashboard
CERBERUS_IAM_USER_MODEL=
```

### HTTP Client Customisation

[](#http-client-customisation)

All outbound calls now run through Laravel's HTTP client, so you get first-class support for `Http::fake()`, middleware, and macros. Tune timeouts or retry behaviour via `cerberus-iam.http` in the config (or the matching environment variables shown above). If you need deeper customisation you can register macros/global middleware on the `Http` facade the same way you would in any Laravel app—those hooks automatically apply to the SDK because it resolves the shared HTTP factory from the container.

---

Database Requirements
---------------------

[](#database-requirements)

Cerberus IAM uses UUIDs for user identifiers. You must configure your Laravel application's database to support this.

### Sessions Table

[](#sessions-table)

Update your sessions table migration to use string for `user_id`:

```
$table->string('user_id')->nullable()->index();
```

If you already have a sessions table with a bigint `user_id` column, create a migration to convert it:

```
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('sessions', function (Blueprint $table) {
            $table->string('user_id')->nullable()->change();
        });
    }

    public function down(): void
    {
        Schema::table('sessions', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id')->nullable()->change();
        });
    }
};
```

### User Model (Optional but Recommended)

[](#user-model-optional-but-recommended)

By default, the SDK retrieves user data from Cerberus IAM on every request (stateless mode). For better performance and integration with Laravel's ecosystem, you can configure the SDK to sync users to a local database table.

To enable database-backed authentication, set the `CERBERUS_IAM_USER_MODEL` environment variable:

```
CERBERUS_IAM_USER_MODEL=App\\Models\\User
```

Your `users` table migration should include:

```
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('cerberus_id')->unique(); // UUID from Cerberus IAM
    $table->string('name');
    $table->string('email')->unique();

    // Optional fields
    $table->string('first_name')->nullable();
    $table->string('last_name')->nullable();
    $table->string('organisation_id')->nullable();
    $table->string('organisation_slug')->nullable();

    $table->timestamps();
});
```

Your User model must:

1. Implement `Illuminate\Contracts\Auth\Authenticatable` (typically via `Illuminate\Foundation\Auth\User`)
2. Have `cerberus_id`, `name`, and `email` in the `$fillable` array
3. Optionally include `first_name`, `last_name`, `organisation_id`, `organisation_slug`

Example User model:

```
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    protected $fillable = [
        'cerberus_id',
        'name',
        'email',
        'first_name',
        'last_name',
        'organisation_id',
        'organisation_slug',
    ];
}
```

When database-backed authentication is enabled:

- Users are automatically created/updated in your local database on login
- Subsequent requests retrieve the user from your database (fast)
- User data is refreshed from Cerberus on each login

---

Guard Setup
-----------

[](#guard-setup)

Replace the default `web` guard (or add a dedicated guard) in `config/auth.php`:

```
'guards' => [
    'web' => [
        'driver' => 'cerberus',
        'provider' => 'cerberus-users',
        'scopes' => ['openid', 'profile', 'email'],
    ],
],

'providers' => [
    'cerberus-users' => [
        'driver' => 'cerberus',
    ],
],
```

The package registers:

- `cerberus` guard (stateful)
- `cerberus` user provider (fetches profiles from IAM as-needed)
- Middleware alias `cerberus.auth`

---

Authentication Flow
-------------------

[](#authentication-flow)

1. **Incoming request** hits a protected route.
2. `EnsureCerberusAuthenticated` checks the guard; guests are redirected to Cerberus using PKCE.
3. After login/consent, the IAM redirects to `/cerberus/callback` (included route) with an auth code.
4. `CerberusGuard::loginFromAuthorizationCode()` exchanges the code for tokens, stores them via the `TokenStore`, and pulls the user profile from `/oauth2/userinfo`.
5. Subsequent requests reuse access tokens, automatically refresh them with the IAM when expired, and fall back to Cerberus' session cookie if present.

### Protecting Routes

[](#protecting-routes)

```
Route::middleware('cerberus.auth')->group(function () {
    Route::view('/dashboard', 'dashboard');
});
```

You can override the default redirect target by passing it as middleware parameter:

```
Route::middleware('cerberus.auth:/account')->get('/settings', SettingsController::class);
```

---

Callback Route
--------------

[](#callback-route)

The package registers `/cerberus/callback` under the `web` middleware group. If you already have a route with that URI, disable the auto-registration by caching routes and defining your own controller that proxies to `CerberusGuard::loginFromAuthorizationCode()`.

```
use CerberusIAM\Auth\CerberusGuard;
use Illuminate\Support\Facades\Auth;

Route::get('/cerberus/callback', function (Request $request) {
    /** @var CerberusGuard $guard */
    $guard = Auth::guard('cerberus');
    $guard->loginFromAuthorizationCode(
        $request->query('code'),
        $request->query('state')
    );

    return redirect()->intended(config('cerberus-iam.redirect_after_login'));
});
```

---

Token &amp; State Storage
-------------------------

[](#token--state-storage)

By default tokens live in the session using `CerberusIAM\Support\Stores\SessionTokenStore`. You can swap it for Redis or any persistent store by binding the interfaces:

```
use CerberusIAM\Contracts\TokenStore;
use CerberusIAM\Contracts\OAuthStateStore;
use App\Auth\RedisTokenStore;
use App\Auth\RedisOAuthStateStore;

$this->app->bind(TokenStore::class, fn () => new RedisTokenStore());
$this->app->bind(OAuthStateStore::class, fn () => new RedisOAuthStateStore());
```

Both interfaces are minimal:

```
interface TokenStore {
    public function store(array $payload): void;
    public function retrieve(): ?array;
    public function clear(): void;
}
```

The guard asks the store for `access_token`, `refresh_token`, and optionally `expires_at` (ISO8601). Refresh happens automatically when `expires_at` is in the past.

---

HTTP Client &amp; Facade
------------------------

[](#http-client--facade)

`CerberusIAM\Http\Clients\CerberusClient` delegates to Laravel's HTTP client, so anything you register via `Http::macro()` or `Http::middleware()` flows through automatically. Use the facade when you need low-level access:

```
use CerberusIAM\Facades\CerberusIam;

$jwks = CerberusIam::url('/oauth2/jwks.json');
$response = CerberusIam::getUserInfo($accessToken);
```

The client respects the timeout/retry options defined in `cerberus-iam.php`.

---

User Directory Proxy
--------------------

[](#user-directory-proxy)

Cerberus exposes administrative endpoints (e.g. `/v1/admin/users`). To keep your Laravel controllers tidy, use the bundled repository + filter pipeline:

```
use CerberusIAM\Repositories\UserDirectoryRepository;
use Illuminate\Http\Request;

class AdminUserController
{
    public function __invoke(Request $request, UserDirectoryRepository $repository)
    {
        $directory = $repository->list(
            organisationSlug: $request->header('X-Org-Domain'),
            request: $request,
            options: ['per_page' => 25],
            accessToken: auth()->guard('cerberus')->getTokenStore()->retrieve()['access_token'] ?? null,
            sessionToken: $request->cookie(config('cerberus-iam.session_cookie'))
        );

        return view('admin.users.index', ['users' => $directory['data'] ?? []]);
    }
}
```

`UserDirectoryFilter` leverages [`jerome/filterable`](https://github.com/Thavarshan/filterable) so your existing HTTP filters map to IAM query parameters (`filter[email]`, `filter[mfa_enabled]`, etc.).

---

Customising Behaviour
---------------------

[](#customising-behaviour)

ConcernContractDefaultNotesIAM client`CerberusIAM\Contracts\IamClient``Http\Clients\CerberusClient`Replace to mock or extend API callsToken store`CerberusIAM\Contracts\TokenStore`SessionIdeal place for Redis-backed storageOAuth state`CerberusIAM\Contracts\OAuthStateStore`SessionPersist `state` + PKCE verifierUser directory`CerberusIAM\Contracts\UserRepository``Repositories\UserDirectoryRepository`Swap if you prefer GraphQL or cachingBind your implementation in any service provider to override defaults.

---

Testing &amp; Local Development
-------------------------------

[](#testing--local-development)

The package ships with a Pest suite backed by Orchestra Testbench.

```
composer test
```

To test against a live Cerberus instance locally:

1. Run the IAM API (`npm run dev` inside the main repo) and ensure an OAuth client exists.
2. Point `CERBERUS_IAM_URL` to that instance.
3. Configure the guard in a sample Laravel app, apply the middleware, and log in.

### Live Integration Tests Against

[](#live-integration-tests-against-httpsapicerberus-iamcom)

Pest now includes an optional `integration` group that exercises the SDK against the deployed API (`https://api.cerberus-iam.com`). Because these tests create real sessions and call privileged admin endpoints, they are skipped unless the following environment variables are defined:

VariableRequiredDescription`CERBERUS_IAM_BASE_URL`YesBase URL for the live API (`https://api.cerberus-iam.com`)`CERBERUS_IAM_USERNAME`YesEmail for a Cerberus account that can log in via `/v1/auth/login``CERBERUS_IAM_PASSWORD`YesPassword for the live test account`CERBERUS_IAM_CLIENT_ID`For admin flowsOAuth client ID with permission to call admin endpoints`CERBERUS_IAM_CLIENT_SECRET`For admin flowsClient secret for the above OAuth client (required for client credentials)`CERBERUS_IAM_ORG_SLUG`OptionalOrganisation slug to scope admin requests (falls back to the login response)`CERBERUS_IAM_SESSION_COOKIE`OptionalSession cookie name (defaults to `cerb_sid`)`CERBERUS_IAM_SCOPES`OptionalSpace-delimited scopes for the OAuth client (default `openid profile email`)`CERBERUS_IAM_ADMIN_SCOPES`OptionalAdditional scopes for client-credential admin calls (default `users:read`)`CERBERUS_IAM_REDIRECT_URI`OptionalRedirect URI associated with the OAuth client`CERBERUS_IAM_TIMEOUT`OptionalHTTP timeout (seconds) for the live calls, default `15`Once configured, run only the live tests with:

```
composer test -- --group=integration
```

The tests log out sessions automatically, but they still mutate real data—use service accounts and non-production organisations wherever possible.

---

Troubleshooting
---------------

[](#troubleshooting)

SymptomLikely CauseFixRedirect loop back to Cerberuscallback URL mismatchConfirm `CERBERUS_IAM_REDIRECT_URI` matches the client settings`invalid_state` exceptionSession not persistingCheck session driver, domain, and ensure HTTPS in production`Route [/cerberus/callback] not defined`Routes cached without package bootClear route cache or define the route manually401 when listing usersMissing organisation slug headerPass `X-Org-Domain` or adjust repository call`Invalid text representation: invalid input syntax for type bigint`Sessions table `user_id` is bigintChange sessions table `user_id` column to string (see Database Requirements)---

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

[](#contributing)

1. `composer install`
2. Make changes (follow PSR-12, small focused commits)
3. `composer test`
4. Submit PR referencing the IAM change if relevant

Bug reports and feature requests are welcome via issues in the main Cerberus IAM repository.

---

License
-------

[](#license)

This project is licensed under the MIT License – see [LICENSE](LICENSE) for details.

###  Health Score

19

—

LowBetter than 10% of packages

Maintenance47

Moderate activity, may be stable

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity13

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/e6a36cdb0d28baadcd00b763ff51b42fdb5128186b1ff0e46c007d43376bfe4d?d=identicon)[Thavarshan](/maintainers/Thavarshan)

---

Top Contributors

[![Thavarshan](https://avatars.githubusercontent.com/u/10804999?v=4)](https://github.com/Thavarshan "Thavarshan (35 commits)")

---

Tags

authorization-code-flowiamjwksjwtlaravellaravel-authlaravel-packagemiddlewareoauth2oidcopenid-connectpkcerbacrolessingle-sign-onssouser-provisioning

### Embed Badge

![Health badge](/badges/cerberus-iam-laravel-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/cerberus-iam-laravel-sdk/health.svg)](https://phpackages.com/packages/cerberus-iam-laravel-sdk)
```

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