//Device-Bound Tokens (DPoP) API

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

  • jkt is 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
confirmation claim "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.