PasskeyBridge

Security · 2026-06-12

Just-in-Time Capability Tokens for Agents: Persistent OAuth Scopes as Standing Privilege

By J. W. Bouckaert

Just-in-Time Capability Tokens for Agents: Persistent OAuth Scopes as Standing Privilege

Standing privilege, repackaged

For two decades, every mature security program has waged the same war against standing privilege. Always-on database admin rights, persistent SSH keys, never-rotated service accounts—the entire just-in-time access industry exists because long-lived broad authority is the single most reliable predictor of catastrophic breach. The CISA Zero Trust Maturity Model v2.0 is explicit: by the Advanced tier, access decisions must be evaluated continuously, not granted at the start of a session and assumed valid forever.

Then the same industry handed AI agents OAuth refresh tokens with twelve-month lifetimes and the union of every scope the agent might ever need.

That is standing privilege. The wrapper changed. The pathology did not.

The agent identity space spent 2024 and 2025 arguing about whether agents should have identities at all. We answered that question in Agentic Identity: Scoped Digital Delegates for AI Agents and again in Delegating Identity to AI Agents Without Delegating Trust. The next question—the one most production deployments are getting wrong right now—is how an agent's identity authorizes a specific action. Persistent OAuth scopes are the wrong primitive. Just-in-time capability tokens are the right one.

JIT capability, defined

A capability token is neither a session token, nor a refresh token, nor an OAuth access token with a shorter TTL. The distinction matters because the failure modes are different.

A capability token, in the sense Mark Miller's capability security work formalized and the object-capability community has refined since, is an unforgeable, transferable, single-purpose grant of authority to perform a specific operation on a specific resource. It does not say "this principal is allowed to do X-class operations on Y-class resources." It says "the bearer of this token may execute exactly this operation, on exactly this resource, exactly once, before exactly this timestamp."

OAuth 2.0 scopes are the opposite. They are role grants—coarse, durable, ambient. When an agent presents an OAuth access token with payments:write scope, the resource server has no way to know whether the agent is paying the invoice the human approved or draining the operating account. The token has nothing to say about that distinction because OAuth 2.0 was not designed to encode it.

OAuth 2.1 tightens some of the worst defaults—mandatory PKCE, removal of the implicit flow, sender-constrained tokens. It does not change the underlying authorization primitive. A scope is still a role grant. RFC 9449 (DPoP) binds tokens to client-side keys so that exfiltrated tokens cannot be replayed by a different client, which is necessary but not sufficient. DPoP binds the token to a client. It does not bind the token to an action.

The 2026 threat model

Three threats reshape the agent authorization problem in ways that persistent OAuth scopes structurally cannot address.

Model substitution. An attacker who can get a different model—or a fine-tuned variant of the same model—behind the same agent identity can use every scope that identity holds. The OAuth token cannot tell that the model behind it has changed. We covered the detection side in Behavioral Fingerprinting of AI Agents: Detecting Model Substitution; the authorization side is that the token's authority must be bound to a freshly-attested model fingerprint at the moment of redemption rather than issuance.

Prompt injection cascading into authorized action. A compromised input does not need to escape the agent's sandbox to cause damage. If the agent already holds payments:write for the next thirty days, the injection only needs to convince the agent to issue one unauthorized transfer. Persistent scopes mean the injection's blast radius equals the scope's blast radius. JIT capabilities cap the blast radius at one redeemable action.

Agent attestation fatigue. We catalogued this failure mode in Agent Attestation Fatigue: When Constant Trust Checks Become a Vulnerability. The naïve answer to over-broad scopes is to re-check trust on every call. That works until the attestation system becomes the slow path everyone optimizes around, at which point the checks degrade into rubber-stamps. JIT capabilities solve this by encoding the trust decision into the token itself—the redemption is fast because the policy evaluation already happened at issuance, and the token's narrow scope means there is nothing to rubber-stamp.

The OWASP NHI top 10

The OWASP Non-Human Identities Top 10 (2025) names the failure modes that persistent agent scopes produce directly. NHI:01 (Improper Offboarding), NHI:02 (Secret Leakage), NHI:03 (Vulnerable Third-Party NHI), and NHI:04 (Insecure Authentication) all share a single architectural prerequisite: the NHI must hold long-lived broadly-scoped authority for the failure to matter at scale. Remove the standing privilege and most of the Top 10 degrade from "catastrophic" to "annoying."

The JIT capability model

PasskeyBridge's NF-05 capability protocol, which sits beneath the digital delegate trust engine, treats every agent action as a discrete authorization event. The flow has four steps and they are non-negotiable.

StepWhat happensWhat the agent presentsWhat the policy engine checks
1. Intent declarationAgent declares the operation it intends to performOperation URI, resource URI, requested freshness windowWhether the agent's delegate has latent authority for this operation class
2. Capability mintPolicy engine issues a one-shot tokenBehavioral trust score, attested model fingerprint, freshness of upstream signals
3. RedemptionResource server validates and consumesCapability token, DPoP proof, attestation evidenceToken signature, single-use nonce, model fingerprint match, freshness bound
4. AuditAppend-only log records the full chain

Three properties of the token are load-bearing.

Single-use. The token carries a nonce that the resource server records before executing the action. A second presentation of the same nonce returns 401 token_replayed. The resource server is the authority on whether a token has been redeemed; the issuer is not—this keeps the issuer off the request path and makes the model survive issuer outages.

Freshness-bounded. The token includes a max_age for every upstream signal that the issuer relied on—carrier signal, device attestation, human-presence assertion. The resource server re-validates these freshness bounds at redemption. A token issued when the SIM-bound carrier signal was 30 seconds old will not redeem if it is presented two hours later, even if the token's nominal expiry is still in the future. We argued this point at length in Carrier Signal Freshness: Why TTL Matters More Than Strength. The same logic applies to model attestations.

