Agent Trust Profile¶
Level: Advanced preview extension
Simple explanation¶
Agent Trust applies SD-JWT selective disclosure to the problem of AI agent authorization.
What you will learn¶
- Why API keys and broad OAuth scopes are insufficient for AI agents
- How capability tokens encode per-action, per-resource permissions
- How delegation chains let one agent authorize another
- The relationship between Agent Trust Profile and Agent Trust Kits
Before Agent Trust: An AI agent calls a tool with a broad API key. The tool cannot distinguish what the agent is allowed to do, who authorized it, or whether the request is legitimate.
After Agent Trust: The agent presents a scoped capability token (an SD-JWT) that says exactly what it can do, who delegated the permission, and when it expires. The tool verifies the token before executing.
How it compares¶
| Approach | Scope control | Delegation chain | Selective disclosure | Audit trail |
|---|---|---|---|---|
| API key | None | None | None | Minimal |
| OAuth token | Broad scopes | Limited | None | Standard |
| mTLS | Identity only | None | None | Transport |
| Agent Trust | Per-action | Multi-hop | Per-claim | Structured receipts, if stored durably |
| Status | Preview |
| Scope | Project-defined profile for scoped SD-JWT capability tokens, policy enforcement, delegation, and audit |
| Packages | SdJwt.Net.AgentTrust.Core, SdJwt.Net.AgentTrust.Policy, SdJwt.Net.AgentTrust.AspNetCore, SdJwt.Net.AgentTrust.Mcp, SdJwt.Net.AgentTrust.A2A, SdJwt.Net.AgentTrust.OpenTelemetry, SdJwt.Net.AgentTrust.Maf, SdJwt.Net.AgentTrust.Policy.Opa |
| Foundation | SD-JWT per RFC 9901, selective disclosure, key binding, nonce freshness, and policy-constrained delegation |
Problem Statement¶
AI agents and automation services increasingly call tools, APIs, and other agents on behalf of users or workflows. Traditional service accounts and broad API keys are difficult to constrain per action, hard to audit, and risky when an agent is compromised or misdirected.
Agent Trust is a preview .NET extension that explores how SD-JWT, key binding, policy, and selective disclosure can support scoped agent delegation and MCP/API tool governance. It complements existing OAuth, mTLS, API gateway, and MCP authorization patterns; it does not replace them.
When to use Agent Trust¶
| Scenario | Use Agent Trust? | Why |
|---|---|---|
| AI agent calls tools on behalf of a user | Yes | Scope the agent's authority to specific tools and actions |
| Agent delegates a subtask to another agent | Yes | Delegation chain captures who authorized what |
| MCP server needs per-tool authorization | Yes | Capability tokens replace broad API keys |
| Human user logs into a web app | No | Use standard OAuth 2.0 / OIDC |
| Service-to-service call with fixed scope | Maybe | OAuth client credentials may suffice; Agent Trust adds per-action scoping |
| Public API with no agent involvement | No | Standard API key or OAuth is sufficient |
OAuth and Agent Trust: complements, not competitors¶
Agent Trust does not replace OAuth. It layers on top of it:
| Layer | What it does | Standard |
|---|---|---|
| Authentication | Proves the agent's identity | OAuth 2.0 / OIDC / mTLS |
| Authorization (coarse) | Grants the agent a set of scopes | OAuth 2.0 scopes |
| Authorization (fine) | Scopes the agent to one tool, one action, one resource, one lifetime | Agent Trust capability token |
| Delegation | Captures the chain of who authorized who | Agent Trust delegation chain |
| Audit | Structured receipts and telemetry | Agent Trust receipts + OpenTelemetry |
A typical deployment uses OAuth to authenticate the agent, then Agent Trust to constrain what the authenticated agent can do at the individual tool-call level.
Threat Model¶
| Threat | Control |
|---|---|
| Prompt injection triggers a tool call | Policy is evaluated before a capability token is minted |
| Over-broad service account access | Tokens are scoped to one tool, action, resource, audience, and lifetime |
| Replay of a captured token | jti, nonce storage, short expiry, and optional sender constraints |
| Token misuse for different request | Request binding (req_bind) ties the token to a specific HTTP method/URI/body |
| Confused-deputy calls | aud binding and server-side capability validation |
| Unbounded agent delegation | Delegation depth, attenuation validation, and inherited capability constraints |
| Privilege escalation via delegation | AttenuationValidator enforces child capabilities are equal or narrower |
| Tool poisoning / schema rug-pull | Tool registry with signed manifests and catalog freshness validation |
| Weak auditability | Structured, partitioned receipts and OpenTelemetry correlation |
| Unauthorized high-risk actions | Human-in-the-loop approval evidence (approval claim) for privileged operations |
Token Model¶
An Agent Trust capability token is an SD-JWT minted for a specific action. The token is short-lived and contains only the claims needed by the target tool or agent. The canonical token type is agent-cap+sd-jwt.
| Claim | Type | Purpose |
|---|---|---|
iss |
Standard | Agent, service, or workload identity minting the capability |
aud |
Standard | Tool, API, MCP server, or downstream agent expected to verify it |
iat |
Standard | Issued-at timestamp |
exp |
Standard | Short expiry, usually seconds to minutes |
jti |
Standard | Unique token identifier for replay prevention |
cnf |
Standard | Optional proof-of-possession binding for DPoP, mTLS, or similar keys |
cap |
Profile | Capability object with tool, toolId, action, resource, limits |
ctx |
Profile | Correlation metadata: correlationId, workflowId, stepId, tenantId, dataClassification |
req_bind |
Profile | Request binding: HTTP method, URI, body hash (ties token to a specific request) |
del |
Profile | Delegation evidence: parentTokenId, rootIssuer, depth, maxDepth |
approval |
Profile | Human-in-the-loop approval evidence: approver, timestamp, mechanism |
pol_bind |
Profile | Policy decision binding: policyId, policyVersion, policyHash |
Capability Claims¶
The cap claim carries the machine-enforceable authority:
{
"tool": "member.lookup",
"toolId": "tool-registry://member-lookup-v2",
"action": "read",
"resource": "member/12345",
"limits": {
"maxResults": 10,
"maxPayloadBytes": 32768
},
"delegationDepth": 0
}
The ctx claim carries correlation and classification metadata:
{
"correlationId": "abc123",
"workflowId": "wf-claims-process",
"stepId": "step-3-lookup",
"tenantId": "tenant-contoso",
"dataClassification": "confidential"
}
Receivers must verify the token before trusting any claim. Application code remains responsible for enforcing resource-specific limits that cannot be enforced by cryptography alone.
Key Binding and Proof-of-Possession¶
Capability tokens may include sender constraints through cnf claims. Deployments can bind tokens to:
- DPoP proof keys (single or dual binding)
- mTLS client certificates
- SD-JWT key binding
- workload identity keys
- gateway-managed proof material
flowchart LR
Token[Capability Token] --> CNF[cnf claim]
CNF --> DPoP[DPoP Proof]
CNF --> MTLS[mTLS Certificate]
CNF --> KB[SD-JWT Key Binding]
DPoP --> Verify[Verifier checks\nkey possession]
MTLS --> Verify
KB --> Verify
Sender constraints are recommended for privileged actions and cross-boundary tool calls. The IDpopProofValidator and IMtlsSenderConstraintValidator interfaces provide extensible PoP validation.
Nonce And Replay Protection¶
Receivers should reject reused jti values within the token lifetime plus configured clock skew. Multi-instance deployments need a distributed nonce store, not the in-memory development implementation.
Default posture:
- Short token lifetimes
- Fail closed for privileged actions
- Distributed replay storage in production-like pilots
- Clock skew kept small and explicit
Delegation Constraints¶
Agent-to-agent delegation must preserve or narrow authority. A delegated capability must not exceed the original token's action, resource, audience, lifetime, or delegation depth.
The AttenuationValidator enforces the following narrowing rules at each delegation hop:
flowchart TD
Parent[Parent Capability] --> Check1{Lifetime <= parent?}
Check1 -->|Yes| Check2{Tool matches?}
Check1 -->|No| Reject[Reject: lifetime exceeded]
Check2 -->|Yes| Check3{Action narrowed?}
Check2 -->|No| Reject2[Reject: tool mismatch]
Check3 -->|Yes| Check4{Resource narrowed?}
Check3 -->|No| Reject3[Reject: action escalation]
Check4 -->|Yes| Check5{Depth < maxDepth?}
Check4 -->|No| Reject4[Reject: resource escalation]
Check5 -->|Yes| Check6{rootIssuer consistent?}
Check5 -->|No| Reject5[Reject: depth exceeded]
Check6 -->|Yes| Accept[Accept delegation]
Check6 -->|No| Reject6[Reject: root issuer mismatch]
Required constraints:
- Maximum delegation depth enforced by
maxDepth - No privilege expansion across hops (attenuation validation)
- Explicit allowed downstream audiences
- Correlation ID propagation across chain
rootIssuermust remain consistent through the chain- Receipt emitted at each hop
MCP Usage¶
SdJwt.Net.AgentTrust.Mcp treats MCP as one adapter target. The profile does not assume MCP is the only agent transport or authorization model.
For MCP tool calls:
- The client interceptor evaluates policy before the call.
- A capability token is minted for the requested tool/action.
- The token is attached using the deployment's chosen metadata or HTTP header convention.
- The server guard verifies signature, audience, expiry, replay status, and capability claims.
- The tool enforces application-level constraints and emits an audit receipt.
ASP.NET Core API Usage¶
SdJwt.Net.AgentTrust.AspNetCore provides inbound middleware and authorization helpers for APIs that receive capability tokens. APIs should still use normal transport security, authentication boundaries, and resource authorization. Agent Trust adds per-action capability proof and audit context.
OpenTelemetry Audit Model¶
Agent Trust receipts should include:
- Token ID (
jti) - Issuer and audience
- Tool and action
- Decision (
Permit,Deny,Indeterminate) - Reason code
- Correlation ID
- Policy ID, version, and hash (
pol_bind) - Evaluation duration
- Receipt partition key (tenantId, date, issuer)
- Obligations (post-decision actions the caller must fulfill)
Receipts should avoid raw sensitive payloads. Use hashes, references, or selective disclosure when the receiver does not need full context.
Metrics (per spec Section 24.1)¶
The AgentTrustMetrics class exposes spec-aligned counters and histograms:
| Metric name | Type |
|---|---|
agent_trust.capability.minted |
Counter |
agent_trust.capability.verified |
Counter |
agent_trust.capability.rejected |
Counter |
agent_trust.policy.evaluated |
Counter |
agent_trust.replay.detected |
Counter |
agent_trust.pop.failed |
Counter |
agent_trust.request_binding.failed |
Counter |
agent_trust.receipt.written |
Counter |
agent_trust.mint.duration_ms |
Histogram |
agent_trust.verify.duration_ms |
Histogram |
agent_trust.policy.evaluation_duration_ms |
Histogram |
Security Modes¶
Agent Trust supports three security modes via AgentTrustSecurityMode:
| Mode | Token type | Algorithm requirements | Use case |
|---|---|---|---|
Demo |
agent-cap+sd-jwt+demo |
HS256 symmetric allowed | Local development/testing |
Pilot |
agent-cap+sd-jwt |
HAIP asymmetric only | Controlled pilots |
Production |
agent-cap+sd-jwt |
HAIP asymmetric + PoP | Production deployments |
Security Considerations¶
- Agent Trust is a preview project profile, not a completed external standard.
- Do not treat capability tokens as a substitute for TLS, OAuth resource-server protections, or API authorization.
- Keep signing keys in KMS/HSM-backed custody for serious pilots.
- Use constant-time comparisons for sensitive token material.
- Reject weak algorithms and follow the repository HAIP algorithm policy (ES256/384/512, PS256/384/512).
- Use request binding (
req_bind) to prevent token reuse across different requests. - Use attenuation validation for all delegation chains to prevent privilege escalation.
- Validate the deployment threat model before using these packages beyond evaluation or pilot environments.
Standards Relationship¶
| Area | Status |
|---|---|
| SD-JWT | RFC 9901 stable base format |
| SD-JWT VC | IETF draft, tracked separately from Agent Trust |
| Delegate SD-JWT | Individual Internet-Draft; useful input, not a normative dependency |
| MCP authorization | External protocol authorization guidance; Agent Trust can complement it as an adapter |
| Agent Trust | Project-defined preview profile implemented by SdJwt.Net.AgentTrust.* packages |