Authentication

Understanding the multi-layer authentication system and token lifecycle

Authentication

Data Border uses a multi-layer authentication system designed for security and simplicity. This guide explains how authentication works and how to integrate it into your WMS.

Authentication Layers

Data Border has three authentication layers, each serving a different purpose:

flowchart TD
    subgraph Layer1["Layer 1: Tenant"]
        A[Create Tenant JWT] --> B[Tenant Refresh Token]
        B --> C[Data Border Access Token]
    end
    
    subgraph Layer2["Layer 2: Seller"]
        D[OAuth with Amazon] --> E[Seller Refresh Token]
        E --> F[Seller Access Token]
    end
    
    subgraph Layer3["Layer 3: Amazon"]
        G[Amazon Refresh Token] --> H[Amazon Access Token]
        H --> I[SP-API Requests]
    end
    
    C --> D
    F --> G
LayerPurposeYour Responsibility
TenantIdentifies your WMSStore refresh token securely
SellerIdentifies a connected Amazon sellerStore refresh token per seller
AmazonAccesses Amazon SP-APIProvide amazonTokenSecret for encryption

Token Lifecycle

Token Validity

Token TypeValidityRefresh Method
Data Border Access Token30 daysExchange tenant refresh token
Seller Access Token24 hoursExchange seller refresh token
Claim Code5 minutesRe-initiate OAuth flow
Amazon Access Token~1 hourAutomatic (handled by Data Border)

Token Flow Diagram

sequenceDiagram
    participant WMS
    participant ADB
    participant Amazon

    Note over WMS,ADB: Initial Setup (once)
    WMS->>ADB: POST /api/create-tenant
    ADB->>WMS: tenant_id + tenant_refresh_token
    WMS->>WMS: Store tenant credentials

    Note over WMS,ADB: Get ADB Access (every 30 days)
    WMS->>ADB: POST /api/get-adb-access-token
    ADB->>WMS: adb_access_token (valid 30 days)

    Note over WMS,Amazon: Connect Seller (once per seller)
    WMS->>ADB: GET /auth/initialize
    ADB->>Amazon: OAuth redirect
    Amazon->>ADB: Authorization code
    ADB->>WMS: Redirect with seller_id + claim_code
    WMS->>ADB: POST /api/claim-code
    ADB->>WMS: seller_refresh_token
    WMS->>WMS: Store seller credentials

    Note over WMS,ADB: Get Seller Access (every 24 hours)
    WMS->>ADB: POST /api/get-seller-access-token
    ADB->>WMS: seller_access_token (valid 24 hours)

Step-by-Step Integration

Step 1: Create Your Tenant

Before anything else, register your WMS as a tenant:

# Generate a JWT with create-tenant permission
# (Run on the Data Border server with JWT_SECRET set)
JWT=$(npx tsx scripts/generate-jwt.ts --expiry 1h)

# Create the tenant
curl -X POST https://adb.example.com/api/create-tenant \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $JWT" \
  -d '{
    "name": "My WMS System",
    "redirectOrigin": "https://my-wms.com/oauth/callback"
  }'

Response:

{
  "success": true,
  "data": {
    "tenant_id": "clx1y2z3a4b5c6d7e8f9g0h1",
    "refresh_token": "rt_abc123..."
  }
}

Store the tenant_id and refresh_token securely. The refresh token cannot be retrieved again.

Step 2: Get a Data Border Access Token

Exchange your tenant refresh token for an access token:

curl -X POST https://adb.example.com/api/get-adb-access-token \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $JWT" \
  -d '{
    "tenant_id": "clx1y2z3a4b5c6d7e8f9g0h1",
    "refresh_token": "rt_abc123..."
  }'

Response:

{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs..."
  }
}

This access token is valid for 30 days. Schedule a refresh before expiry.

Step 3: Connect an Amazon Seller

When a seller wants to connect their Amazon account:

3a. Generate the Amazon Token Secret

Create a secure random secret that will encrypt the seller's Amazon tokens:

// Generate 32+ bytes of random data, base64 encode
const crypto = require('crypto')
const amazonTokenSecret = crypto.randomBytes(32).toString('base64')
// Store this with the seller - you'll need it for every API call

3b. Redirect to OAuth

Redirect the seller to the OAuth initialization endpoint:

https://adb.example.com/auth/initialize
  ?state=YOUR_STATE_DATA
  &marketplace_region=us-east-1
  &amazonTokenSecret=BASE64_ENCODED_SECRET
  &sellerRedirectUrl=https://my-wms.com/oauth/callback/seller
