Project 4: 3D Secure Authentication Flow
Project 4: 3D Secure Authentication Flow
Project Overview
| Attribute | Value |
|---|---|
| Difficulty | Level 3: Advanced |
| Time Estimate | 2 weeks |
| Programming Language | C / Web (HTML/JS for frontend simulation) |
| Knowledge Area | Payment Protocols / Authentication |
| Key Technologies | 3D Secure 2.0, EMVCo Specs, Digital Signatures |
| Coolness Level | Level 3: Genuinely Clever |
| Business Potential | 3. The โService & Supportโ Model |
Learning Objectives
By completing this project, you will:
- Understand the 3D Secure protocol - Learn how cardholder authentication works for online payments
- Implement the three-party model - Build merchant, issuer, and directory server components
- Handle challenge and frictionless flows - Implement risk-based authentication decisions
- Verify cryptographic assertions - Validate signatures between parties
- Manage redirect flows securely - Prevent session hijacking and CSRF
- Understand liability shift - Learn how authentication affects fraud liability
The Core Question Youโre Answering
โHow can a bank verify that the person making an online purchase actually owns the card?โ
Unlike in-store transactions where you physically present the card, online transactions have no way to verify cardholder presence. 3D Secure solves this:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THE CARD-NOT-PRESENT PROBLEM โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ IN-STORE TRANSACTION ONLINE TRANSACTION โ
โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Customer โ โ Customer โ โ
โ โ with card โ โ (remote) โ โ
โ โโโโโโโโฌโโโโโโโโ โโโโโโโโฌโโโโโโโโ โ
โ โ โ โ
โ โ Presents card โ Types card number โ
โ โ Enters PIN โ ...that's it? โ
โ โ Signs receipt โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Terminal โ โ Website โ โ
โ โ verifies: โ โ has: โ โ
โ โ โข Card โ โ โข PAN โ โ
โ โ โข PIN โ โ โข CVV โ โ
โ โ โข Chip โ โ โข Expiry โ โ
โ โ โข Signatureโ โ โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โ Authentication: Strong Authentication: WEAK! โ
โ (something you have + (something you know + โ
โ something you know) ...nothing else) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ 3D SECURE ADDS: โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Customer โ โ Merchant โ โ Issuer โ โ
โ โ โโโโโโโบโ (website) โโโโโโโบโ (bank) โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ โ โ
โ โ Challenge (if needed) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ โ
โ OTP, biometric, app notification โ โ
โ โ
โ Now the ISSUER verifies the cardholder! โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Security Model: 3D Secure lets the card-issuing bank authenticate its own customer, rather than trusting the merchant.
Deep Theoretical Foundation
1. The Three Domains
โ3Dโ refers to Three Domains:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ THREE DOMAIN MODEL โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ DOMAIN 1: ISSUER DOMAIN โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โข Card-issuing bank โ
โ โข Access Control Server (ACS) โ
โ โข Authenticates the cardholder โ
โ โข Example: Your bank (Chase, BofA, etc.) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ DOMAIN 2: ACQUIRER DOMAIN โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โข Merchant's payment processor โ
โ โข 3DS Server (MPI - Merchant Plug-In) โ
โ โข Initiates authentication โ
โ โข Example: Stripe, Square, Adyen โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ DOMAIN 3: INTEROPERABILITY DOMAIN โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โข Card network infrastructure โ
โ โข Directory Server (DS) โ
โ โข Routes messages between domains โ
โ โข Example: Visa, Mastercard โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ ISSUER INTEROPERABILITY ACQUIRER โ โ
โ โ DOMAIN DOMAIN DOMAIN โ โ
โ โ โ โ
โ โ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโโโโโ โ โ
โ โ โ ACS โโโโโโโโโโบโ DS โโโโโโโโโโโโโบโ 3DS Serverโ โ โ
โ โ โ โ โ โ โ (MPI) โ โ โ
โ โ โโโโโฌโโโโ โโโโโโโโโ โโโโโโโฌโโโโโโ โ โ
โ โ โ โ โ โ
โ โ โ Challenge Flow โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ โ โ
โ โ โ โ โ โ
โ โ โโโโโผโโโโ โโโโโโโผโโโโโโ โ โ
โ โ โIssuer โ โ Merchant โ โ โ
โ โ โ Bank โ โ Website โ โ โ
โ โ โโโโโโโโโ โโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2. 3D Secure 2.0 vs 1.0
3D Secure 1.0 (Deprecated):
- Every transaction required a redirect
- Full-page redirect to bankโs authentication page
- Poor mobile experience
- High cart abandonment
3D Secure 2.0 (Current):
- Risk-based authentication
- Frictionless flow for low-risk transactions
- Embedded challenge (iframe, not redirect)
- Mobile SDK support
- Better data sharing for risk decisions
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3DS 1.0 vs 3DS 2.0 FLOW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ 3DS 1.0 (old) 3DS 2.0 (current) โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ
โ Every transaction: Risk assessment first: โ
โ โ
โ Customer โ Merchant โ Redirect โ Customer โ Merchant โ DS โ โ
โ Bank Page โ Password โ Redirect โ โ โ
โ Merchant โโโบ Low risk? Frictionless โ
โ โ (no customer action) โ
โ โ โ
โ โโโบ High risk? Challenge โ
โ (OTP, biometric, etc.) โ
โ โ
โ Friction: 100% Friction: ~5% (typical) โ
โ Abandonment: High Abandonment: Low โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
3. The Authentication Request (AReq)
The merchant (via 3DS Server) sends rich data to the Directory Server:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AUTHENTICATION REQUEST (AReq) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ REQUIRED FIELDS: โ
โ โโโโโโโโโโโโโโโโ โ
โ โข messageType: "AReq" โ
โ โข messageVersion: "2.2.0" โ
โ โข threeDSServerTransID: unique transaction ID โ
โ โข acctNumber: PAN (encrypted) โ
โ โข cardExpiryDate: "2512" (YYMM) โ
โ โข purchaseAmount: "10000" (in minor units) โ
โ โข purchaseCurrency: "840" (USD) โ
โ โข merchantName: "Example Store" โ
โ โข deviceChannel: "02" (browser) / "01" (app) โ
โ โ
โ RISK ASSESSMENT DATA: โ
โ โโโโโโโโโโโโโโโโโโโโโ โ
โ โข browserAcceptHeader: from HTTP request โ
โ โข browserIP: customer's IP address โ
โ โข browserLanguage: "en-US" โ
โ โข browserUserAgent: full user agent string โ
โ โข browserJavaEnabled: true/false โ
โ โข browserColorDepth: "24" โ
โ โข browserScreenHeight: "1080" โ
โ โข browserScreenWidth: "1920" โ
โ โข browserTZ: "-300" (timezone offset) โ
โ โ
โ โข cardholderEmail: "customer@example.com" โ
โ โข cardholderName: "John Doe" โ
โ โข billAddrLine1, billAddrCity, billAddrPostCode, billAddrCountry โ
โ โข shipAddrLine1, shipAddrCity, shipAddrPostCode, shipAddrCountry โ
โ โ
โ โข threeDSRequestorAuthenticationInd: "01" (payment) โ
โ โข transType: "01" (goods/service purchase) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4. Risk-Based Authentication
The ACS (issuer) analyzes the AReq data to decide:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RISK-BASED DECISION MATRIX โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ SIGNALS FOR FRICTIONLESS (low risk): โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โข Known device (browser fingerprint matches history) โ
โ โข Known IP range (customer's usual location) โ
โ โข Low transaction amount โ
โ โข Shipping to billing address โ
โ โข Trusted merchant โ
โ โข Recent successful authentication โ
โ โ
โ SIGNALS FOR CHALLENGE (high risk): โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โข New device โ
โ โข Unusual location/IP โ
โ โข High transaction amount โ
โ โข Different shipping address โ
โ โข Unusual purchase time โ
โ โข Card recently compromised (data breach) โ
โ โข Multiple failed attempts โ
โ โ
โ DECISION MATRIX: โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โ Low Amount โ High Amount โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโ โ
โ Known โ โ Frictionless โ ? Maybe Challenge โ
โ Device โ โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโ โ
โ New โ ? Maybe โ โ Challenge Required โ
โ Device โ Challenge โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
5. Authentication Response (ARes)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AUTHENTICATION RESPONSE (ARes) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ FRICTIONLESS APPROVAL: โ
โ โโโโโโโโโโโโโโโโโโโโโ โ
โ { โ
โ "messageType": "ARes", โ
โ "transStatus": "Y", // Authenticated โ
โ "transStatusReason": null, โ
โ "eci": "05", // Fully authenticated โ
โ "authenticationValue": "CAVV...", // Cryptographic proof โ
โ "acsTransID": "uuid" โ
โ } โ
โ โ
โ CHALLENGE REQUIRED: โ
โ โโโโโโโโโโโโโโโโโโ โ
โ { โ
โ "messageType": "ARes", โ
โ "transStatus": "C", // Challenge required โ
โ "acsChallengeMandated": "Y", โ
โ "acsURL": "https://acs.issuer.com/challenge", โ
โ "acsTransID": "uuid", โ
โ "authenticationType": "01" // OTP โ
โ } โ
โ โ
โ FAILED/REJECTED: โ
โ โโโโโโโโโโโโโโโ โ
โ { โ
โ "messageType": "ARes", โ
โ "transStatus": "N", // Not authenticated โ
โ "transStatusReason": "01", // Card not enrolled โ
โ "eci": "07" // Attempted (no liability shift) โ
โ } โ
โ โ
โ TRANSACTION STATUS VALUES: โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ Y = Authenticated โ
โ N = Not authenticated / Authentication failed โ
โ U = Authentication could not be performed โ
โ A = Attempted (ACS not available) โ
โ C = Challenge required โ
โ R = Rejected by issuer โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
6. ECI (E-Commerce Indicator) Values
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ECI VALUES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ VISA: MASTERCARD: โ
โ โข 05: Fully authenticated โข 02: Fully authenticated โ
โ โข 06: Attempted authentication โข 01: Attempted authentication โ
โ โข 07: No authentication โข 00: No authentication โ
โ โ
โ LIABILITY SHIFT: โ
โ โโโโโโโโโโโโโโโโ โ
โ โ
โ ECI 05/02 (Authenticated): โ
โ โข Liability shifts to ISSUER โ
โ โข Merchant protected from chargebacks (fraud) โ
โ โข Best outcome for merchant โ
โ โ
โ ECI 06/01 (Attempted): โ
โ โข Partial liability shift in some cases โ
โ โข Card enrolled but ACS unavailable โ
โ โ
โ ECI 07/00 (No Authentication): โ
โ โข No liability shift โ
โ โข Merchant bears fraud risk โ
โ โข Card not enrolled or merchant opted out โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
7. The Challenge Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CHALLENGE FLOW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Customer โ โ Merchant โ โ DS โ โ ACS โ โ
โ โ Browser โ โ 3DS โ โ โ โ (Issuer) โ โ
โ โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ โ
โ โ โ โ โ โ
โ โ Checkout โ โ โ โ
โ โโโโโโโโโโโโโโโโโบโ โ โ โ
โ โ โ AReq โ โ โ
โ โ โโโโโโโโโโโโโโโโโบโ โ โ
โ โ โ โ AReq โ โ
โ โ โ โโโโโโโโโโโโโโโโโบโ โ
โ โ โ โ โ โ
โ โ โ โ ARes โ โ
โ โ โ โโโโโโโโโโโโโโโโโโ โ
โ โ โ ARes โ (C=Challenge) โ
โ โ โโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ โ
โ โ Challenge โ โ โ โ
โ โ (iframe) โ โ โ โ
โ โโโโโโโโโโโโโโโโโโ โ โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบ โ
โ โ CReq (challenge request) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Challenge UI (OTP form) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบ โ
โ โ CRes (OTP entered) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ RReq (result) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ โ โ
โ โ Result โ โ โ โ
โ โโโโโโโโโโโโโโโโโโ โ โ โ
โ โ โ โ โ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Project Specification
What Youโll Build
A working 3D Secure 2.0 simulation including:
- Merchant 3DS Server: Initiates authentication
- Directory Server (Mock): Routes between merchant and issuer
- Access Control Server (Mock): Makes authentication decisions
- Checkout Page: Demonstrates the customer experience
- Challenge Interface: OTP/password challenge flow
Expected Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3D SECURE DEMO CHECKOUT โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ โ
โ Purchase Details โ
โ โโโโโโโโโโโโโโโ โ
โ Item: "Wireless Headphones" โ
โ Amount: $149.99 โ
โ Merchant: Demo Store โ
โ โ
โ Card Information โ
โ โโโโโโโโโโโโโโโ โ
โ Card Number: 4111111111111111 โ
โ Expiry: 12/25 โ
โ CVV: 123 โ
โ Name: John Doe โ
โ โ
โ [PAY NOW] โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[User clicks PAY NOW]
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3DS AUTHENTICATION IN PROGRESS โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ โ
โ [3DS Server] Collecting browser data... โ
โ [3DS Server] Browser: Chrome 121.0.0.0 โ
โ [3DS Server] IP: 192.168.1.100 โ
โ [3DS Server] Screen: 1920x1080 โ
โ โ
โ [3DS Server] Sending AReq to Directory Server... โ
โ { โ
โ "messageType": "AReq", โ
โ "acctNumber": "4111111111111111", โ
โ "purchaseAmount": "14999", โ
โ "browserIP": "192.168.1.100" โ
โ } โ
โ โ
โ [DS] Received AReq, routing to ACS for BIN 411111... โ
โ โ
โ [ACS] Risk Assessment: โ
โ โข Known device: NO โ
โ โข Known IP: NO โ
โ โข Amount: $149.99 (MEDIUM) โ
โ โข Risk Score: 72/100 โ
โ โข Decision: CHALLENGE REQUIRED โ
โ โ
โ [ACS] Sending ARes with transStatus="C" โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CHALLENGE: Verify Your Identity โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ ๐ฆ Your Bank โ โ
โ โ โ โ
โ โ To verify this purchase, we've sent a one-time โ โ
โ โ password to your registered phone ending in **89 โ โ
โ โ โ โ
โ โ Purchase: $149.99 at Demo Store โ โ
โ โ โ โ
โ โ Enter OTP: [______] โ โ
โ โ โ โ
โ โ [VERIFY] [Cancel] โ โ
โ โ โ โ
โ โ Didn't receive code? Resend โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ (This iframe is served by the issuer's ACS) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[User enters correct OTP: 123456]
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AUTHENTICATION COMPLETE โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ โ
โ [ACS] OTP verified successfully โ
โ [ACS] Generating authentication value (CAVV)... โ
โ [ACS] Sending RReq to 3DS Server โ
โ โ
โ Authentication Result: โ
โ โโโโโโโโโโโโโโโโโโโโโ โ
โ Status: Y (AUTHENTICATED) โ
โ ECI: 05 (Visa fully authenticated) โ
โ CAVV: AAABBJlHYWUZ... (base64) โ
โ โ
โ LIABILITY SHIFT: โ Issuer accepts fraud liability โ
โ โ
โ [3DS Server] Authentication successful โ
โ [3DS Server] Proceeding with authorization... โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โ PAYMENT APPROVED โ
โ โ
โ Authorization Code: A12345 โ
โ Transaction ID: TXN-987654321 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Project Structure
3ds_simulator/
โโโ src/
โ โโโ main.c # CLI/server entry
โ โโโ merchant/
โ โ โโโ checkout.c # Checkout page handler
โ โ โโโ threeds_server.c # 3DS Server (MPI)
โ โ โโโ browser_data.c # Browser fingerprinting
โ โโโ directory_server/
โ โ โโโ ds.c # Directory Server
โ โ โโโ routing.c # BIN to ACS routing
โ โ โโโ message_validation.c # Schema validation
โ โโโ acs/
โ โ โโโ acs.c # Access Control Server
โ โ โโโ risk_engine.c # Risk-based decision
โ โ โโโ challenge.c # Challenge flow
โ โ โโโ otp.c # OTP generation/validation
โ โโโ protocol/
โ โ โโโ areq.c # AReq message
โ โ โโโ ares.c # ARes message
โ โ โโโ creq.c # CReq message
โ โ โโโ cres.c # CRes message
โ โ โโโ rreq.c # RReq message
โ โโโ crypto/
โ โ โโโ signatures.c # Message signatures
โ โ โโโ cavv.c # CAVV generation
โ โโโ web/
โ โโโ http_server.c # Basic HTTP server
โ โโโ json.c # JSON parsing
โโโ static/
โ โโโ checkout.html # Checkout page
โ โโโ challenge.html # Challenge iframe
โ โโโ style.css
โโโ tests/
โ โโโ test_areq.c
โ โโโ test_risk_engine.c
โ โโโ test_challenge.c
โโโ Makefile
โโโ README.md
Core API Design
// threeds_server.h
typedef struct {
char trans_id[37]; // UUID
char merchant_id[32];
char merchant_name[64];
int purchase_amount; // In minor units (cents)
char purchase_currency[4]; // ISO currency code
} TransactionInfo;
typedef struct {
char acct_number[20];
char card_expiry[5]; // YYMM
char cardholder_name[64];
} CardInfo;
typedef struct {
char user_agent[256];
char accept_header[128];
char ip_address[46];
char language[8];
int screen_width;
int screen_height;
int color_depth;
int timezone_offset;
bool java_enabled;
bool javascript_enabled;
} BrowserInfo;
// Build and send AReq
typedef struct {
char trans_status; // Y, N, C, U, A, R
char eci[3]; // 05, 06, 07
char cavv[64]; // Base64 encoded
char acs_url[256]; // For challenge
char acs_trans_id[37];
bool challenge_required;
} AResResult;
AResResult initiate_authentication(
const TransactionInfo* trans,
const CardInfo* card,
const BrowserInfo* browser
);
// acs.h
typedef struct {
int risk_score; // 0-100
char decision; // Y (frictionless), C (challenge), N (deny)
char reason[64];
} RiskDecision;
RiskDecision assess_risk(
const char* pan,
int amount,
const BrowserInfo* browser,
const char* merchant_id
);
typedef struct {
char otp[7]; // 6 digits
time_t expires_at;
char trans_id[37];
} Challenge;
Challenge generate_challenge(const char* trans_id, const char* phone_last4);
bool verify_challenge(const char* trans_id, const char* otp_entered);
Solution Architecture
System Design
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3DS SIMULATOR ARCHITECTURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ BROWSER โ
โ โโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ checkout.html โ โ
โ โ โ โ
โ โ โข Card form โ โ
โ โ โข Browser data collection (JS) โ โ
โ โ โข 3DS Method iframe (device fingerprinting) โ โ
โ โ โข Challenge iframe container โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โ POST /initiate-3ds โ
โ โ {card, browser_data, transaction} โ
โ โผ โ
โ MERCHANT SERVER (3DS Server) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ threeds_server.c โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ Build AReq โ โ Parse ARes โ โ โ
โ โ โ (protocol/areq.c) โ โ (protocol/ares.c) โ โ โ
โ โ โโโโโโโโโโโฌโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโ โ โ
โ โ โ โ โ โ
โ โ โ AReq JSON โ ARes JSON โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โ โ
โ DIRECTORY SERVER โ โ
โ โโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ds.c โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ Validate Message โ โ Route by BIN โ โ โ
โ โ โ โ โ (BIN โ ACS URL) โ โ โ
โ โ โโโโโโโโโโโฌโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโ โ โ
โ โ โ โ โ โ
โ โ โ AReq โ ARes โ โ
โ โ โผ โ โ โ
โ โโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โ โ
โ ACCESS CONTROL SERVER (ACS) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ acs.c โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ Risk Engine โ โ Challenge Logic โ โ โ
โ โ โ (risk_engine.c) โ โ (challenge.c) โ โ โ
โ โ โ โ โ โ โ โ
โ โ โ โข Device history โ โ โข OTP generation โ โ โ
โ โ โ โข Amount analysis โ โ โข OTP validation โ โ โ
โ โ โ โข Behavioral โ โ โข Timeout โ โ โ
โ โ โโโโโโโโโโโฌโโโโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโ โ โ
โ โ โ โ โ โ
โ โ โผ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ Decision: โ โ โ
โ โ โ โข Frictionless (transStatus=Y) โ Return ARes โ โ โ
โ โ โ โข Challenge (transStatus=C) โ Serve challenge UI โ โ โ
โ โ โ โข Deny (transStatus=N) โ Return ARes with reason โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ CAVV Generation (crypto/cavv.c) โ โ โ
โ โ โ โข Sign authentication result โ โ โ
โ โ โ โข Include transaction details โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Risk Engine Design
// risk_engine.c
typedef struct {
// Device fingerprint
char device_id[64]; // Hash of browser characteristics
// History
int previous_purchases; // From this device
int failed_attempts; // Recent failures
time_t last_purchase;
// Current transaction
int amount;
bool shipping_matches_billing;
char merchant_category[8]; // MCC code
} RiskFactors;
#define RISK_WEIGHT_DEVICE_NEW 25
#define RISK_WEIGHT_IP_NEW 15
#define RISK_WEIGHT_HIGH_AMOUNT 20
#define RISK_WEIGHT_DIFFERENT_SHIP 10
#define RISK_WEIGHT_ODD_TIME 5
#define RISK_WEIGHT_FAILED_RECENT 15
#define RISK_WEIGHT_SUSPICIOUS_MCC 10
int calculate_risk_score(const RiskFactors* factors) {
int score = 0;
// New device
if (factors->previous_purchases == 0) {
score += RISK_WEIGHT_DEVICE_NEW;
}
// High amount (threshold varies by merchant)
if (factors->amount > 10000) { // $100 in cents
score += RISK_WEIGHT_HIGH_AMOUNT;
}
// Different shipping
if (!factors->shipping_matches_billing) {
score += RISK_WEIGHT_DIFFERENT_SHIP;
}
// Recent failures
if (factors->failed_attempts > 0) {
score += RISK_WEIGHT_FAILED_RECENT * factors->failed_attempts;
}
return score > 100 ? 100 : score;
}
RiskDecision assess_risk(/*...*/) {
RiskFactors factors = gather_factors(/*...*/);
int score = calculate_risk_score(&factors);
RiskDecision decision;
decision.risk_score = score;
if (score < 30) {
decision.decision = 'Y'; // Frictionless
strcpy(decision.reason, "Low risk transaction");
} else if (score < 70) {
decision.decision = 'C'; // Challenge
strcpy(decision.reason, "Moderate risk - verification needed");
} else {
decision.decision = 'N'; // Deny
strcpy(decision.reason, "High risk - declined");
}
return decision;
}
Implementation Guide
Phase 1: Protocol Messages
Goal: Implement AReq/ARes message structures.
// areq.c
#include <json.h>
typedef struct {
char message_type[8]; // "AReq"
char message_version[8]; // "2.2.0"
char three_ds_server_trans_id[37];
char acct_number[20];
char card_expiry_date[5];
char purchase_amount[16];
char purchase_currency[4];
char merchant_name[64];
char device_channel[3];
// Browser info
char browser_accept_header[256];
char browser_ip[46];
char browser_language[8];
char browser_user_agent[512];
// ... many more fields
} AReq;
char* areq_to_json(const AReq* areq) {
json_t* root = json_object();
json_object_set_new(root, "messageType",
json_string(areq->message_type));
json_object_set_new(root, "messageVersion",
json_string(areq->message_version));
// ... all fields
char* json_str = json_dumps(root, JSON_COMPACT);
json_decref(root);
return json_str;
}
Phase 2: Basic Server
Goal: HTTP server to handle checkout flow.
// Using mongoose or libmicrohttpd
void handle_initiate_3ds(Request* req, Response* res) {
// Parse card, browser data, transaction from request
CardInfo card;
BrowserInfo browser;
TransactionInfo trans;
parse_checkout_request(req->body, &card, &browser, &trans);
// Build AReq
AReq areq = build_areq(&card, &browser, &trans);
// Send to DS (in production, over TLS mutual auth)
AResResult ares = send_areq_to_ds(&areq);
if (ares.challenge_required) {
// Return challenge URL to browser
json_response(res, 200, "{\"challenge\": true, \"acsUrl\": \"%s\"}",
ares.acs_url);
} else if (ares.trans_status == 'Y') {
// Proceed with authorization
AuthResult auth = authorize_transaction(&trans, ares.cavv, ares.eci);
json_response(res, 200, "{\"success\": true, \"authCode\": \"%s\"}",
auth.auth_code);
} else {
json_response(res, 200, "{\"success\": false, \"reason\": \"%s\"}",
ares.reason);
}
}
Phase 3: Directory Server Routing
Goal: Route AReq to correct ACS by BIN.
// routing.c
typedef struct {
char bin_start[9];
char bin_end[9];
char acs_url[256];
char acs_id[32];
} BinRoute;
static BinRoute routes[] = {
{"40000000", "49999999", "http://localhost:8082/acs", "VISA_ACS_001"},
{"51000000", "55999999", "http://localhost:8083/acs", "MC_ACS_001"},
{"34000000", "34999999", "http://localhost:8084/acs", "AMEX_ACS_001"},
// ...
};
const char* route_to_acs(const char* pan) {
char bin[9];
strncpy(bin, pan, 8);
bin[8] = '\0';
for (int i = 0; i < sizeof(routes)/sizeof(routes[0]); i++) {
if (strcmp(bin, routes[i].bin_start) >= 0 &&
strcmp(bin, routes[i].bin_end) <= 0) {
return routes[i].acs_url;
}
}
return NULL; // Card not enrolled
}
Phase 4: ACS Risk Engine
Goal: Make frictionless vs challenge decisions.
See Risk Engine Design section above.
Phase 5: Challenge Flow
Goal: Implement OTP challenge.
// challenge.c
// In-memory challenge store (use Redis in production)
static Challenge active_challenges[1000];
static int challenge_count = 0;
Challenge generate_challenge(const char* trans_id, const char* phone_last4) {
Challenge c;
strncpy(c.trans_id, trans_id, 36);
c.trans_id[36] = '\0';
// Generate 6-digit OTP
unsigned int seed;
RAND_bytes((unsigned char*)&seed, sizeof(seed));
snprintf(c.otp, 7, "%06d", seed % 1000000);
c.expires_at = time(NULL) + 300; // 5 minutes
// Store
active_challenges[challenge_count++] = c;
// In production: actually send SMS via Twilio, etc.
printf("[ACS] Sending OTP %s to phone ending in %s\n", c.otp, phone_last4);
return c;
}
bool verify_challenge(const char* trans_id, const char* otp_entered) {
for (int i = 0; i < challenge_count; i++) {
if (strcmp(active_challenges[i].trans_id, trans_id) == 0) {
if (time(NULL) > active_challenges[i].expires_at) {
return false; // Expired
}
return strcmp(active_challenges[i].otp, otp_entered) == 0;
}
}
return false; // Not found
}
Phase 6: CAVV Generation
Goal: Generate cryptographic authentication value.
// cavv.c
// CAVV structure (simplified - real CAVV is more complex)
typedef struct {
char algorithm; // 0 = HMAC, 1 = CVN etc.
char version; // Protocol version
char key_indicator[2]; // Which key was used
char auth_result; // Y/A/N etc.
char trans_id[4]; // Abbreviated trans ID
char mac[20]; // HMAC of above
} CAVV;
char* generate_cavv(const char* trans_id, char auth_result,
const unsigned char* key) {
CAVV cavv;
cavv.algorithm = 0;
cavv.version = 2;
cavv.auth_result = auth_result;
// Copy first 4 bytes of trans ID
memcpy(cavv.trans_id, trans_id, 4);
// Generate HMAC
unsigned char to_mac[8];
to_mac[0] = cavv.algorithm;
to_mac[1] = cavv.version;
to_mac[2] = cavv.auth_result;
memcpy(to_mac + 3, cavv.trans_id, 4);
HMAC(EVP_sha1(), key, 16, to_mac, 7, cavv.mac, NULL);
// Base64 encode entire structure
char* b64 = base64_encode((unsigned char*)&cavv, sizeof(cavv));
return b64;
}
Testing Strategy
Protocol Compliance Tests
void test_areq_required_fields() {
AReq areq = {0};
// Missing required field
char* json = areq_to_json(&areq);
// Should fail validation
assert(validate_areq(json) == false);
// Add required fields
strcpy(areq.message_type, "AReq");
strcpy(areq.message_version, "2.2.0");
// ... add all required
json = areq_to_json(&areq);
assert(validate_areq(json) == true);
}
Risk Engine Tests
void test_low_risk_frictionless() {
RiskFactors factors = {
.previous_purchases = 10,
.failed_attempts = 0,
.amount = 1000, // $10
.shipping_matches_billing = true
};
int score = calculate_risk_score(&factors);
assert(score < 30); // Should be frictionless
}
void test_high_risk_challenge() {
RiskFactors factors = {
.previous_purchases = 0, // New device
.failed_attempts = 2,
.amount = 50000, // $500
.shipping_matches_billing = false
};
int score = calculate_risk_score(&factors);
assert(score >= 30); // Should require challenge
}
End-to-End Flow Tests
#!/bin/bash
# test_3ds_flow.sh
# Start all servers
./ds_server &
./acs_server &
./merchant_server &
sleep 2
# Test frictionless flow (low amount, known device)
RESPONSE=$(curl -s -X POST http://localhost:8080/initiate-3ds \
-H "Content-Type: application/json" \
-d '{
"pan": "4111111111111111",
"amount": 1000,
"browserInfo": {...}
}')
assert_contains "$RESPONSE" '"transStatus":"Y"'
# Test challenge flow (high amount)
RESPONSE=$(curl -s -X POST http://localhost:8080/initiate-3ds \
-H "Content-Type: application/json" \
-d '{
"pan": "4111111111111111",
"amount": 100000,
"browserInfo": {...}
}')
assert_contains "$RESPONSE" '"challenge":true'
Common Pitfalls & Debugging
Pitfall 1: Incorrect Version Handling
Symptom: DS rejects messages.
Cause: Protocol version mismatch between components.
Fix: Ensure all components use same messageVersion.
Pitfall 2: CAVV Validation Failure
Symptom: Authorization fails despite successful authentication.
Cause: CAVV format doesnโt match network expectations.
Fix: Follow EMVCo specification exactly for CAVV structure.
Pitfall 3: Challenge Iframe Issues
Symptom: Challenge doesnโt display.
Cause: CSP blocking iframe, or cross-origin issues.
Fix: Set proper headers: X-Frame-Options: ALLOW-FROM merchant.com.
Extensions & Challenges
Extension 1: Device Fingerprinting
Implement 3DS Method for device fingerprinting before authentication.
Extension 2: SCA Exemptions
Implement Strong Customer Authentication exemptions (low value, recurring, etc.)
Extension 3: Decoupled Authentication
Implement app-based push notification authentication.
Extension 4: Real Card Network Integration
Integrate with Visa/Mastercard test environments.
Resources
Specifications
- EMVCo 3D Secure 2.x Specification (free from emvco.com)
- EMVCo 3D Secure SDK Specification
- PCI 3DS Core Security Standard
Books
| Topic | Book |
|---|---|
| Digital Signatures | Serious Cryptography Ch. 13 |
| Web Security | Bug Bounty Bootcamp by Vickie Li |
| Risk-Based Auth | Security in Computing by Pfleeger |
Self-Assessment Checklist
- AReq/ARes messages comply with EMVCo spec
- Risk engine makes reasonable decisions
- Challenge flow works end-to-end
- CAVV is generated correctly
- Frictionless flow works for low-risk transactions
- Can explain liability shift
- Understand the three-domain model
- Iframe security is properly handled
Whatโs Next?
You now understand e-commerce authentication. Move to Project 5: Mini Payment Gateway to build a system that ties together tokenization, P2PE, and 3DS with PCI-compliant architecture.