wearedevtical/novassport
NovaPassport brings Laravel Passport management into Laravel Nova, letting you create, view, and revoke OAuth clients and access tokens from a clean Nova interface. It simplifies administering API credentials without building custom Passport screens.
novassport is a Nova tool for managing Laravel Passport OAuth clients from the admin panel — creating clients, rotating secrets, assigning scopes, and auditing grants without dropping into tinker or passport:client.
Minimal setup:
composer require wearedevtical/novassport
php artisan passport:install # if Passport isn't set up yet
php artisan vendor:publish --tag=novassport-config
Register the tool in app/Nova/NovaServiceProvider.php:
public function tools()
{
return [
new \Wearedevtical\Novassport\Novassport,
];
}
If the package ships migrations, run php artisan migrate before opening the tool — the resource will 500 on a missing table otherwise. Check the README for the exact config/asset tags in v2, since tags are the part most likely to shift during a rebrand.
First use case: create a password grant client for a first-party SPA/mobile app, or a client credentials client for service-to-service calls. Both are one form submission in the Nova UI versus a passport:client --password round trip. Grab the ID/secret from the edit screen, drop them into config/services.php or your frontend build secrets, and you're done — no more oauth_clients rows hand-written into seeders.
On v2.0.2 specifically: it's a maintenance release (rebrand, sync/refactor, removed empty CSS). No new features, no changelog-flagged breaking changes. If you're on 2.0.1, upgrade is low risk — but see the rebrand note under Gotchas.
Treat the Nova UI as ops tooling, not as provisioning. Use it to create and rotate clients interactively, but keep the authoritative client list in migrations or a seeder per environment so migrate:fresh on a new dev machine doesn't leave you recreating secrets by hand:
// database/seeders/OAuthClientSeeder.php
Artisan::call('passport:client', [
'--password' => true,
'--name' => 'First-party SPA',
'--provider' => 'users',
]);
The Nova tool then handles the drift — revoking stray clients, rotating a leaked secret, assigning scopes after launch.
Environment separation. Passport clients are stored per-database, so your local, staging, and production client IDs differ. Never hardcode a client ID in frontend code; source it from config/services.php populated by env vars, and use the Nova tool per environment to fetch the matching value.
Scopes. Define scopes once in AuthServiceProvider via Passport::tokensCan([...]), then use the Nova client edit screen to attach the allowed scope set per client. This keeps the "what can this client request" decision in one place (the client record) and the "what does this scope mean" decision in another (the provider).
Rotation workflow. When rotating: create the new secret on the client, deploy it to consumers, let old tokens expire (or revoke via Passport::token()->where('client_id', ...)->delete()), then confirm in the Nova UI that only the expected tokens remain. Don't delete the client and recreate it — that invalidates every already-issued refresh token and forces every consumer to re-authenticate.
Testing. The Nova tool doesn't change how you test auth — keep using Passport::actingAs($user, ['scope-a']) in feature tests. If you're writing tests for the tool, act as a Nova user with the right permissions (Nova::actingAs), because the resource is gated behind Nova's authorization layer.
Multi-guard / multi-provider apps. Passport supports per-guard providers. If you serve both users and admins, create separate clients with different provider values, and name them descriptively in the Nova UI — the default "Laravel Password Grant Client" naming bites you the moment there are two.
Rebrand = republish and clear caches. PRs #17/#18 rebranded the package. Even in a patch release, that often means config file contents, asset paths, or the tool's display name changed. After upgrading:
php artisan vendor:publish --tag=novassport-config --force
php artisan config:clear && php artisan view:clear
php artisan nova:publish # if the tool registers assets
Diff the republished config against yours before forcing — if you've customized keys (e.g. table names, guard), a blind --force silently reverts them.
Removed empty CSS (PR #13). If you were importing vendor/wearedevtical/novassport/dist/css/novassport.css into your own build — or any asset path that was previously shipped-but-empty — that import will now 404 and break npm run prod. Either drop the import (Nova already loads tool assets via its own mix pipeline) or switch to the published tag. This is the one item in the changelog most likely to cause a visible break, and it's cosmetic-only.
Sync/refactor (PRs #14, #16). "Sync" here reads like keeping the resource in step with Nova's newer APIs. Patch-level, but if you've subclassed the tool or the underlying resource to add fields, re-check that your subclass still resolves — refactors love to move namespaces. Run the tool once in staging before promoting.
config:cache in production. Any config change requires php artisan config:cache on deploy; a stale config cache is the #1 cause of "the tool worked yesterday." Similarly route:cache after upgrades that touch Nova routes.
401 with correct credentials almost always means one of: wrong grant type for the endpoint, client secret mismatch (re-check against the Nova client detail view), or missing/stale storage/oauth-private.key. php artisan passport:keys --force regenerates keys but invalidates outstanding tokens — a last resort, not a debugging step.
Token bloat. Passport accumulates rows in oauth_access_tokens. Schedule Passport::pruneRevokedTokens() or php artisan passport:purge — the Nova UI showing thousands of expired tokens is a symptom, not the disease.
Personal access clients are per-environment singletons. passport:client --personal sets a flag on one row; if you delete that client through the Nova UI, $user->createToken() breaks app-wide. Hide or soft-protect it via the resource's authorization policy rather than trusting future-you not to click delete.
Extension points. The resource and its fields are the intended customization surface — override the resource class in config or vendor:publish the views to add columns (last-used-at, owner, environment). Prefer that over editing vendor files, which the rebrand in this release makes especially painful to track.
How can I help you explore Laravel packages today?