3-D Secure (3DS) & the Access Control Server: The Complete Engineer’s Guide
Everything you need to understand about how online payments are authenticated ,from architecture to every single field value
Who is this for? Back end engineers, payment engineers, and fintech developers who need to deeply understand how 3DS 2.x works, what every message means, why it was designed that way, and what happens when a field changes value
What is 3-D Secure and Why Does It Exist?
When you pay for something in a physical store, the cashier can see your card, the terminal reads your chip, and you enter a PIN. The bank can be reasonably confident you are who you say you are. But when you type your card number into a website, none of that happens. Anyone who knows your 16-digit card number, expiry date, and CVV (Card Verification Value,3 digit number behind your card) can make a purchase. This is the Card Not Present (CNP) fraud problem.
3-D Secure (3DS) was invented to solve this. It adds an authentication layer between the cardholder and the payment, a way for the card-issuing bank (Issuer) to verify that the person making the online purchase is the actual cardholder, before the payment is authorized.
The original protocol (3DS 1.0 — Introduced by VISA) was clunky, it redirected cardholders to a separate bank webpage, showed a branded popup, and often just asked for a static password. Conversion rates plummeted. Customers abandoned checkout. Merchants hated it.
3DS 2.x, standardized by EMVCo in 2017 and now on version 2.3.1, is a fundamentally different protocol:
- It shares 10x more data about the transaction with the issuer
- It supports risk-based authentication, low-risk transactions go through invisibly (frictionless).
- It works natively in mobile apps via an embedded SDK
- It supports bio-metrics, push notifications, OTP, and out-of-band authentication (a security process that requires users to verify their identity through separate communication channels)
- It is the technical foundation for PSD2 Strong Customer Authentication (SCA) in Europe
The result is that today, a significant majority of 3DS 2.x transactions complete without the cardholder ever seeing a verification step. The bank silently checks device fingerprints, transaction history, and behavioral data in under 300ms, decides the transaction is genuine, and approves it, invisible to the shopper.
The Three Domains
The “3-D” in 3-D Secure refers to three domains , organizational and technical boundaries across which the protocol operates. Each domain owns specific components and responsibilities.
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ ACQUIRER DOMAIN │ │ INTEROPERABILITY │ │ ISSUER DOMAIN │
│ │ │ DOMAIN │ │ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ Merchant │ │ │ │ Directory │ │ │ │ ACS │ │
│ │ Website / │ │ │ │ Server │ │ │ │ (Access │ │
│ │ Mobile App │ │ │ │ (DS) │ │ │ │ Control │ │
│ └───────┬───────┘ │ │ │ Visa / MC / │ │ │ │ Server) │ │
│ │ │ │ │ Amex etc. │ │ │ └───────────────┘ │
│ ┌───────▼───────┐ │ │ └───────────────┘ │ │ │
│ │ 3DS Server │◄─┼────┼─────────────────────┼────┼► Issuing Bank │
│ │ (3DSS) │ │ │ │ │ │
│ └───────────────┘ │ │ │ │ │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘The Acquirer Domain
The merchant and its technical infrastructure live here. The merchant’s website or app initiates the authentication. The 3DS Server (3DSS),which can be built by the merchant, a PSP, or a payment gateway is the technical component that:
- Queries the Directory Server to find out which ACS handles a given card
- Runs the 3DS Method device fingerprinting step (collect ip address, device and related information)
- Constructs and sends the Authentication Request (AReq)
- Receives the authentication result and extracts the CAVV(Cardholder Authentication Verification Value) + ECI (Electronic Commerce Indicator) for use in the payment authorization.
Don’t worry if you don’t understand the CAVV, AREQ, ECI etc right now. We will discuss it in detail in next sections. Just Remember, These are issued by Issuer ACS and utilize by Acquirer Merchant.
For reference CAVV is cryptographic security token generated by a card issuer to verify that a cardholder has successfully authenticated during a 3-D Secure online (card-not-present) transaction.
ECI is a value returned by the ACS to the Merchant that indicates the outcome of a 3DS authentication attempt. For example ECI: 05 indicates successfull authentication
The Interoperability Domain
The Directory Server (DS) lives here, owned by the card scheme (Visa’s DS, Mastercard’s DS, etc.). The DS:
- Maintains a registry of all card ranges and which ACS handles each
- Routes AReq messages from the 3DS Server to the correct ACS
- Routes ARes messages back from the ACS to the 3DS Server
- Enforces protocol version negotiation
- Signs and validates messages through JWS (JSON Web Signature)
The Issuer Domain
The issuing bank and its Access Control Server (ACS) live here. The ACS is where the authentication decision is made. It:
- Receives the AReq from the DS
- Runs its Risk-Based Authentication (RBA) engine
- Either approves frictionlessly (DO not ask for proof of identity) or challenges the cardholder (ask for proof)
- Generates the CAVV cryptographic proof
- Returns the authentication result
3. The ACS
The Access Control Server is the most technically complex component in the 3DS ecosystem. It sits entirely inside the issuer’s infrastructure and is the system we will focus on most deeply.
What an ACS Actually Is
An ACS is not a single service. It is an integrated system of components:
┌──────────────────────────────────────────────────────────────────────────┐
│ ACS — INTERNAL ARCHITECTURE │
├──────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌──────────────────┐ ┌─────────────────────────┐ │
│ │ TLS/mTLS │ │ Message Parser │ │ Card Range & Enrolment │ │
│ │ Termination│──►│ & Validator │──►│ Database (PAN Lookup) │ │
│ │ (443) │ │ (JSON Schema) │ └─────────────────────────┘ │
│ └────────────┘ └────────┬─────────┘ │
│ │ │
│ ┌─────────────▼────────────────────┐ │
│ │ Risk-Based Auth (RBA) Engine │ │
│ │ · Transaction risk scoring │ │
│ │ · Device fingerprint match │ │
│ │ · Velocity checks │ │
│ │ · Behavioural fraud model │ │
│ └──────────┬───────────┬───────────┘ │
│ │ │ │
│ ┌─────────▼────┐ ┌───▼───────────┐ │
│ │ Frictionless │ │ Challenge │ │
│ │ Auth Path │ │ Flow Engine │ │
│ └──────────┬───┘ └──┬────────────┘ │
│ │ │ │
│ ┌──────────▼─────────▼──────────┐ │
│ │ CAVV Generator (HSM-backed) │ │
│ └─────────────────┬─────────────┘ │
│ │ │
│ ┌───────────────────┐ ┌───────▼────────────┐ ┌──────────────────┐ │
│ │ Notification URL │ │ ARes / RRes │ │ 3DS Method URL │ │
│ │ Handler (CRes) │ │ Builder & Signer │ │ (Fingerprinting)│ │
│ └───────────────────┘ └────────────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘ACS Security Requirements
- TLS 1.2 minimum (TLS 1.3 strongly recommended) on all endpoints
- Mutual TLS (mTLS) on the server-to-server channel between DS and ACS
- JSON Web Signature (JWS) on all server-to-server messages using RS256 or ES256
- HSM (Hardware Security Module, FIPS 140–2 Level 3+) for CAVV generation , never software-only
- EMVCo Letter of Approval (LOA) , formal certification required before production use
- PCI DSS Level 1, ACS handles PANs and must meet the highest compliance tier
Protocol Versions
The ACS has undergone significant evolution over time. It initially started with version 1.0, and the protocol has progressed through multiple updates to reach its current, more advanced versions. Each version introduced improvements in security, authentication methods, and user experience. The key differences between these versions are described below.
All Message Types
Here is every message in the 3DS protocol, what it carries, and what it means:
Message Correlation — How Messages Are Linked
Every message in a single 3DS transaction is linked by three UUIDs:
When debugging a transaction, these three IDs let you reconstruct the entire flow across all participant logs.
The Authentication Flows
These flows can either be App based or Browser Based. Details of these flows are given below
Browser Frictionless
deviceChannel = 01
The ideal path. The cardholder sees nothing, authentication happens silently in under a second. The ACS will send a response of ARes with transStatus=Y.
Merchant 3DS Server DS ACS
──────── ────────── ── ───
│ │ │ │
│── Checkout ────►│ │ │
│ │── PReq ─────►│ │
│ │◄─ PRes ──────│ │
│◄── 3DS Method ──│ │ │
│ iframe │ │ │
│ (hidden) │ │ │
│ Browser ──────────────────────────────────► │ Fingerprint stored
│ │ │ │
│ Notification ◄──────────────────────────────│
│ │── AReq ─────►│── AReq ──────►│
│ │ │ │ [RBA: LOW RISK]
│ │◄─ ARes(Y) ───│◄─ ARes(Y) ────│ CAVV generated
│◄── Auth OK ─────│ │ │
│ (with CAVV) │ │ │The 3DS Method is defined below but for an intuition it is a device fingerprinting step used before authentication to collect information about the cardholders browser or device. This helps the issuer’s Access Control Server perform risk-based authentication.
Browser Challenge
When the ACS’s risk engine determines more verification is needed. The cardholder is asked for an OTP, biometric, or other proof.
Merchant 3DS Server DS ACS
──────── ────────── ── ───
│ │ │ │
│── Checkout ────►│ │ │
│ │── PReq ─────►│ │
│ │◄─ PRes ──────│ │
│◄── 3DS Method ──│ │ │
│ iframe │ │ │
│ (hidden) │ │ │
│ Browser ──────────────────────────────────► │ Device fingerprint
│ │ │ │ stored
│ Notification ◄──────────────────────────────│
│ │ │ │
│ │── AReq ─────►│── AReq ──────►│
│ │ │ │
│ │ │ │ [RBA: HIGH RISK]
│ │◄─ ARes(C) ───│◄─ ARes(C) ────│ Challenge required
│◄─ Challenge URL │ │ │
│ + CReq data │ │ │
│ │ │ │
│ Browser ────────────────────────────────────► │
│ POST CReq (Base64)Challenge Window │
│ │ │ │
│ │ │ │ User Authentication
│ │ │ │ (OTP / App / Biometrics)
│ │ │ │
│ Browser ◄─────────────────────────────────────│
│ CRes (challenge result) │
│ │ │ │
│ │ │◄──────────────│
│ │◄─ RReq ──────│ Result Req │
│ │ │ │
│ │── RRes ─────►│ │
│ │ │ │
│◄── Auth Result ─│ │ │
│ (CAVV / ECI) │ │ │
│ │ │ │App-Based (SDK)
deviceChannel = 02
In native mobile apps, the 3DS SDK embedded in the merchant app handles device data collection and challenge rendering natively as no browser involved.
Merchant App 3DS SDK 3DS Server DS ACS
──────────── ─────── ────────── ── ───
│ │ │ │ │
1. │── Init SDK ───►│ │ │ │
│ (card data) │ │ │ │
│ │── AReq ─────────►│── AReq ────►│── AReq ─►│
│ │ sdkEncData(JWE) │ │ │ Decrypt JWE
│ │ sdkEphemPubKey │ │ │ Read device data
│ │ sdkTransID │ │ │
│ │◄─ ARes ──────────│◄─ ARes ─────│◄─ ARes ──│
│ │ (Y or C) │ │ │
│◄── Native UI ──│ │ │ │
│ (if challenge)│ │ │ │The key difference: In 3DS app flows, device data is transmitted in an encrypted JWE payload (sdkEncData). The SDK generates an ephemeral key pair and sends its ephemeral public key (sdkEphemPubKey) in the AReq. The ACS uses its private key together with the SDK’s ephemeral public key to perform ECDH key agreement, derive a shared session key, and decrypt the JWE payload to obtain the device fingerprint data.
Decoupled Authentication
The cardholder authenticates asynchronously , for example, via a push notification in their banking app, while the merchant’s checkout session is paused.
Merchant 3DS Server DS ACS
──────── ────────── ── ───
│ │ │ │
│── Checkout ────►│ │ │
│ │── PReq ─────►│ │
│ │◄─ PRes ──────│ │
│◄── 3DS Method ──│ │ │
│ iframe │ │ │
│ Browser ──────────────────────────────────► │ Device fingerprint
│ │ │ │ collected
│ Notification ◄──────────────────────────────│
│ │ │ │
│ │── AReq ─────►│── AReq ──────►│
│ │ │ │
│ │ │ │ [RBA evaluation]
│ │ │ │
│ │◄─ ARes(D) ───│◄─ ARes(D) ────│
│◄─ DecoupledAuth │ │ │
│ Indicator │ │ │
│ │ │ │
│ │ │ │ Send push notification
│ │ │ │ to cardholder banking app
│ │ │ │
│ │ │ │ Cardholder approves
│ │ │ │ authentication
│ │ │ │ (fingerprint, faceid etc)
│ │ │ │
│ │ │◄──────────────│
│ │◄─ RReq ──────│ Result Req │
│ │ │ │ (auth result + CAVV)
│ │── RRes ─────►│ │
│ │ │ │
│◄── Auth Result ─│ │ │
│ (CAVV / ECI) │ │ │
3DS Requestor Initiated (3RI)
No cardholder is present. Used for recurring billing, installments, or split shipments. The merchant (3DS Requestor) initiates authentication on behalf of a previously consenting cardholder.
deviceChannel=03- ACS cannot return
transStatus=C, there is no cardholder to challenge - ACS validates that the cardholder previously consented to this merchant
- Returns
Y(frictionless) orU(cannot authenticate) only
The 3DS Method
The 3DS Method is a silent device fingerprinting mechanism that runs before the AReq is sent. The merchant page loads a hidden iframe (200px × 100px, visibility: hidden) that POSTs to the ACS's 3DS Method URL. This allows the ACS to:
- Set a first-party cookie in its own domain, creating a browser session binding
- Collect browser characteristics user-agent, screen resolution, fonts, plugins, canvas fingerprint
- Record the IP address of the cardholders browser
- Store the fingerprint keyed by
threeDSServerTransIDfor correlation with the later AReq
Merchant Page Browser ACS Method URL
───────────── ─────── ──────────────
│ │ │
1. │── Render hidden iframe─►│ │
│ (size: 200×100px) │ │
│ │── POST to ACS ─────────►│
│ │ threeDSMethodData │
│ │ =Base64({ │
│ │ threeDSServerTransID,│
│ │ notifURL}) │
│ │ │ Stores fingerprint
│ │ │ Sets cookie
│ │◄── Auto-submit form ────│
│ │ POST to notifURL │
│◄── Notification ────────│ │
│ threeDSCompInd=Y │ │
│ │ │
2. │ Sets threeDSCompInd=Y in AReq │
│ ACS correlates fingerprint ↔ AReq by transID │threeDSCompInd — The Critical Output
Critical engineering rule: Never set
threeDSCompInd=Yunless yourthreeDSMethodNotifURLendpoint actually received the POST. Falsely claiming method completion gives the ACS incorrect confidence and can result in wrongly approved fraudulent transactions, voiding your liability shift protection
The AReq — Every Field Explained
The Authentication Request is the most data-rich message in the protocol. The ACS uses everything in this message to make its authentication decision. Here are the fields grouped by category:
Identity Fields
{
"messageType": "AReq",
"messageVersion": "2.2.0",
"threeDSServerTransID": "f38e6948-5338-4411-a51b-8b1d3b1d06e6",
"dsTransID": "97267598-fab6-1272-9817-be07cb82b9a4",
"acsTransID": "13a0ea67-2e7a-4bfc-be20-b3d6c7ca2d3c"
}Channel and Category Fields
{
"deviceChannel": "02",
"messageCategory": "01",
"threeDSCompInd": "Y"
}deviceChannel is one of the most important fields in the entire protocol. It determines which code path everything else follows:
messageCategory tells the ACS whether this is a real payment:
Card and Cardholder Fields
{
"acctNumber": "4111111111111111",
"cardExpiryDate": "2412",
"acctType": "02",
"cardholderName": "John Doe",
"email": "john.doe@example.com",
"mobilePhone": { "cc": "1", "subscriber": "8005551234" }
}Address Fields
{
"addrMatch": "Y",
"billAddrLine1": "123 Main St",
"billAddrCity": "San Francisco",
"billAddrState": "CA",
"billAddrPostCode": "94105",
"billAddrCountry": "840",
"shipAddrLine1": "123 Main St",
"shipAddrCity": "San Francisco",
"shipAddrState": "CA",
"shipAddrPostCode": "94105",
"shipAddrCountry": "840"
}addrMatch is a simple but powerful signal. Y means the billing and shipping addresses are the same , a strong indicator of a genuine cardholder transaction. N raises risk but is legitimate for gifts and work deliveries.
Browser Fingerprint Fields
These only apply when deviceChannel=02. They are collected by JavaScript on the merchant page:
{
"browserAcceptHeader": "text/html,application/xhtml+xml",
"browserColorDepth": "24",
"browserIP": "203.0.113.42",
"browserJavaEnabled": "false",
"browserJavascriptEnabled": "true",
"browserLanguage": "en-US",
"browserScreenHeight": "900",
"browserScreenWidth": "1440",
"browserTZ": "-300",
"browserUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
}Merchant Fields
{
"acquirerBIN": "411111",
"acquirerMerchantID": "MERCHANT_12345",
"mcc": "5411",
"merchantCountryCode": "840",
"merchantName": "ACME Online Store",
"threeDSRequestorID": "12345678901",
"threeDSRequestorName": "ACME Online Store",
"threeDSRequestorURL": "https://acme.example.com",
"notificationURL": "https://3dsserver.acme.com/3ds/notify"
}mcc (Merchant Category Code) is particularly important for the ACS's risk assessment. High-risk MCCs automatically increase the risk threshold and make frictionless approval less likely.
notificationURL is the URL where the ACS will POST the final CRes after a challenge is complete. If this URL is wrong or unreachable, the 3DS Server will never receive the challenge result , transactions will appear to hang indefinitely.
Transaction Fields
{
"purchaseAmount": "10000",
"purchaseCurrency": "840",
"purchaseExponent": "2",
"purchaseDate": "20240115143022",
"transType": "01"
}Account Information Object
The acctInfo object contains merchant-supplied signals about the cardholder's history at the merchant. These are among the most impactful fields for RBA:
{
"acctInfo": {
"chAccAgeInd": "05",
"chAccChangeInd": "04",
"suspiciousAccActivity": "01",
"nbPurchasesInLast6Months": "15",
"txnActivityDay": "2",
"txnActivityYear": "47"
}
}chAccAgeInd — How old is the account?
chAccChangeInd — When was the account last modified?
suspiciousAccActivity is the most powerful negative signal in the entire acctInfo object:
Velocity fields:
txnActivityDayis transactions in the last 24 hours. A spike (e.g.txnActivityDay=15whentxnActivityYear=10) is a strong fraud indicatortxnActivityYearis total transactions in the last year. High values indicate loyal customers
Merchant Risk Indicator Object
The merchantRiskIndicator lets the merchant share their own risk intelligence:
{
"merchantRiskIndicator": {
"shipIndicator": "01",
"deliveryTimeframe": "04",
"reorderItemsInd": "02",
"preOrderPurchaseInd": "01",
"giftCardCount": "00",
"giftCardAmount": null
}
}shipIndicator — Where is the order going?
deliveryTimeframe — How urgently?
Gift card fields deserve special attention. Gift cards are the number 1 fraud laundering mechanism. Fraudsters buy large numbers immediately using stolen cards. When giftCardCount is 3 or more combined with deliveryTimeframe=01, virtually every ACS will mandate a challenge or reject the transaction outright.
SDK-Specific Fields (deviceChannel=01 Only)
{
"sdkAppID": "3c1e90f8-ae11-4ebe-9a47-61a8a56c0ed5",
"sdkEphemPubKey": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." },
"sdkEncData": "eyJhbGciOiJFQ0RILUVTIiwi...",
"sdkMaxTimeout": "05",
"sdkReferenceNumber": "3DS_SDK_VENDOR_001",
"sdkTransID": "b2385523-a48c-4576-87b3-12abc123",
"deviceRenderOptions": {
"sdkInterface": "03",
"sdkUiType": ["01", "02", "03", "04"]
}
}sdkEphemPubKey is a JSON Web Key (JWK) containing the SDK's ephemeral ECDH public key. The ACS performs ECDH key agreement with its own private key to derive a symmetric session key, which it then uses to decrypt sdkEncData. To Learn more about Ephem Key. kindly refer to this article
Get Hammad Hassan’s stories in your inbox
Join Medium for free to get updates from this writer.
sdkEncData is a JSON Web Encryption (JWE) compact serialization containing the device fingerprint, browser characteristics equivalent, but for the mobile device. To understand JWE,you can look into this article
deviceRenderOptions tells the ACS what challenge UIs the SDK can render:
The ARes — Reading the Decision
The Authentication Response is the ACS’s verdict. It is the most consequential message in the entire flow because it determines whether the transaction proceeds, challenges, or dies.
transStatus — The Central Decision Field
The difference between N and R is critical and often misunderstood:
Nmeans authentication failed, the cardholder couldn't prove they are who they say. This might be a wrong OTP, or the ACS decided the risk was too high for frictionless and the cardholder failed the challenge.Rmeans the issuer explicitly rejected the transaction as suspected fraud. This is an active fraud signal, not just a failed verification. You should not retry, and you should flag this to your fraud system.
acsChallengeMandated
transStatusReason — Why It Failed
Present when transStatus is N, U, or R. Tells you the specific reason:
The Challenge Flow — CReq and CRes
Challenge Request (CReq)
The CReq is sent by the 3DS Server (as a browser form POST) to initiate a challenge. It is Base64URL-encoded and submitted as the creq form parameter.
Initial CReq — starts the challenge session:
{
"messageType": "CReq",
"messageVersion": "2.2.0",
"threeDSServerTransID": "f38e6948-5338-4411-a51b-8b1d3b1d06e6",
"acsTransID": "13a0ea67-2e7a-4bfc-be20-b3d6c7ca2d3c",
"challengeWindowSize": "05"
}challengeWindowSize tells the ACS how to size the challenge UI:
OTP submission CReq sent after cardholder enters the code:
{
"messageType": "CReq",
"messageVersion": "2.2.0",
"threeDSServerTransID": "f38e6948-5338-4411-a51b-8b1d3b1d06e6",
"acsTransID": "13a0ea67-2e7a-4bfc-be20-b3d6c7ca2d3c",
"challengeWindowSize": "05",
"challengeDataEntry": "847291"
}Cancellation CReq when cardholder clicks Cancel:
{
"messageType": "CReq",
"acsTransID": "13a0ea67-...",
"threeDSServerTransID": "f38e6948-...",
"challengeCancel": "01"
}challengeCancel values tell the ACS why the challenge is being terminated:
Challenge Response (CRes)
The CRes comes back from the ACS. It can be intermediate (challenge still in progress) or final (challenge complete).
Intermediate CRes — OTP entry UI:
{
"messageType": "CRes",
"messageVersion": "2.2.0",
"threeDSServerTransID": "f38e6948-...",
"acsTransID": "13a0ea67-...",
"challengeCompletionInd": "N",
"uiType": "01",
"challengeInfoHeader": "Secure Payment Verification",
"challengeInfoLabel": "One-Time Password",
"challengeInfoText": "Enter the 6-digit code sent to your mobile ending in 1234.",
"submitAuthenticationLabel": "Verify",
"resendInformationLabel": "Resend Code",
"whyInfoLabel": "Why is this needed?",
"whyInfoText": "This protects your card from unauthorised use.",
"issuerImage": {
"medium": "https://acs.bank.com/images/logo_med.png",
"high": "https://acs.bank.com/images/logo_high.png"
}
}challengeCompletionInd:
NChallenge still in progress. 3DS Server awaits another CReq (cardholder to submit data)YChallenge complete. ChecktransStatusfor outcome
uiType Challenge interface type:
OOB (uiType=04) is particularly interesting. The CRes will contain:
oobAppURLa deeplink to open the issuer's banking app (e.g.bankxyz://auth?token=abc)oobAppLabelbutton text: "Open BankXYZ App"oobContinueLabelbutton text after returning: "I have approved in the app"
The cardholder opens their banking app, sees the transaction details, authenticates with biometric or PIN, and taps Approve. Then they return to the browser and click “I have approved.” The 3DS Server sends a follow-up CReq, and the ACS checks if the banking app received the approval signal.
Final CRes — Challenge Passed:
{
"messageType": "CRes",
"challengeCompletionInd": "Y",
"transStatus": "Y"
}This is POSTed by the ACS to the notificationURL as a Base64URL-encoded form parameter named cres. The 3DS Server decodes it, reads transStatus=Y, and then waits for the RReq.
The Results Flow — RReq and RRes
After a challenge completes (or after a decoupled auth), the ACS sends the Results Request (RReq) to the DS, which forwards it to the 3DS Server. This message carries the final authentication outcome, CAVV, and ECI.
{
"messageType": "RReq",
"messageVersion": "2.2.0",
"threeDSServerTransID": "f38e6948-5338-4411-a51b-8b1d3b1d06e6",
"dsTransID": "97267598-fab6-1272-9817-be07cb82b9a4",
"acsTransID": "13a0ea67-2e7a-4bfc-be20-b3d6c7ca2d3c",
"messageCategory": "01",
"authenticationType": "02",
"authenticationValue": "jJ81HADVRtXfCBATAp7ME0cGZiQB",
"eci": "05",
"transStatus": "Y",
"interactionCounter": "01"
}The interactionCounter tells you how many CReq/CRes exchanges occurred"01" means the cardholder needed only one attempt.
The 3DS Server must acknowledge with RRes:
{
"messageType": "RRes",
"threeDSServerTransID": "f38e6948-...",
"dsTransID": "97267598-...",
"acsTransID": "13a0ea67-...",
"resultsStatus": "01",
"messageCategory": "01"
}resultsStatus: 01 = received and processed. The ACS needs this acknowledgment to close its transaction session cleanly.
How Field Values Change the Flow
Understanding which field value changes which code path is essential for both integration and debugging.
The Big Switch: deviceChannel
deviceChannel is the master switch of the entire protocol:
deviceChannel = 01 (App)
└─► ACS derives ECDH session key from sdkEphemPubKey
└─► ACS decrypts sdkEncData JWE with session key
└─► Challenge rendered in native SDK, not HTML
└─► CReq/CRes exchanged with encrypted SDK counters
└─► No browser fingerprint fields needed
deviceChannel = 02 (Browser)
└─► ACS reads all browser* fields directly
└─► Correlates threeDSCompInd with 3DS Method fingerprint
└─► Challenge rendered in HTML iframe via form POST
└─► Base64URL encoding on CReq/CRes
deviceChannel = 03 (3RI)
└─► No cardholder present - CANNOT return transStatus=C or D
└─► ACS validates prior consent (priorAuthenticationInfo)
└─► Returns Y/A/U/N only
└─► threeRIInd must explain why merchant is authenticatingthreeDSCompInd × Risk Score
The 3DS Method completion indicator acts as a multiplier on the base risk score:
The whiteListStatus Bypass
When whiteListStatus=Y in the ARes, it means the cardholder has added this merchant to their trusted list. The ACS can skip the challenge entirely and return transStatus=Y, regardless of what the base risk score would have been. This is the most powerful path to frictionless after account history.
A cardholder can add a merchant to their whitelist during a challenge. The ACS challenge UI shows a “Trust this merchant for future purchases” checkbox. When checked and the challenge passes, the ACS sets whiteListStatus=P (pending) in the RReq. Future transactions from that merchant return whiteListStatus=Y , frictionless every time.
acctInfo Signal Combinations
Individual acctInfo fields matter, but their combinations create the strongest signals:
Highest risk combination (almost certain challenge/reject):
{
"chAccAgeInd": "02",
"chAccChangeInd": "01",
"suspiciousAccActivity": "02",
"txnActivityDay": "12",
"txnActivityYear": "3"
}Translation: Account created this session, modified this session, merchant flagged it suspicious, 12 transactions today but only 3 all year. This is textbook account takeover.
Lowest risk combination (strong frictionless candidate):
{
"chAccAgeInd": "05",
"chAccChangeInd": "04",
"suspiciousAccActivity": "01",
"txnActivityDay": "2",
"txnActivityYear": "52"
}Translation: 60+ day old account, no recent changes, no suspicious activity, normal daily/annual velocity. Combined with threeDSCompInd=Y and addrMatch=Y, this is the ideal frictionless scenario.
Risk-Based Authentication
RBA is the intelligence engine inside the ACS. It takes every data point in the AReq and produces a risk score. Here is how a real RBA decision is made:
Step 1: Pre-RBA Checks
Card enrolled? ─── No ──► ARes transStatus=U
│
▼ Yes
Mandatory challenge policy? ─── Yes ──► ARes transStatus=C (skip RBA)
│
▼ No
Whitelist match? ─── Yes ──► ARes transStatus=Y (skip RBA)
│
▼ No
RBA EngineStep 2: Signal Collection and Weighting
Step 3: Decision
Score ≤ Low Threshold ──► transStatus=Y (Frictionless)
ACS generates CAVV
Returns ECI 05
Low < Score ≤ High ──► transStatus=C (Challenge)
ACS sets acsURL
Challenge type selected (OTP/OOB/etc.)
Score > High Threshold ──► transStatus=N or R
transStatusReason code set
No CAVVSCA Exemptions ; When the ACS Can Skip the Challenge
Under PSD2 in Europe (and similar regulations globally), the ACS must apply SCA (Strong Customer Authentication) rules. But certain exemptions allow frictionless approval even for payment transactions:
Without a valid exemption and above EUR 30, the ACS must challenge. Returning transStatus=Y without applying an exemption would violate SCA rules.
14. ECI, CAVV, and Liability Shift
These three concepts form the financial backbone of 3DS. They determine who pays when fraud occurs.
ECI (Electronic Commerce Indicator)
The ECI is a 2-digit code generated by the ACS that travels into the ISO 8583 payment authorisation message. It tells every participant in the payment chain what level of authentication was applied.
CAVV (Cardholder Authentication Verification Value)
The CAVV is a 20-byte cryptographic token generated by the ACS’s HSM. It proves to the issuer’s authorisation host that their own ACS authenticated the cardholder for this specific transaction. The CAVV is returned Base64-encoded (28 characters) in authenticationValue in ARes and RReq.
The CAVV is computed as roughly:
CAVV = HMAC-SHA256(
input = {ECI + ATC + transaction_data_hash + unpredictable_number},
key = issuer_master_key (stored in HSM)
)When the merchant includes the CAVV in the authorisation request, the issuer’s payment host recomputes the expected CAVV and compares. If they match, the issuer knows their own ACS issued this CAVV for this transaction and they accept liability.
Critical rule: Never modify the authenticationValue after receiving it from the ACS. Pass it exactly as-is, byte-for-byte, to the payment authorisation. Any modification breaks the cryptographic signature and causes CAVV validation to fail which either causes the transaction to be declined or removes the liability shift.
The Liability Chain
Frictionless Y (ECI 05/02):
Fraud occurs → Cardholder disputes → Issuer bears chargeback
Merchant is protected
Challenge passes, Y via RReq (ECI 05/02):
Same as above → full liability shift
Attempted (A), ECI 06/01:
Partial shift → scheme rules determine exact scope
Failed auth or no 3DS (ECI 07/00):
Fraud occurs → Merchant bears chargeback
Rejected (R):
Never proceed to auth - if you do, issuer declines
Any fraud = merchant's problem
SCA and PSD2
The Payment Services Directive 2 (PSD2) is a European regulation that mandates Strong Customer Authentication for most online payments. The 3DS 2.x protocol is the primary technical mechanism for achieving SCA compliance.
SCA requires at least two of three factors:
- Knowledge something the cardholder knows (PIN, password, security question)
- Possession something the cardholder has (registered mobile device, hardware token)
- Inherence something the cardholder is (fingerprint, face scan, voice)
In 3DS 2.x terms:
- An OTP sent to a registered mobile phone = possession (the phone) + knowledge (reading the OTP)
- A biometric in a banking app = possession (the phone) + inherence (face/fingerprint)
- A static password alone = only knowledge — not SCA-compliant
The ACS must track which exemptions are available, enforce SCA when required, and apply the correct ECI based on the authentication level achieved.
Error Handling
Error Messages (ErReq / ErRes)
When a protocol-level error occurs, any participant can send an ErReq:
{
"messageType": "ErReq",
"messageVersion": "2.2.0",
"errorCode": "201",
"errorComponent": "C",
"errorDescription": "Message Received Invalid",
"errorDetail": "acctNumber is missing",
"errorMessageType": "AReq"
}Key error codes:
The 10-Second Rule
The ACS must respond to every AReq within 10 seconds. If no ARes arrives, the DS sends an ErReq (code 306) to the 3DS Server, which must either retry, fall back to 3DS 1.x, or proceed without authentication.
The most common cause of ACS timeouts is a synchronous RBA engine call to a slow fraud system. The correct architecture is to run RBA asynchronously and cap all fraud system calls at < 7 seconds, with a pre-computed fallback decision if the fraud system doesn’t respond in time.
JWS Signature Failure
Every server-to-server message must be signed with JWS. If the ACS receives an AReq with an invalid signature, it must reject it with ErReq code 203. This is a security requirement a spoofed AReq could trick the ACS into authenticating a fraudulent transaction.
Common causes:
- DS rotated its signing key. ACS certificate store not updated
- Clock skew between DS and ACS. JWS timestamp check fails
- Message modified in transit (integrity violation)
- Wrong certificate environment (production cert used in test, or vice versa)
Conclusion
3-D Secure 2.x is a sophisticated protocol that creates a near-invisible authentication experience for genuine cardholders while significantly increasing the friction for fraudsters. The key insight is that every field in the AReq is a signal, and the quality of those signals directly determines the authentication outcome.
The protocol’s genius is in its layering: the 3DS Method device fingerprint sets a baseline, acctInfo adds behavioural context, merchantRiskIndicator adds transaction-level signals, and the RBA engine synthesises all of it into a sub-second decision that balances security against conversion.
This article is based on EMVCo 3DS Specification version 2.2.0 and 2.3.1. For the most accurate and current specification, refer to the official EMVCo documentation at emvco.com.








