Device-Bound Tokens (DPoP) API
Self-service management of the device keys bound to a user's session. ButtrBase supports sender-constrained (DPoP-style) access tokens per RFC 9449: a token may carry a confirmation claim binding it to a specific device key. These endpoints let an authenticated end user list and revoke their own device keys.
> No private key material is ever returned or stored — only public thumbprints.
Endpoints
GET /api/app/devices
List the caller's active (non-revoked) device keys, scoped to the verified token's user.Auth: access token (Authorization: Bearer <access JWT>).
Output: ~~~json { "data": [ { "device_uuid": "…", "jkt": "oKIywvGUpTVTyxMQ3bwIIeQUudfr_CkLMjCE19ECD-U", "label": "MacBook Pro", "created_at": "2026-06-14T12:00:00Z", "last_seen_at": "2026-06-14T13:00:00Z" } ] } ~~~
POST /api/app/devices/:device_uuid/revoke
Soft-revoke a device the caller owns.Auth: access token. Ownership is enforced.
Output: ~~~json { "data": { "device_uuid": "…", "revoked": true } } ~~~
A device that does not exist, is already revoked, or belongs to another user
returns 404 device not found (no existence oracle for other users' devices).
Binding model
jktis the device key's RFC 7638 JWK thumbprint: a base64url (no-pad)
SHA-256 over the canonical JSON of the key's required members (EC, OKP, or
RSA).
- A sender-constrained access token carries the optional RFC 9449
"cnf": { "jkt": "<thumbprint>" }. The
claim is additive and off by default — verifiers that don't understand
cnf ignore it, so it does not change existing token accept/reject behavior.