Skip to content

Repository files navigation

🌐 Browser Driver Example

This repository shows how to securely intercept and handle browser network requests containing cardholder data. Instead of a traditional proxy, it listens for outgoing requests in the browser, detects sensitive payloads, and securely recreates them using Basis Theory Reactors inside a managed Cardholder Data Environment (CDE).

By outsourcing the CDE to Basis Theory, platforms can reduce PCI scope, simplify compliance, and avoid building their own secure infrastructure. This example lets agents (human or bot) enter fake card numbers, intercepts the request, replaces the data with tokenized card information, and completes the transaction securely.

This example uses Puppeteer for request interception and fulfillment, but developers can adapt the approach to any browser stack or tool suitable for their needs.

sequenceDiagram
    actor A as Agent<br>(Person/Bot)
    participant B as Browser
    box rgba(84, 110, 150, 100) Browser Driver
    participant P as Puppeteer
    participant R as Basis Theory<br>Reactor
    end
    participant M as Merchant<br>Checkout
    A->>B: Enters fake card number on checkout page
    B->>P: Sends network request with fake card data
    P->>P: Intercepts request
    P->>R: Forwards request with {{ token }}
    R->>R: Detokenizes card data
    opt Optional
        R->>R: Manipulates request
    end
    R->>M: Recreates and sends request with real card data
    M-->>R: Returns transaction response
    R-->>P: Returns transaction response
    P-->>B: Fulfills the response
    B-->>A: Displays transaction confirmation
Loading

🧩 Prerequisites

🔐 Environment Setup

  1. Create a Management Application
    You need an API key with reactor:* and application:* permissions.

    👉 Click here to create an application using the Customer Portal

  2. Configure Terraform variables

    cp terraform.tfvars.example terraform.tfvars
    # Paste your Management API key in terraform.tfvars under BT_MANAGEMENT_API_KEY
  3. Configure Node variables

    cp .env.example .env
    # Paste your card token id under TOKEN_ID

    💡 If you don't have a card token created yet, check out our the Tokens API spec or get started with one of our Guides.

⚙️ Installation

  1. Initialize your Terraform workspace:

    terraform init
  2. Apply your Terraform configuration:

    terraform apply
  3. Install Node dependencies:

    yarn install

🪄 Run it

Launch the browser connected to Puppeteer using the command below:

yarn start

Now navigate to the merchant checkout page, enter a fake card number, and see the magic happen.

🧱 Extending

Matcher

A Matcher is a JavaScript module that intercepts and handles specific network requests. Each matcher defines two core functions: match() to identify relevant requests and handle() to process them securely.

Matcher API Specification

export default {
  match: (request) => boolean,
  handle: async (request) => response
}

Required Functions

match(request)
  • Purpose: Determines if this matcher should handle the intercepted request
  • Parameters:
    • request.url (string): The request URL
    • request.method (string): HTTP method (GET, POST, PUT, etc.)
    • request.headers (object): Request headers
    • request.postData (string): Request body
  • Returns: boolean - true if this matcher should handle the request
handle(request)
  • Purpose: Processes the matched request by tokenizing sensitive data and forwarding to a Basis Theory Reactor
  • Parameters: Same as match() function
  • Returns: Promise<response> - Response object with:
    • status (number): HTTP status code
    • headers (object): Response headers
    • body (string): Response body

Creating a New Matcher

  1. Create a new file in src/matchers/ (e.g., yourService.js)

  2. Implement the matcher structure with match() and handle() functions

  3. Register the matcher in src/matchers/index.js by importing and adding to the matchers array

Token Expressions

Use Basis Theory detokenization expressions to securely replace sensitive data:

  • {{ token: TOKEN_ID }} - Use the entire token value
  • {{ token: TOKEN_ID | json: "$.data.number" }} - Extract specific field from token data
  • {{ token: TOKEN_ID | json: "$.data" | card_exp: "MM" }} - Format card expiration month
  • {{ token: TOKEN_ID | json: "$.data" | card_exp: "YYYY" }} - Format card expiration year

Environment Variables

Ensure you have the required environment variables:

  • TOKEN_ID: Your card token ID
  • YOUR_REACTOR_ID: Your Basis Theory Reactor ID
  • BROWSER_APPLICATION_KEY: Your Basis Theory Private API key
  • BT_API_URL: Basis Theory API URL (e.g. "https://api.basistheory.com")

Reactor

A Reactor is server-side code that runs inside the Basis Theory Cardholder Data Environment (CDE). It receives tokenized data from matchers, detokenizes it securely, and forwards the request to the actual merchant API.

When to Use Which Reactor

  • Plain Reactor: Use when the request can be fully formatted at the client side with token expressions. The plain reactor simply forwards the request with detokenized data.
  • Custom Reactor: Create a new reactor when you need to manipulate the request format, encrypt data, or perform additional processing inside the CDE.

Reactor API Specification

const axios = require('axios');

module.exports = async function (req) {
  const {
    configuration: { /* your config vars */ },
    args: {
      request: { url, method, headers, data }
    }
  } = req;

  // Your processing logic here
  
  const res = await axios({
    method,
    url,
    headers,
    data,
    validateStatus: () => true
  });
  
  return {
    raw: {
      status: res.status,
      headers: res.headers,
      data: res.data
    }
  };
}

Reactor Parameters

For detailed parameter specifications, see the Basis Theory Reactor API documentation.

Creating a New Reactor

  1. Create a new file in src/reactors/ (e.g., yourService.js)
  2. Add the reactor to Terraform in main.tf with configuration variables
  3. Add the reactor ID output in main.tf
  4. Load the reactor ID in src/utils/loadEnvVars.js
  5. Add the variable to terraform.tfvars.example

Environment Variables

Reactor configuration variables are passed through the configuration object:

  • Define them in main.tf under the reactor's configuration block
  • Add corresponding variables to terraform.tfvars
  • Access them in your reactor code via req.configuration.YOUR_VAR

About

Intercept and recreate browser requests in an outsourced cardholder data environment (CDE)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages