From

Ideem

— device-bound passkeys and A2A payment authentication for banks, fintechs, and payment platforms.

Passkeys
9 min read

Step-Up Authentication with Passkeys: Transaction-Bound Signing for High-Value Payments

Session-level passkey auth proves a user logged in but not that they approved a specific wire. Transaction-bound signing closes that gap by deriving the WebAuthn challenge from the actual payee and amount so the signature is cryptographically tethered to the transaction itself — and it's exactly what PSD2/PSD3 dynamic linking requires.
Written by
Tim Massey
Published on
June 11, 2026

TL;DR

  • Session-level passkey authentication is not enough for a wire transfer. The signature only proves the user logged in — not that the user approved this payee for this amount.
  • Transaction-bound signing fixes that by deriving the WebAuthn challenge from the actual transaction details, so the resulting signature is cryptographically tied to the payee, amount, and account.
  • This is the same property PSD2's Article 5 calls "dynamic linking," which regulators across the EU, UK, and Gulf are codifying for high-value payments. PSD3 keeps it and tightens it.
  • For first-party bank flows — wires, treasury, beneficiary changes — the cleaner 2026 pattern is a WebAuthn assertion with a transaction-derived challenge issued from the bank's own origin. The W3C's Secure Payment Confirmation (SPC) is the dedicated API for cross-origin merchant-initiated payments.
  • The FBI's IC3 attributed $3.0 billion in 2025 losses to business email compromise, with 86% of dollar losses routed through wire or ACH. Transaction-bound signing is one of the few controls that cuts that path.
  • Ideem Passkeys+ binds each high-value transaction to a fresh passkey signature derived from the transaction itself — not the session — so the audit record proves what the customer approved, not just that they were logged in.

A wire transfer is one of the few moments in modern banking where everything that can go wrong does go wrong at once. The user is rushed, the destination is unfamiliar, the amount is large, the settlement is fast and irreversible. And the authentication that gates the transfer, in most banks, is exactly the same authentication that gated the user reading their checking balance ten minutes earlier.

That is the core engineering problem step-up authentication exists to solve, and it is the reason passkeys at session login — while a meaningful improvement over passwords and SMS one-time passwords — do not finish the job. A passkey assertion at login proves the user authenticated. It does not prove the user looked at the wire screen, saw a $250,000 transfer to an account they have never paid before, and consented to that specific transaction. The mechanic that closes the gap is transaction-bound signing: binding a fresh WebAuthn signature to the actual transaction details so the cryptographic record proves what the customer approved, not just that they were logged in.

What "transaction-bound" actually means in WebAuthn

A standard WebAuthn assertion is generated when the relying party calls navigator.credentials.get() with a server-issued challenge. The authenticator signs over the concatenation of authenticatorData and the SHA-256 hash of clientDataJSON, which contains the challenge, the origin, and the operation type. The server validates the signature and checks the challenge against the one it issued.

The freedom in that design — and the reason it can carry transaction binding — is the challenge. The W3C specification says the challenge must be a cryptographically random buffer of at least 16 bytes, and that is the only constraint. Nothing prevents the relying party from deriving the challenge deterministically from transaction details: a 32-byte value computed as the SHA-256 hash of the canonical JSON of {payeeAccount, amount, currency, valueDate, nonce}. The authenticator does not know or care what the bytes mean; it signs them either way. The bank can then prove on the server side that the signature in hand corresponds to exactly that payee and amount.

Encode the transaction into the challenge, retain the original input on the server, and the WebAuthn assertion becomes a non-repudiable record of consent to the specific payment. Modify the amount or the payee after the fact, and the signature stops verifying. Replay the signature against a different transaction, and the challenge will not match. Yubico's developer guidance lays out this pattern explicitly for document signing, and the same construction works for payments because the constraints are identical.

Why session-level passkey auth is not enough

The temptation in a passkey rollout is to declare victory at sign-in. The user authenticated with a phishing-resistant factor; the threat model is closed. For low-value interactions that framing is defensible. For payments it is not.

The reason is the difference between authenticating a user and authorizing an action. A session cookie says "this browser was, at login time, in possession of a credential held by the user." It says nothing about what the user has seen, considered, and consented to since. If an attacker compromises the browser session through malware, a malicious extension, or a remote-control attack — or if the user is being socially engineered in real time by a voice-cloned "executive" demanding a wire — the session-level passkey proves nothing about the wire itself.

Transaction-bound signing forces a fresh user-verification gesture against a challenge derived from the transaction on the screen. The cost is one extra biometric tap. The benefit is that the bank holds a cryptographic artifact it can show to a court, an examiner, or an APP-fraud reimbursement panel that says, in effect, "this signature could not exist unless the customer approved this exact payment on their enrolled device."

What the regulators are actually asking for

The European framework gives this property a specific legal name: dynamic linking. PSD2's Regulatory Technical Standards on Strong Customer Authentication, in Article 5, require that for remote electronic payment transactions the authentication code be dynamically linked to the amount and the payee, that any change to either invalidates the code, and that the payer is made aware of both. PSD3 and the accompanying Payment Services Regulation, which reached provisional political agreement in November 2025 and is moving toward 2026–2027 implementation, retain dynamic linking and direct the EBA to issue refined technical standards on how it must be evidenced.

Outside the EU, the same idea is showing up under different names. FFIEC's authentication guidance has long contemplated transaction-level controls for high-risk activity. SAMA, the UAE Central Bank, QCB, and the Reserve Bank of India have moved toward authorization patterns that look like dynamic linking in everything but name. Banks building once for the EU and exporting the same control framework to other regulated markets are taking the right architectural bet.

Where Secure Payment Confirmation fits — and where it doesn't yet

The W3C Web Payments Working Group has been developing Secure Payment Confirmation (SPC) as a dedicated browser API for payment authentication. SPC layers on top of WebAuthn and adds two features that matter for merchant-side payments: a browser-rendered confirmation dialog that shows the amount and payee in trusted UI the relying party cannot style, and cross-origin authentication so a merchant page can invoke a credential registered with the customer's bank or card issuer. As of the Working Group's February 2026 minutes, SPC is published as a W3C Candidate Recommendation and is gathering implementation experience.

For first-party bank payment flows — the wire screen on the bank's own origin, the beneficiary-add flow, the treasury approval — SPC's cross-origin features are not what's needed. A standard WebAuthn assertion with a transaction-derived challenge, issued from the bank's own origin, is simpler to deploy, works in every modern browser today, and produces an equivalent dynamic-linking guarantee on the server side. For merchant-initiated cross-origin payments, SPC is the right primitive to invest in — but as Corbado's analysis earlier this year noted, browser support is still effectively Chromium-only, so production banks are running it in pilots. The practical posture in 2026: build first-party transaction-bound signing now, and let SPC mature into the cross-origin merchant story as the second browser engines catch up.

The engineering checklist

What a working implementation looks like, end to end.

  • The bank's payment-initiation service computes a canonical representation of the transaction — payee identifier, amount, currency, value date, internal nonce — and hashes it to produce the 32-byte challenge. Store the canonical input and the hash together, keyed by a short-lived transaction ID.
  • The client invokes navigator.credentials.get() with that challenge, userVerification: "required", and an allowCredentials list scoped to the customer's enrolled passkey for the originating device. The on-screen UI shows the same payee and amount the bank just hashed.
  • On the assertion return, the server reconstructs clientDataHash, verifies the signature against the stored public key, confirms the challenge in clientDataJSON matches the hash on file for the transaction ID, confirms the origin, confirms userVerification was performed, and records the signature counter delta.
  • Treat any signature-counter regression as a cloned-authenticator signal and route the transaction to manual review. ImperialViolet's note on signature counters is the right reference for the edge cases — some platform authenticators return a constant zero, so the counter check has to be conditional on the authenticator class your bank actually accepts.
  • Persist the assertion, the canonical transaction input, the signature counter, the AAGUID, and the timestamp as the audit record. This is the artifact the bank will hand to compliance, to fraud, and — if it ever comes to it — to a regulator asking how the bank knows the customer approved the wire.

Nothing in that list is exotic. The WebAuthn primitives are already in the bank's stack if it has shipped a passkey program. What changes is the discipline of computing the challenge from the transaction rather than from a random buffer, and of treating each high-value action as its own authorization event.

What this means for product and risk teams

The visible artifact of all this engineering is one extra biometric prompt at the moment of confirming a wire or adding a beneficiary. The invisible artifact is that the bank's record of consent has gone from "the customer's session was authenticated" to "the customer's authenticator signed a hash of this payee and this amount." That claim survives the kinds of attacks — session hijack, real-time social engineering, voice-cloned authorization — that defeat session-level passkey auth.

For risk teams, the operational upside is a cleaner fraud-decisioning surface. Transactions carrying a valid transaction-bound assertion move through faster lanes with lower review thresholds; transactions lacking one become a much higher-signal exception. For product teams, the upside is a defensible answer to the question every payments product owner now gets asked: what does the bank do, structurally, to stop authorized push payment fraud and BEC-driven wire fraud? Transaction-bound signing is not a complete answer — the social-engineering layer still needs in-line intervention — but it is the cryptographic floor underneath every other control.

Where Ideem fits

Ideem's Passkeys+ binds each high-value transaction to a fresh passkey signature derived from the transaction itself. The platform handles challenge derivation, canonical input storage, assertion verification, signature-counter bookkeeping, and audit-record persistence — so the bank's payment-initiation service hands Passkeys+ a transaction object and gets back a verified, dynamically-linked authorization artifact. The same pipeline supports first-party WebAuthn flows on the bank's origin today and is built to extend into Secure Payment Confirmation as browser support broadens.

Passkeys+ runs alongside whatever identity provider the bank has already standardized on — Okta, ForgeRock, Ping, or a homegrown stack — so transaction-bound signing becomes an authentication-layer capability rather than something every payment service has to implement independently.

The forward-looking part of this story is short. PSD3 will codify dynamic linking more strictly, the EBA will publish refined RTS that supervisors will examine against, and other regulators outside Europe will continue to converge on the same property under different names. The banks that have already moved transaction approval from the session layer to the transaction layer will spend 2027 explaining the audit trail. The banks that have not will spend it rebuilding the payment flow under a deadline.

Sources

How exposed is your auth stack?

Most orgs running OTP-based MFA have 3–4 exploitable gaps they don’t know about. Our Authentication Assessment takes 2 minutes and shows you exactly where you stand — plus a phased migration roadmap.

Take the Assessment →

Built by Ideem

Device-bound passkeys and A2A payment authentication. One SDK. No OTPs, no redirects.

Weekly newsletter
No spam. Just the latest releases and tips, interesting articles, and exclusive interviews in your inbox every week.
Read about our privacy policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Think your MFA is solid? Let's find out.

Our 2-minute assessment scores your authentication setup and shows you exactly where the improvements are.

See Your Score →

See how your stack measures up →

Free Assessment →

Before you go —

Ideem replaces the authentication patterns described in this post. Two minutes to see where your stack stands.

8 questions. 2 minutes. Get a phased migration roadmap.

Take the 2-Min Assessment →No thanks, I’ll skip for now