Bound to an attested model fingerprint. The token's audience claim is not just "agent X." It is "the model whose attestation fingerprint hashes to F at issuance time, running on behalf of agent X." If the model behind agent X changes between issuance and redemption, the fingerprint will not match and the token will not redeem. This closes the model-substitution loop in a way scopes cannot.

Macaroons as the wire format

The capability security community spent ten years on the wire format. The state of the art is Macaroons—a token format that supports attenuation, where a holder can derive a strictly less-privileged token from a more-privileged one without contacting the issuer. This is exactly the primitive multi-agent workflows need: a procurement agent delegates a narrowed capability to a payment-execution sub-agent, which in turn delegates a further-narrowed capability to a settlement adapter. No issuer round-trip. No central choke point. Cryptographically enforced monotonic narrowing.

Macaroons in their original form are not quite right for 2026 agent traffic because they do not natively encode model attestation or carrier signal freshness. The fix is mechanical: extend the caveat language with first-class predicates for model_fingerprint, carrier_signal_max_age, and presence_attestation_id, and treat those predicates as third-party caveats discharged by the attestation issuer at redemption time. This is the direction the GNAP working group is heading with grant negotiation, although GNAP has not yet absorbed the agent-attestation primitives that the threat model now demands.

Latency budget

The most common objection is that JIT minting must be too slow for production agent traffic. The arithmetic says otherwise. A reasonable per-phase budget for an edge-deployed JIT capability mint, building on the same edge-first stack we benchmarked at 17.9 ms p50 for a single /health round-trip on the PasskeyBridge API Playground, looks like this:

Phasep50 budgetp95 budget
Intent declaration to issuer~5 ms~10 ms
Policy evaluation (cached trust score + cached attestation)~5 ms~12 ms
Capability mint + dual-sign (ES256 + ML-DSA-65)~8 ms~15 ms
Token return to agent~5 ms~10 ms
Redemption validation at resource server~5 ms~10 ms
End-to-end overhead per action~28 ms~57 ms

These are budget targets derived from the per-component latencies the platform already meets at the edge, short of a full end-to-end benchmark of a production JIT issuer (which has not yet been instrumented as a single composite trace). The signing cost dominates the budget and is the line item most worth re-measuring against your own hardware; ML-DSA-65 is fast in WASM but not free.

For comparison, a single frontier-model inference call at typical agent-payload sizes commonly takes hundreds of milliseconds to several seconds. Even at the upper bound of this JIT budget, the overhead is a single-digit percentage of the inference path the agent is already paying. At that ratio the overhead is rounding error, and nowhere near the bottleneck.

The architectural choices that keep the budget realistic are the same ones we use across the platform: edge-first verification (Edge-First Identity Verification: Bringing CDN-Layer Trust to Carrier Signals), cached trust scores with sub-second invalidation, and hybrid classical-plus-PQC signing rather than serial signing. None of this is exotic. It is engineering discipline applied to a problem most teams have not yet recognized as a latency problem at all.

A migration path

Every team running agents in production today already has persistent OAuth scopes wired up. Telling them to delete the scopes and start over is a non-starter. The migration that works in practice has three phases.

Phase 1: Shadow-mint. Keep the existing OAuth scopes. Mint JIT capability tokens alongside every authorized call. Log the redemption decisions. Do not enforce. This produces the evidence that the JIT decisions match the OAuth decisions in 99.something percent of cases, and surfaces the cases where they diverge for human review.

Phase 2: Selective enforcement. Identify the smallest set of high-blast-radius operations—funds movement, IAM mutation, PII export, code deploy—and switch those to JIT-only. Leave everything else on OAuth scopes. This is where the security win is concentrated, and the operational risk is bounded by the scope of operations you cut over.

Phase 3: Default deny. Flip the default so that OAuth scopes alone authorize nothing destructive, and every action either presents a JIT capability or fails closed. At this point the OAuth token is reduced to its honest role: a delegation envelope that says "this agent acts on behalf of this human, under this contract"—not a license to act.

Most teams stall in Phase 1 because they did not budget for the audit-log volume. Plan for it. Append-only audit storage at ~1 KB per redemption, at 10,000 redemptions per agent per day, at 1,000 agents, is 10 GB per day uncompressed. Compressed, indexed, and retained for the SOC 2 and SEC Reg S-ID windows that actually apply to your workload, it is a manageable line item—but it is a line item.

Standards

The standards bodies are not asleep on this. The IETF OAuth 2.1 draft and the GNAP charter both move in the JIT direction, although neither absorbs model attestation yet. The NIST AI Risk Management Framework explicitly calls out continuous authorization for autonomous systems. The EU AI Act's high-risk provisions require human-in-the-loop controls that map cleanly onto the intent-declaration step of a JIT capability flow. None of these specs prescribe the wire format yet. That gap is where vendors will ship for the next twenty-four months. Pick the ones whose token format encodes attestation, freshness, and single-use as first-class fields—not as best-effort extensions—or pay the migration cost again in 2028.

Summary

Persistent OAuth scopes for AI agents are the always-on database admin rights of 2026. The threat model has moved. The primitive has not. JIT capability tokens—single-use, narrowly-scoped, freshness-bounded, bound to an attested model fingerprint—are the architecturally correct answer, and the latency cost is rounding error against the agent's own inference budget. The migration is gradual but the destination is not negotiable. Standing privilege lost its argument a long time ago. Agents do not get an exemption.

Get started free → or explore the platform.

Start free · Test the API