Where Authsignal fits
In SPC the ACS is the WebAuthn relying party (RP). It owns credential enrollment (the issuer domain), stores the public key, issues the challenge, and cryptographically verifies the assertion. This is the reverse of non-SPC FIDO, where the merchant is the RP and the ACS only consumes the attestation as a risk signal it does not verify. Authsignal provides that relying party. It slots in wherever your ACS makes an authentication decision, and never touches the PAN or the 3DS message rails.The transaction is set server-side (when you
track the action) and validated server-side by
Authsignal. The cardholder’s browser only renders what the server issued, and nothing
client-supplied is trusted for the amount or payee.Prerequisites
- EMV 3DS 2.3.1, which defines the SPC data elements. The ACS advertises SPC support for a card
range with
acsInfoInd=07. - A platform authenticator registered with the WebAuthn
paymentextension: Touch ID, Windows Hello, or a Google Password Manager passkey on Android. Authsignal marks a credential payment-capable only when the browser returns a successfulpaymentextension result at registration. - Browser support: SPC runs on Chromium browsers (Chrome on macOS, Windows, and Android).
Feature-detect with
PaymentRequest.securePaymentConfirmationAvailability()and fall back on Safari and Firefox. - A
Permissions-Policyofpayment=*, publickey-credentials-get=*on whichever page runs the ceremony (the ACS challenge iframe, or the merchant page).
The two SPC flows
EMV 3DS defines two ways to run SPC. Authsignal’s role, and its API calls, are identical in both; only where the browser ceremony runs and how the data travels in the 3DS messages differ.- ACS-initiated (recommended)
- Requestor-initiated
The ACS decides a challenge is needed and runs the SPC ceremony inside its own challenge
iframe (
CReq/CRes). No merchant changes are required, so it lights up passkeys for every
merchant that already integrates 3DS.AReq:threeDSRequestorSpcSupportis omitted (setting it triggers the requestor flow).ARes:transStatus=CwithauthenticationMethod=14(SPC).- The ACS renders the
PaymentRequest, verifies the assertion, and completes the challenge withCRes.
Enrollment
Enroll one payment passkey per user, per device. It works across all of the cardholder’s cards: the specific card is a per-transaction value (see step 1), not bound to the credential. This matches the SPC model, where the relying party supplies the instrument at authentication time and the issuer keeps the card-to-credential mapping. Enrollment is owned by the ACS and typically offered as an uplift in a prior authenticated session (for example right after a successful OTP step-up). Authsignal forces a platform authenticator with required user verification and thepayment extension, and marks the credential payment-capable.
1
Generate an enrollment token (server SDK)
token to the browser.2
Create the passkey (browser SDK)
paymentInstrument: { displayName } is optional: it sets a default label for the single-card
case. Multi-card issuers omit it and set the card per transaction instead.signUp without the flag to enroll a
standard passkey, or fall back to another method.
Authenticating a payment
The ACS uses three Authsignal calls per transaction: set the transaction, fetch the SPC request data, and verify the assertion. In the ACS-initiated flow the ACS makes all three server-side and runs the ceremony in its iframe; in the requestor-initiated flow the SPC request data is handed to the merchant inARes and the assertion comes back in the second AReq.
Client REST calls use the Client API base https://api.authsignal.com/v1/client with
Authorization: Bearer <token> (regional bases available: au., eu., ca.). The <token> is the
action token returned by track.
1. Set the transaction (server SDK)
Set the amount, payee, and the card for this transaction on the action’scustom data. These values
are the source of truth Authsignal validates the signed assertion against, and the client never
supplies them.
token to the client calls that follow.
2. Fetch the SPC request data (client REST)
Request authentication options withsecurePaymentConfirmation: true. The response carries the
rpId, challenge, the payment-capable credentialIds, and the server-set payment. The ACS uses
this to run the ceremony in its iframe, or delivers it to the merchant in ARes.
payment.instrumentDisplayName is the card for this transaction (from track). Use it as the
instrument in the ceremony. paymentInstruments (a credential-level label) is still returned for
the single-card default, but the per-transaction value takes precedence.
3. Run the SPC ceremony (browser)
The page that runs the ceremony (the ACS challenge iframe, or the merchant page) builds aPaymentRequest from the request data and shows the native “Confirm your purchase” dialog. The
amount and payee come from the server-set payment.
The native Secure Payment Confirmation dialog. The browser renders the payee, instrument and amount, and binds them into the signed assertion.
clientDataJSON (type: "payment.get") binds the amount, currency and payee.
4. Verify the assertion (client REST)
The ACS verifies the assertion against the transaction set attrack. Authsignal checks the WebAuthn
signature and that the signed payment matches the server-set amount, currency and payee, so a
tampered client can’t bind a valid signature to a different transaction.
401.
5. Confirm the result (server SDK)
EMV 3DS field mapping
How the Authsignal steps sit in each flow. Authsignal’s calls are the same; the 3DS message carriage differs.
Field names follow the EMV 3DS 2.3.1 specification. Confirm the exact carriage of the SPC request
data and assertion against your 3DS Server and scheme profile.
Feature detection and fallback
SPC only runs on Chromium browsers (Chrome on macOS, Windows, and Android). On Safari and Firefox the ACS must fall back, and must never dead-end the cardholder. Detect support before attempting the ceremony:First-party alternative (browser SDK)
For a merchant-initiated, first-party web flow (not split across 3DS messages), the@authsignal/browser SDK wraps the client calls in steps 2 to 4 into
one method:
track), and there is no payment
argument. For a split 3DS ceremony, the SDK also exposes runPaymentConfirmation({ rpId, challenge, credentialIds, payment }), which runs only the browser ceremony against request data you already
hold.
Authsignal never stores or sees the card number; the instrument is a display label and icon only.

