A runnable, self-contained demo of agentauth: an AI/LLM agent gets capability-scoped access to an HTTP API, approved by a human via the existing oauth2 RFC 8628 device-authorization flow, then calls a capability with a short-lived, replay-protected JWT.

The integration story, end to end

  1. The agent presents its own existing credential to the app’s wrapper around oauth2.DeviceAuthorizationService.Begin, along with the capabilities it wants. The app records that in agentauth.PendingRequestStore, indexed by both user_code and the agent’s principal ID.
  2. The human “visits” the verification page and approves — via the app’s own custom approve handler, not oauth2.DeviceApproveHandler (which would bind the grant to the human’s identity instead of the agent’s). The custom handler resolves the agent’s principal ID via PendingRequestStore.GetByUserCode and calls svc.Authorize with that identity.
  3. The agent polls the device-token endpoint once and gets a capability JWT via agentauth.NewAccessTokenIssuer.
  4. The agent calls POST /capability/execute with that JWT.
  5. After the token expires — the device flow’s Poll is single-use, so there’s no “poll again” — the app calls agentauth.RefreshCapabilityToken directly (simulating its own authenticated internal channel) to mint a second token off the same still-Active grant, and the agent calls execute again with no second approval.

Full source

Trying it out

Production note

This demo uses MemoryGrantStore, MemoryReplayStore, and MemoryPendingRequestStore — all process-local. A production deployment needs a single instance or sticky routing until a shared (e.g. SQL-backed) store exists, and should verify asymmetric tokens against a published JWKS rather than holding a signing key, same as the resource server example.