Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Passport Ui Laravel Package

n3xt0r/filament-passport-ui

Adds a structured Filament admin UI for Laravel Passport: manage OAuth clients by grant type, personal access tokens, and scopes in one place. Focused on visibility, review, and governance of existing OAuth resources, with no custom tooling or CLI workflows needed.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and scaffold

composer require n3xt0r/filament-passport-ui
php artisan filament-passport-ui:install

The install command is interactive — expect it to ask about your owner model (the model that owns OAuth clients), the label attribute to display for owners, and whether to enable database-backed scope management. It wires up config/passport-ui.php and points you at the migrations.

From v2 onward, the database schema is owned by n3xt0r/laravel-passport-authorization-core, not by this package. Do not assume the Passport UI install alone created the passport_scope_resources, passport_scope_actions, and passport_scope_grant tables — install/migrate the core package too, then php artisan migrate.

Register the plugin

In your panel provider:

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            \N3xt0r\FilamentPassportUi\FilamentPassportUiPlugin::make(),
        ]);
}

Register it only in the panel where OAuth administration belongs (typically /admin), not in customer-facing panels.

Where to look first

  1. config/passport-ui.php — owner model, owner label attribute, Passport model mappings, navigation group/label, enable_scopes_management.
  2. The docs index (docs/index.md) plus docs/migration-to-v2.md if you're upgrading — the v2 model change is the single most disruptive thing about this package.
  3. The three resources: ClientResource, TokenResource, and the scope resources (PassportScopeResourceResource, PassportScopeActionsResource).

First meaningful use case

Don't start by clicking "New client." Start by modelling scopes, because the client creation wizard is scope-aware:

  1. Create a scope resource (e.g. orders) and actions (read, write, refund) to produce orders:read, orders:write, orders:refund.
  2. Create a client-credentials client for a backend integration, assign orders:read only.
  3. Have the integration request a token, then confirm it appears in TokenResource with a visible token ID.
  4. Revoke the client in the UI and check that the corresponding activitylog entries exist.

That end-to-end loop (scope → client → token → revoke → audit) is the package's whole value proposition; if it doesn't work cleanly in your environment, nothing downstream will.

Implementation Patterns

Model scopes as data, not strings

The core idea is resource:action composition. Resist the temptation to use the scope table as a junk drawer of arbitrary strings — if you do, you lose the filtering, least-privilege checks, and audit readability that justify installing this at all. Seed a baseline set of resources/actions in a seeder so every environment (local, staging, prod) starts with the same scope vocabulary, and treat scope creation as a reviewed change, not a casual click.

Least privilege as a two-tier model

The package enforces that user-level scopes are a strict subset of client-level scopes. Structure your integration accordingly:

  • Client scopes = the ceiling for that integration (e.g. orders:read, orders:write).
  • Per-tokenable grants (PassportScopeGrant) = the narrower set an individual user actually approved or was granted.

So a client might hold orders:* but each user only gets orders:read. When a user reports "I can't do X," check the user-level grant first, not the client.

Provisioning via use cases instead of clicking

The resources are thin — actions route to CreateClientUseCase, EditClientUseCase, SaveOwnershipRelationUseCase, etc. Call the same use cases from your own artisan command or seeder for repeatable provisioning:

  • Good for: bootstrapping known integrations per environment, integration tests, backfills.
  • The payoff is that events (OAuthClientCreated, OAuthClientRevoked) and activity log entries fire exactly as they do from the UI, so your audit trail stays consistent whether a human or a script made the change.

If you bypass the use cases and write directly to oauth_clients, you silently lose auditability — which is the feature you paid for.

Owner model wiring

Point the owner model at whatever your tenancy unit is: User for small teams, Team/Organization for multi-tenant. Set the label attribute to something humans recognise (name, not email-as-ID). The "All owners" use cases (GetAllOwnersUseCase, GetAllOwnersRelationshipUseCase) drive the owner select — if that dropdown is empty or wrong, your owner config is the culprit, not the resources.

