PHPackages                             sandstorm/filament-keycloak-admin - 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. sandstorm/filament-keycloak-admin

ActiveLibrary

sandstorm/filament-keycloak-admin
=================================

Filament v4 admin UI for managing Keycloak users through the Keycloak Admin REST API

v1.0.0(today)00MITPHPPHP ^8.3CI failing

Since Aug 24Pushed todayCompare

[ Source](https://github.com/sandstorm/filament-keycloak-admin)[ Packagist](https://packagist.org/packages/sandstorm/filament-keycloak-admin)[ Docs](https://github.com/sandstorm/filament-keycloak-admin)[ RSS](/packages/sandstorm-filament-keycloak-admin/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (9)Versions (2)Used By (0)

Filament Keycloak Admin
=======================

[](#filament-keycloak-admin)

A Filament v4 admin panel to manage Keycloak users through the Keycloak Admin REST API. Keycloak is the source of truth — there is no local user mirror. This package is **UI only**; every HTTP call goes through the standalone client library [`sandstorm/keycloak-admin-api`](https://github.com/sandstorm/keycloak-admin-api).

- **Target:** Filament v4, PHP ^8.3, Keycloak 26.5.3+.
- **Features:** searchable user list; per-user detail with Identity (edit + enable toggle + User-Profile attributes), Groups (add/remove), Security/2FA (remove second factors), Active sessions (log out all), User events, and Admin history; and a "Send password-reset email" action.

The whole package is work in progress, and is extended as needed.

> Thanks to [BroodfondsMakers](https://www.broodfonds.nl/) for sponsoring the development of this package, and for agreeing to Open Source it!

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

[](#installation)

```
composer require sandstorm/filament-keycloak-admin
```

Register the plugin on a panel:

```
use Sandstorm\FilamentKeycloakAdmin\FilamentKeycloakAdminPlugin;

$panel->plugin(FilamentKeycloakAdminPlugin::make());
```

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

[](#configuration)

The plugin reads resolved `config('filament-keycloak-admin.*')` and never calls `env()` itself — the consuming app owns the authoritative config. Provide `config/filament-keycloak-admin.php` in your app:

```
return [
    'connection' => [
        'backchannel_url'    => 'http://keycloak.internal:8080/', // required
        'frontend_url'       => 'https://login.example/',         // optional, defaults to backchannel_url
        'administration_url' => null,                             // optional, defaults to frontend_url
        'realm'              => 'YourRealm',
        'client_id'          => 'admin-panel-serviceaccount',
        'client_secret'      => '…',
    ],
    'auth_mode' => 'service_account', // 'service_account' | 'sso' (act-as-user; see Auth modes below)
    'http' => [
        'connect_timeout' => 5,
        'timeout'         => 15,
    ],
    'pw_reset' => [
        'lifespan'     => 43200,
        'client_id'    => null,
        'redirect_uri' => null,
    ],
];
```

The package publishes only a structure-only stub (keys + docs, no values, no `env()`).

### Connection URLs

[](#connection-urls)

The three URLs follow [Keycloak's hostname nomenclature](https://www.keycloak.org/server/hostname), because a Keycloak instance can be reachable under a different address per channel:

KeyKeycloak optionUsed for`backchannel_url``--hostname-backchannel-dynamic`This application's *own* calls: the Admin REST API and the service-account token endpoint. Frequently an internal/cluster address.`frontend_url``--hostname`Anything the admin's **browser** is sent to.`administration_url``--hostname-admin`The administration console's own base URL.Only `backchannel_url` is required; `administration_url` falls back to `frontend_url`, which falls back to `backchannel_url` — the right behaviour for a single-hostname deployment.

Only the backchannel URL is used today; the other two exist so a browser is never handed an internal address.

### Auth modes

[](#auth-modes)

- **`service_account`** (wired today) — a `client_credentials` grant on a confidential client with the required `realm-management` roles: `view-users`, `manage-users`, `query-users`, `query-groups` (plus `view-events` for the event tabs). One shared identity.
- **`sso`** (act-as-user) — the Admin-API bearer is the **logged-in admin's own** Keycloak token, so Keycloak evaluates that person's fine-grained permissions and attributes admin events to them. `FilamentSsoTokenProvider` reads the token through an `AdminKeycloakSession` seam: bind your own, or install `heloufir/filament-keycloak-sso` for the bundled `HeloufirAdminKeycloakSession` adapter. Selecting `sso` with neither present fails loudly.

There is **no fallback**: a misconfigured or underprivileged mode fails loudly. Every read failure (including 401/403) propagates to the framework error page.

Testing
-------

[](#testing)

Use **mise** (see `mise.toml`):

```
composer install
mise run test              # unit/feature suite (hermetic, no Keycloak)
mise run analyse           # PHPStan
mise run lint              # Pint
mise run e2e               # full E2E cycle: boot Keycloak → integration suite → tear down
```

### End-to-end against a real Keycloak

[](#end-to-end-against-a-real-keycloak)

`mise run e2e` boots a throwaway Keycloak 26.5.3 (`tests/Integration/docker-compose.yml`) importing two realms and runs the opt-in `integration` suite against it. To iterate:

```
mise run e2e:up            # boot Keycloak (both realms) on http://localhost:9911
mise run test:integration  # run the integration suite (sets KEYCLOAK_E2E_BASE_URL for you)
mise run e2e:down          # tear down
```

**Log into the Keycloak admin console** at  with **`admin` / `admin`** (the `KC_BOOTSTRAP_ADMIN_*` creds in the compose file). Seeded users all have password `changeit`.

Two realms are imported so the `sso` act-as-user path is proven in both authorization modes:

RealmAdmin Permissions (FGAP)Notable seeded users`test-realm`**off** (classic roles)`admin-user` (realm-management roles), `login-user` (none), `jane` in `/staff``test-realm-fgap`**on**`admin-user`, `login-user`, `sarah` + `jane` in `/staff`, `emma` in `/endusers`#### FGAP staff policy (baked into `realm-import-fgap.json`)

[](#fgap-staff-policy-baked-into-realm-import-fgapjson)

Staff read everyone, edit endusers, can't touch other staff:

```
match-staff  = Group policy → members of /staff
                │
   ┌────────────┴─────────────────────────────┐
   ▼                                           ▼
"staff can view all"                  "staff can manage endusers"
 Users · view · All users              Groups · manage-members · group /endusers
   │                                           │
   ▼                                           ▼
 sarah ──view──▶ everyone            sarah ──manage──▶ emma (∈/endusers)  ✔
                                     sarah ──manage──▶ jane (∈/staff)     ✘ 403

```

License
-------

[](#license)

MIT. See [LICENSE.md](LICENSE.md).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

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

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2ced0d63cfdae881c32128c7f66451a013d3e24d9eed210d6a846b6d8e95fa3b?d=identicon)[sandstorm](/maintainers/sandstorm)

---

Top Contributors

[![skurfuerst](https://avatars.githubusercontent.com/u/190777?v=4)](https://github.com/skurfuerst "skurfuerst (17 commits)")

---

Tags

laravelkeycloakfilamentfilament-pluginfilamentphp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/sandstorm-filament-keycloak-admin/health.svg)

```
[![Health](https://phpackages.com/badges/sandstorm-filament-keycloak-admin/health.svg)](https://phpackages.com/packages/sandstorm-filament-keycloak-admin)
```

###  Alternatives

[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

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

View logged mails and events in a beautiful Filament UI.

16429.7k](/packages/backstage-mails)[marcelweidum/filament-passkeys

Use passkeys in your filamentphp app

6758.2k2](/packages/marcelweidum-filament-passkeys)[stephenjude/filament-two-factor-authentication

Filament Two Factor Authentication: Google 2FA + Passkey Authentication

85240.3k10](/packages/stephenjude-filament-two-factor-authentication)[relaticle/custom-fields

User Defined Custom Fields for Laravel Filament

16461.2k](/packages/relaticle-custom-fields)[croustibat/filament-jobs-monitor

Background Jobs monitoring like Horizon for all drivers for FilamentPHP

278359.3k12](/packages/croustibat-filament-jobs-monitor)

PHPackages © 2026

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