YogaSec · IAM for AI agents
A financial-grade profile for agentic transactions
When an AI agent asks a bank to move money, who can prove what the human actually saw before saying yes?
In short
- Agents now buy, transfer and pay invoices. The weak link is the human approval. Most flows today prove that a server logged what it meant to show, or that a key signed a value nobody could read.
- Banks already know a stronger pattern. EU payment law requires the authentication code to be specific to the amount and the payee that the payer was made aware of.
- Every building block exists, either as a standard or as a draft. What is missing is a profile that fixes the seams between them: who issues the challenge, what gets hashed, who renders it, and who verifies it.
- I sketch that profile here, with a logical architecture and a sequence diagram. It is my proposal for discussion, not a standard.
01Agents are already at the till
In barely a year, card networks, wallets and identity standards bodies have all published something about agents that pay. A few dated milestones show the pace.
- Sep 2025Google announces the Agent Payments Protocol (AP2) with signed "mandates" that record what the user approved.16
- Oct 2025Visa launches its Trusted Agent Protocol so merchants can recognise trusted shopping agents.17 The OpenID Foundation publishes its whitepaper on identity management for agentic AI.12
- Mar 2026Mastercard open-sources Verifiable Intent, co-developed with Google, to link "identity, intent, and action into a single, privacy-preserving record".15
- May 2026Google and Mastercard contribute AP2 and Verifiable Intent to the FIDO Alliance.20
- Jun 2026An IETF draft lets an API answer an agent with a signed, transaction-specific authorization challenge.7
- Jul to Sep 2026IDPro publishes "Assembly Required" and the agent identity framework behind it is adopted by the IETF WIMSE working group as AIMS.1110
- Sep to Oct 2026New drafts tackle the consent screen itself: a hash-pinned display document (R3) and passkey-signed permission receipts.89
Behind these announcements sit three different situations. They do not need the same proof.
The shopping agent you are watching
The agent fills a basket and you confirm the final cart on your phone. In AP2 this produces a Cart Mandate that your device signs. Verifiable Intent calls it the human-present mode.1615
Must prove: the exact cart and amount you confirmed.
The agent with a budget
"Pay my utility bills, up to 300 € a month." You sign the rules once, then the agent acts alone. AP2 calls this an Intent Mandate.16
Must prove: the limits you signed, and that each payment stayed inside them.
The agent that hits a wall
An accounts payable agent processes an invoice. The supplier's IBAN changed since last month, maybe through a forged PDF or an injected prompt. The bank API refuses and asks for a specific approval.
Must prove: that the approver saw the new beneficiary and the amount, on a channel the agent cannot reach.
Scenario C is the focus here. It is the one bank APIs face directly, and the least specified. Scenarios A and B are mostly card commerce, where AP2 and Verifiable Intent already carry signed records. When an agent calls a bank's own API, though, nothing equivalent is standardised yet.
02Three levels of proof for "the human approved"
A human approval can leave three kinds of evidence. They are not equal, and the difference is easy to miss.
The server says what it showed
The authorization server records which screen or document was displayed. The R3 draft does this well. The resource publishes a display document with a plain-language summary and its implications. The authorization server "MUST reject" a token if the document's hash does not match, and records r3_uri and r3_s256 in its audit log (§8.1).8
This is strong audit evidence, but it comes from the server itself. Nothing signed by the user confirms that this content reached their screen.
The user's key signed something
The permission receipts draft asks a passkey to sign a challenge equal to the SHA-256 hash of the permission (§4.7). The author states the limit plainly: "An approval shows that the passkey approved the action, not that the principal read it" (§6).9
Here is why. A WebAuthn authenticator signs a challenge it cannot interpret. The text on screen is drawn by an app or a web page, and that software can show one thing while the key signs another.
The device signed what it displayed
The component that renders the transaction is also the one that signs it, and the signed data contains the displayed fields. Two standards already work this way.
In W3C Secure Payment Confirmation, the user agent "MUST ensure" that the payee, amount and instrument are communicated to the user (§4.10.1). The payment data then goes into the client data that the authenticator signs.6 In OpenID4VP 1.0, a verifier sends typed transaction_data. The wallet returns a hash of each entry inside its signed presentation. For SD-JWT VC credentials, the SD-JWT VC appendix places these hashes in the key binding JWT.5
The law requires dynamic linking. It does not prescribe a protocol, and it does not require the user's device to sign the rendered text. Level 3 is the technically achievable reading that produces the cleanest evidence for it. For banks outside the EU, such as in Morocco, the RTS is not binding. It is still a precise and testable yardstick for what "the human approved" should mean.
03The building blocks already on the table
Nothing in this design needs a new protocol. Here is what exists, what each piece proves, and where it stops.
| Building block | Status | What it provides | Where it stops |
|---|---|---|---|
| Rich Authorization Requests (RFC 9396)1 | Standard | Structured authorization_details describing the operation. "When gathering user consent, the AS MUST present the merged set of requirements" (§3.1). The AS MUST refuse unknown types (§5). |
Presentation is left to deployments (§11.2). The AS may enrich the details during consent (§7.1). No signature by the user. |
| FAPI 2.0 Security Profile3 with PAR (RFC 9126)2 | Standard | PAR is mandatory, requests are authenticated, and access tokens are sender-constrained with mTLS or DPoP (§5.3.2). | RAR is only "recommended" (Note 5). No decoupled approval and no display proof. |
| CIBA Core 1.04 | Standard | Approval on a separate authentication device, outside the agent's screen. | binding_message is a short code to "interlock" two devices (§7.1), not a transaction description. The client must name the user with exactly one hint. |
OpenID4VP 1.0, transaction_data5 |
Standard | Typed transaction data. Wallets that do not support it "MUST reject requests that contain it", and the wallet must error on any unrecognized type (§5.1). The hash comes back signed in the presentation. | Each transaction type defines what gets displayed. Built for wallets and credentials, not yet wired to OAuth token issuance. |
| Secure Payment Confirmation6 | W3C CR | The browser displays payee, amount and instrument and signs them with a passkey. | Payment fields only. Runs in a browser, which may be on the same machine a computer-use agent controls. |
| Transaction authorization challenge7 | Draft -00 | The API returns a signed JWT (txn-authz-challenge+jwt) carrying txn and authorization_details. "The access token MUST contain the txn value". |
"The authorization server MUST obtain any required approval" but how it does so, and how it renders the request, is left open. |
| AuthZEN Access Request OAuth Profile19 | Draft 1 | Chains the transaction challenge, Deferred Token Response and CIBA in one OpenID profile. The client presents the resource-signed challenge to the transaction_authorization_endpoint and polls it. |
No OpenID4VP and no signature by the user's device over the displayed transaction. A CIBA binding_message conveys the operation to the user. |
| AAuth R38 | Draft -00 | A resource-published, hash-pinned display document, logged at token issuance. | Exploratory individual draft. Evidence stays at the server (level 1). |
| Permission receipts9 | Draft -00 | Passkey-signed permissions and receipts that anyone can verify offline later. | Level 2 by the author's own statement. Checked after the fact, not before execution. |
| AP2 and Verifiable Intent1615 | Industry spec | Signed mandates for human-present and delegated purchases. | Scoped to commerce and card rails, not to arbitrary bank APIs. |
| AIMS (WIMSE)10 | WG draft | Treats agents as workloads and maps existing specs into one model, without a new wire protocol.11 | An architecture, not a banking profile. |
04Why a profile, and not one more protocol
"We don't have a standards gap. We have an assembly gap."Jeff Lombardo, IDPro, 29 July 202611
That sentence describes the problem well. Each block above secures one link. The failures happen where blocks meet. A profile is the document that fixes those joins with MUST and MUST NOT, the way FAPI 2.0 turned general OAuth options into a financial-grade baseline.
Part of this assembly has already started. The AuthZEN Access Request OAuth Profile, at Draft 1, connects the transaction challenge with CIBA and Deferred Token Response.19 What it leaves out is the user's device signing what it displayed, and the API checking that signature. Four seams matter most.
Seam 1 · The challenge comes from the bank, never from the agent
If the agent builds the thing the human approves, a prompt-injected agent can build a convincing lie. In the transaction challenge draft, the API itself signs the challenge, including the operation and a transaction identifier txn. The agent only relays it, and the final token must carry the same txn.7 The agent never writes a byte the human signs.
Seam 2 · Hash what was granted, not what was asked
A natural idea is to hash the agent's request and have the user sign that hash. RFC 9396 breaks it. Deployments may "modify requested authorization details in the user consent process, e.g., adding fields" (§11.2), and the token response can return enriched details (§7.1).1 For example, the approver picks which account to debit on the consent screen. A hash of the original request no longer matches what will run.
So the object the user signs must be built after enrichment, and the token must carry the very same granted details. OpenID4VP also avoids a classic trap here. The hash is computed over the encoded transaction_data string as transmitted, so nobody has to re-serialise JSON identically to check it.5
Seam 3 · Render on a device the agent cannot drive
CIBA moves the approval to a separate device. But its binding_message is designed as "a visual cue" to link two screens, and "SHOULD be relatively short" (§7.1).4 It cannot describe a transfer, even though the AuthZEN profile notes that a binding_message can convey the operation to the user.19 Channel choice is also left to products. Auth0's asynchronous authorization, for instance, offers Guardian push and an email option where "the email contains a link" and approval "happen[s] in the browser".18
A browser or computer-use agent working in the user's own session may be able to open that inbox or that browser. That is my inference, not a documented incident. For challenged operations, the profile should allow one channel only: the bank's wallet app on a separate device, rendering typed transaction_data before it signs.
Seam 4 · Let the API check the human proof itself
Today the API trusts the authorization server's token, and the token is the only proof that someone approved. If the token also carries the user's signed presentation, the API can recompute the hash and compare it with the operation it is about to execute. A misconfigured authorization server, or a policy bug, can no longer turn a refusal into an approval without the API noticing. It also gives every party evidence they can verify independently.
05Logical architecture
Three trust zones, plus an evidence log. The agent zone is treated as compromised by design. The bank control plane issues and verifies. Only the approval zone talks to the human.
06Sequence: from refusal to verified execution
The walkthrough below uses scenario C. The accounts payable agent tries to pay 18,450 € to a beneficiary whose IBAN is new. The colours show which specification each message comes from.
What the wallet signs, and what the API checks
The authorization server builds one transaction_data entry after consent enrichment. The wallet decodes it, displays it, and returns its hash inside the key binding JWT that its hardware key signs. Here is the decoded entry for the invoice in scenario C:
{
"type": "https://bank.example/tx/credit-transfer/v1",
"credential_ids": ["bank_wallet_key"],
"txn": "c41f9e2a-6d0b-4b8e-9a51-2f7c0d13e8aa",
"authorization_details": [{
"type": "https://bank.example/tx/credit-transfer/v1",
"instructedAmount": { "currency": "EUR", "amount": "18450.00" },
"creditorName": "Atlas Logistique SARL",
"creditorAccount": { "iban": "FR76 3000 4000 0500 0012 3456 789" },
"debtorAccount": { "id": "acc-ops-02" },
"beneficiaryStatus": "new"
}]
}
Before executing, the bank API runs checks like these (pseudo-code). None of them trusts the agent, and only the first trusts the authorization server.
# token was issued by the AS and is bound to the agent's DPoP key
verify_token(token, dpop_proof, request)
td = token.approval.transaction_data # exact base64url string sent to the wallet
kb = token.approval.key_binding_jwt # signed by the wallet's hardware key
verify_signature(kb, wallet_key_from(bank_issued_credential))
assert kb.nonce == nonce_for(token.txn)
assert b64url(sha256(td)) in kb.transaction_data_hashes
data = json(b64url_decode(td))
assert data.txn == token.txn and not spent(token.txn)
assert data.authorization_details == token.authorization_details
assert request_operation(request) within data.authorization_details
execute(request)
mark_spent(token.txn)
log_evidence(token.txn, td, kb, token.jti)
The fourth line does the real work. The API recomputes the hash of the exact string the wallet received and finds it inside a signature only the user's device could produce. If anything changes the amount or the payee afterwards, the comparison fails. That is dynamic linking, checked end to end by the party that executes.
07A profile sketch in eleven rules
- New High-risk bank operations MUST be expressed as RFC 9396
authorization_detailswith a registered, versioned type.Tightens FAPI 2.0 Note 5, where RAR is only recommended. - Existing A challenged operation MUST start with a challenge signed by the resource server. The agent MUST NOT construct any data that the user signs.Transaction challenge draft, §3. The second sentence makes its intent explicit.
- Existing The authorization server MUST verify the challenge signature and determine the approver from policy, not from a hint supplied by the client.Transaction challenge draft, step 6, against CIBA's client-supplied hint.
- New The approval object MUST be built from the granted details after consent enrichment and MUST include
txn.Answers RFC 9396 §7.1 and §11.2. - New Exactly one
transaction_dataentry MUST be sent per challenge, hashed with SHA-256 only.Avoids the hash-matching ambiguity raised in OpenID4VP issue #442.21 - New Approval MUST happen on a device separate from the agent runtime, in the bank's app, with a hardware-bound key and user verification. Email links and same-device redirects MUST NOT be used for challenged operations.Extends CIBA's decoupled model.
- New The wallet MUST display every field of the type before signing and MUST NOT offer approval from a notification banner. It MUST also reject unknown types, which OpenID4VP already requires.OpenID4VP §5.1 for unknown types. Display rules are new.
- New Strings that come from outside the bank, such as creditor names or remittance text, MUST be shown as plain data, without markup or bidirectional control characters.Profile rule. RFC 9396 §2.1 already warns about ambiguous type values.
- New The access token MUST carry
txn, the granted details and the user's proof, and MUST be sender-constrained to the agent's key.The txn binding comes from the transaction challenge draft and sender constraint from FAPI 2.0 §5.3.2.1. Carrying the user's proof is new. - New The resource server MUST verify the user's proof itself and MUST treat
txnas single use.Profile rule implementing RTS Article 5(1)(d) end to end. - New Below a risk threshold, a pre-signed mandate with limits SHOULD replace per-action approval, so the human is asked rarely and only for what matters.Same logic as AP2 Intent Mandates and Verifiable Intent's autonomous mode.
08What this does not solve
- Signing is not reading. Level 3 proves what was displayed, not what was understood. For high-risk AI systems, the EU AI Act asks that overseers "remain aware of the possible tendency of automatically relying or over-relying" on system output (Article 14(4)(b)).14 If approvals become frequent, people will tap through them. Rule 11 matters as much as the cryptography.
- A compromised phone. A hardware key protects the key, not the screen. Malware with screen overlay rights on the phone can still mislead the user. App attestation narrows this risk without removing it.
- Who defines the display. Each transaction type needs a reviewed rendering. A published, hash-pinned display document in the style of R3 is a good candidate for this, as long as the wallet signs over it and the server does not just log it.
- Reach and cost. It only works where the approver has the bank's app. Corporate dual control means several approvers and several proofs per
txn. - Moving ground. The transaction challenge and R3 are -00 drafts, and the AuthZEN profile is at Draft 1. All of them will change. As of 22 October 2026, I found no FAPI or OpenID Foundation profile that adds a signature by the user's device over the displayed transaction, verified by the API. If one appears, this sketch should be compared with it.
09Where this belongs
The natural home is the OpenID Foundation's FAPI work, which already maintains FAPI 2.0 and a CIBA profile for financial services. The transaction challenge lives in the IETF OAuth community, and the AuthZEN profile already chains it with CIBA. Three concrete contributions seem more useful than a new draft. The first is a comment on the transaction challenge draft, asking how approval evidence can reach the resource server. The second is a comment on R3, asking for an option where the user's device signs the display and does not just log it. The third is proposing to the AuthZEN profile an approval option based on OpenID4VP transaction data.
If you work on these drafts, run agent payments at a bank, or see where this sketch breaks, I would like to hear it. YogaSec is a personal project shared with the community, and this post is open to correction.
Update, 25 October 2026. Sections 01 and 07 use the mandate names AP2 had when it launched in September 2025: Cart Mandate and Intent Mandate. The current AP2 specification defines a Checkout Mandate (what is bought) and a Payment Mandate (how it is paid).2220 Each starts Open, holding the user's constraints, and becomes Closed when bound to a final cart and amount. In case A the user closes it, in case B the agent does, within the limits the user signed. The argument is unchanged.
Sources
- IETF, RFC 9396, OAuth 2.0 Rich Authorization Requests, May 2023. §2.1, §3.1, §5, §7.1, §11.2.
- IETF, RFC 9126, OAuth 2.0 Pushed Authorization Requests, September 2021.
- OpenID Foundation, FAPI 2.0 Security Profile, Final, 22 February 2025. §5.3.2.
- OpenID Foundation, OpenID Connect CIBA Core 1.0. §7.1.
- OpenID Foundation, OpenID for Verifiable Presentations 1.0, Final, 9 July 2025. §5, §5.1, §8.4.
- W3C, Secure Payment Confirmation, Candidate Recommendation Draft, 13 October 2026. §1.1.1, §4.10.1.
- Rosomakho, Campbell, McGuinness, Kasselman, draft-rosomakho-oauth-txn-challenge-00, OAuth Transaction Authorization Challenge, June 2026.
- Hardt, draft-hardt-aauth-r3-00, AAuth Rich Resource Requests, 28 September 2026. §8.1.
- Izmaylov, draft-izmaylov-agent-permission-receipts-00, October 2026. §4.7, §6.
- IETF WIMSE WG, draft-ietf-wimse-aims, AI Identity Management System, September 2026.
- Jeff Lombardo, Assembly Required: How we Stopped Reinventing and Started Composing Standards for Agentic Identity, IDPro, 29 July 2026.
- OpenID Foundation, Identity Management for Agentic AI, arXiv:2510.25819, October 2025.
- European Commission, Delegated Regulation (EU) 2018/389, RTS on strong customer authentication, Article 5.
- European Union, Regulation (EU) 2024/1689, Artificial Intelligence Act, Article 14.
- Mastercard, Verifiable Intent, 5 March 2026.
- SiliconANGLE, Google's Agent Payments Protocol provides framework for AI to automate consumer purchases, 16 September 2025. Mandate types described in Vellum, Google's AP2.
- FStech, Visa launches protocol for agentic commerce, 15 October 2025.
- Auth0, Asynchronous Authorization, product documentation, consulted 22 October 2026.
- OpenID AuthZEN WG, Karl McGuinness, AuthZEN Access Request OAuth Profile, Draft 1, consulted 22 October 2026.
- FIDO Alliance, Building the trust layer for agentic payments with AP2 and Verifiable Intent, 26 May 2026.
- OpenID DCP WG, OpenID4VP issue #442, matching transaction_data_hashes to transaction_data entries.
- Google, Agent Payments Protocol (AP2) specification, Checkout Mandate and Payment Mandate, consulted 25 October 2026.