Self-service panels (v2.4+)

For non-admin panels where users manage their own clients:

FilamentPassportUiPlugin::make()->selfService()

This scopes ClientResource and TokenResource to the authenticated user's records and locks the owner field server-side. Use a separate panel (or at minimum separate policies) rather than trying to make one panel do both jobs — mixing admin and self-service in one navigation gets confusing fast, and the filtering is ownership-based, not role-based.

Offboarding and revocation workflow

Favour revoke over delete. Revoking preserves the record and the audit trail; deleting a client can orphan token rows and destroys the "who had what, when" story. A practical pattern: listen for OAuthClientRevoked and notify the owning team / open a ticket, then separately expire tokens so downstream integrations fail fast rather than lingering.

Audit log consumption

Everything goes through spatie/laravel-activitylog, and the logs stay application-owned. That's good (you can query, export, retain on your own schedule) and also a chore (nobody prunes it for you). Decide up front:

  • Retention window for activity log rows (compliance often wants 1–3 years; ops wants them small).
  • Whether to ship entries to an external SIEM via a model event listener.
  • Whether to surface a per-client activity timeline to support staff.

Gotchas and Tips

The config namespace bug — check your version. Prior to 2.4.0, the plugin read config('filament-passport-ui.enable_scopes_management') while the config was published under passport-ui. The option silently fell back to true no matter what you set. If you're pinned below 2.4.0 and think you disabled scope management, you didn't. Read config('passport-ui.*') in all your own overrides.

Hard version floors. PHP ^8.4, Laravel ^12/^13, Passport ^13, Filament v4/v5. These are aggressive minimums — on PHP 8.3 or Filament v3 this package simply won't install. Verify before you promise it to anyone. If you're on Laravel 11, you're out of scope.

It does not authorise anything at runtime. The README is explicit and it matters: this package is administration and visibility only. You still need your own scope-checking middleware, policies, or Passport scope middleware on the API routes. A beautifully governed client with orders:write can still call whatever your API lets it call — the UI doesn't enforce a thing.

Stale caches after scope changes. The service layer uses cached repository decorators and a ScopeRegistryService cache. After seeding scopes, changing config, or bulk-importing grants, run:

php artisan filament-passport-ui:cleanup-cache

Symptom of forgetting: new scopes exist in the DB but never appear in the client wizard.

Custom Passport models require config mapping. If you've swapped Laravel\Passport\Client or Token for your own subclasses, publish and edit the model mappings in config/passport-ui.php. Skipping this produces wrong-model bugs in table columns — the changelog already records one such fix (LastLoginColumn rendering against the wrong model).

Don't rely on the UI for ownership enforcement. selfService() filters the query and locks the form field server-side, which is the right design — but if you add custom actions, bulk operations, or your own resources on top, you must re-apply the ownership constraint yourself. Filament resource getEloquentQuery() scoping does not automatically protect every action you bolt on.

Migration to v2 is a real migration. Schema and optional config moved to the core package and are not published automatically. Budget for it: read docs/migration-to-v2.md, confirm old tables vs. new, and be prepared to backfill passport_scope_grant data from whatever ad-hoc structure you had before.

Maturity caveat. 11 stars, zero dependents, a very recent and rapid changelog. That's not a disqualifier — the architecture (use cases, strategies, repository contracts) is more disciplined than most Filament plugins — but it means you are the QA. Pin an exact version, skim the resource and use-case source before extending, and avoid the assumption that a documented extension point is battle-tested. The 2.4.0 config bug is a good illustration: the feature existed, was documented, and did nothing for several releases.

Extension points that actually hold up. Override navigation via config, subclass resources for extra columns/actions, and wrap use cases rather than replacing them. The repository contracts and the ClientFactory strategies (one per grant type) are the cleanest seams — a custom grant type or a bespoke provisioning flow goes there, not in a resource closure.

Localisation is en/de only. For other locales, publish and add translations rather than shipping a half-translated admin panel to operations staff.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo