cboxdk / laravel-id-client
Laravel/PHP consumer SDK for Cbox ID — turnkey OIDC login, hosted profile-management redirect, machine tokens, and webhook verification against a Cbox ID instance.
Requires
- php: ^8.4
- firebase/php-jwt: ^7.0
- illuminate/contracts: ^12.0 || ^13.0
- illuminate/http: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0 || ^11.0
- pestphp/pest: ^3.5 || ^4.0
README
Laravel/PHP consumer SDK for Cbox ID — the package a product installs to
authenticate its users against a running Cbox ID instance (the opposite end from
cboxdk/laravel-id, which is the identity platform).
It speaks standard OpenID Connect, so integrating is a login redirect and a callback —
not a rewrite — with PKCE, CSRF state, a nonce, and full id_token signature/issuer/
audience verification handled for you. It adds the two conveniences a hosted-identity
product needs: a redirect to the instance's hosted profile-management page, and
back-channel helpers (machine tokens, userinfo, introspection, revocation, webhook
verification).
Part of Cbox ID — the self-hostable, Laravel-native identity platform. MIT licensed.
Install
composer require cboxdk/laravel-id-client php artisan vendor:publish --tag=cbox-id-client-config
Requires PHP ^8.4 and Laravel 12 or 13.
Configure the instance and your OAuth client (registered on the Cbox ID instance):
CBOX_ID_ISSUER=https://id.acme.com CBOX_ID_CLIENT_ID=client_... CBOX_ID_CLIENT_SECRET=secret_... CBOX_ID_REDIRECT=https://app.acme.com/auth/callback
Every endpoint (authorize, token, userinfo, jwks) is discovered from the issuer, so that's usually all you configure.
Log a user in
use Cbox\Id\Client\Facades\CboxId; // routes/web.php Route::get('/auth/redirect', fn () => CboxId::redirect()); // → Cbox ID login Route::get('/auth/callback', function (\Illuminate\Http\Request $request) { $cbox = CboxId::authenticate($request); // verifies state, PKCE, id_token $user = User::updateOrCreate( ['cbox_id' => $cbox->id], // the stable `sub` ['email' => $cbox->email, 'name' => $cbox->name], ); auth()->login($user); return redirect('/dashboard'); });
authenticate() returns a CboxUser — id (subject), email, name,
organizationId, the full verified claims, and the accessToken / refreshToken.
It throws InvalidState on a forged/stale callback and AuthenticationFailed
otherwise.
Send users to hosted profile management
Let users manage their own password, MFA, passkeys and sessions on the instance's hosted account page, then come back to your app:
Route::get('/account', fn () => CboxId::redirectToProfile(returnTo: route('dashboard'))); // or just the URL: CboxId::profileUrl(route('dashboard'))
Call Cbox ID APIs
$token = CboxId::machineToken(['api.read']); // client-credentials (M2M) $claims = CboxId::userinfo($accessToken); // OIDC userinfo $active = CboxId::introspect($token)['active']; // RFC 7662 CboxId::revoke($refreshToken, 'refresh_token'); // RFC 7009
Revoking a refresh token drops the whole token family — that's what "sign out everywhere" needs.
Verify a webhook / action
$ok = CboxId::verifyWebhook( payload: $request->getContent(), // the RAW body signatureHeader: $request->header('X-Cbox-Signature'), secret: config('services.cbox.webhook_secret'), ); abort_unless($ok, 400);
Receive provisioning webhooks (outbound provisioning)
Instead of standing up a SCIM server, register a hook and let the SDK verify and
route Cbox ID's signed events. Set CBOX_ID_WEBHOOK_SECRET, then in a service
provider's boot():
use Cbox\Id\Client\Facades\CboxIdWebhooks; CboxIdWebhooks::on('organization.member_added', fn ($e) => Seat::allocate($e->string('user_id'))); CboxIdWebhooks::on('organization.member_removed', fn ($e) => Seat::release($e->string('user_id'))); CboxIdWebhooks::on('role.assigned', fn ($e) => /* … */); CboxIdWebhooks::on('*', fn ($e) => Log::info('cbox event', ['type' => $e->type]));
The SDK mounts a signed receiver at POST /cbox-id/webhooks (configurable). Register
that URL as a webhook endpoint on your Cbox ID instance (Developers → Webhooks),
subscribe it to the event types you handle, and copy its signing secret into
CBOX_ID_WEBHOOK_SECRET. Signature verification (HMAC-SHA256, replay-bounded) and JSON
parsing are handled for you; a bad or stale signature is rejected before anything runs.
The receiver is slim. It verifies, acknowledges immediately, and runs your handlers
on a queued job (ProcessCboxIdWebhook) — so a slow handler never stalls the response
or trips the dispatcher's timeout/retry. Point CBOX_ID_WEBHOOK_QUEUE_CONNECTION /
CBOX_ID_WEBHOOK_QUEUE at a real async queue in production (with QUEUE_CONNECTION=sync
the job runs inline). Each event's deliveryId is stable, so dedupe retries with it.
License
MIT © Cbox.