ParameterDescription
stateArbitrary data returned to you after OAuth (e.g., internal seller ID)
marketplace_regionus-east-1 (NA), eu-west-1 (EU), or us-west-2 (FE)
amazonTokenSecretYour generated secret (32-64 chars of base64 random data)
sellerRedirectUrlWhere to redirect after OAuth (must start with your redirectOrigin)

3c. Handle the OAuth Callback

After the seller authorizes, they're redirected to your sellerRedirectUrl with:

https://my-wms.com/oauth/callback/seller
  ?state=YOUR_STATE_DATA
  &seller_id=seller_abc123
  &code=temp_claim_code_xyz

3d. Claim the Authorization

Exchange the claim code for a seller refresh token (within 5 minutes):

curl -X POST https://adb.example.com/api/claim-code \
  -H "Content-Type: application/json" \
  -H "x-adb-access-token: YOUR_ADB_ACCESS_TOKEN" \
  -d '{
    "seller_id": "seller_abc123",
    "name": "Seller Display Name",
    "callback_url": "https://my-wms.com/webhooks/seller",
    "code": "temp_claim_code_xyz"
  }'

Response:

{
  "success": true,
  "data": {
    "refresh_token": "srt_def456..."
  }
}

Store the seller's refresh_token and amazonTokenSecret securely together. You need both for all seller operations.

Step 4: Get a Seller Access Token

Exchange the seller refresh token for an access token:

curl -X POST https://adb.example.com/api/get-seller-access-token \
  -H "Content-Type: application/json" \
  -H "x-adb-access-token: YOUR_ADB_ACCESS_TOKEN" \
  -d '{
    "seller_id": "seller_abc123",
    "refresh_token": "srt_def456..."
  }'

Response:

{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs..."
  }
}

This access token is valid for 24 hours. Use it with the x-seller-access-token header.

Using Tokens in API Calls

Once you have tokens, use them in API requests:

# Example: Get orders via passthrough API
curl -X GET "https://adb.example.com/passthrough-api/orders/v0/orders?MarketplaceIds=ATVPDKIKX0DER" \
  -H "x-seller-access-token: SELLER_ACCESS_TOKEN" \
  -H "x-amazon-token-secret: AMAZON_TOKEN_SECRET"
HeaderValueWhen Required
x-adb-access-tokenData Border access tokenTenant management, seller management
x-seller-access-tokenSeller access tokenAll seller operations (PII, passthrough, labels, print)
x-amazon-token-secretYour generated secretAll seller operations that access Amazon

Token Refresh Strategy

Implement automatic token refresh to avoid service interruptions:

// Pseudocode for token management
class TokenManager {
  async getAdbAccessToken() {
    if (this.adbToken && !this.isExpiringSoon(this.adbToken, '7d')) {
      return this.adbToken
    }
    // Refresh 7 days before expiry
    this.adbToken = await this.refreshAdbToken()
    return this.adbToken
  }

  async getSellerAccessToken(sellerId) {
    const token = this.sellerTokens[sellerId]
    if (token && !this.isExpiringSoon(token, '1h')) {
      return token
    }
    // Refresh 1 hour before expiry
    this.sellerTokens[sellerId] = await this.refreshSellerToken(sellerId)
    return this.sellerTokens[sellerId]
  }
}

Security Best Practices

Token Storage

TokenStorage Recommendation
Tenant refresh tokenEncrypted at rest, limited access
Data Border access tokenCan cache in memory, refresh on startup
Seller refresh tokenEncrypted per-seller, database storage
Amazon token secretEncrypted, stored with seller refresh token
Seller access tokenCache in memory, short-lived

Never Do This

  • Store tokens in client-side code or local storage
  • Log tokens in plain text
  • Share tokens between environments
  • Use predictable values for amazonTokenSecret
  • Skip HTTPS for any token exchange

Troubleshooting

"Invalid or expired token"

  • Check token expiry times
  • Ensure you're using the correct token for the endpoint
  • Verify the token hasn't been revoked

"Invalid claim code"

  • Claim codes expire after 5 minutes
  • Each code can only be used once
  • Re-initiate the OAuth flow if expired

"Invalid amazonTokenSecret"

  • Must be at least 32 bytes when base64 decoded
  • Must be the same secret used during OAuth initialization
  • Store it securely - you can't recover it

Next Steps

WMS Setup Guide

Complete guide for integrating Data Border into your WMS.

API Reference

Full API documentation for all endpoints.