Approve agent actions with CIBA
Approve agent actions with CIBA
CIBA ships the protocol; the notification and approval surface are yours. Here is how to wire them.
1. The agent initiates (no host code)
The agent calls the backchannel endpoint directly:
POST /oauth/backchannel_authentication
Authorization: Basic <client_id:client_secret>
Content-Type: application/x-www-form-urlencoded
scope=openid&[email protected]&binding_message=Approve%20deployment%20to%20prod
{ "auth_req_id": "auth_req_…", "expires_in": 300, "interval": 5 }
2. Notify the user on the emitted event
The OP emits oauth.backchannel_authentication_requested when the request is
created. Domain events are delivered through the outbox as an EventDelivered
Laravel event (see architecture); listen for it
and notify the user's authentication device. The payload carries the internal
request id (your approval handle) — never the client's auth_req_id:
use Cbox\Id\Kernel\Events\EventDelivered;
use Illuminate\Support\Facades\Event;
Event::listen(EventDelivered::class, function (EventDelivered $delivered): void {
if ($delivered->event->type !== 'oauth.backchannel_authentication_requested') {
return;
}
$payload = $delivered->event->payload;
// Show $payload['binding_message'] to the user, and keep $payload['request_id']
// as the handle to approve/deny.
Notification::route(/* the user's device */)->notify(
new ApproveAgentRequest($payload['request_id'], $payload['binding_message']),
);
});
3. Record the user's decision
When the user taps approve or deny on their device, call the contract with the internal request id:
use Cbox\Id\OAuthServer\Contracts\BackchannelAuthentication;
app(BackchannelAuthentication::class)->approve($requestId, $organizationId);
// or
app(BackchannelAuthentication::class)->deny($requestId);
4. The agent polls and gets its token
The agent polls /oauth/token with grant_type=urn:openid:params:grant-type:ciba
and the auth_req_id, receiving authorization_pending until approval, then an
access_token and id_token bound to the approving user.
Show the binding_message verbatim on the approval screen so the user knows exactly
what they are authorizing. See Security: CIBA.