AWS Cloudfront

This guide explains how to set up a reverse proxy for Didomi's Privacy Center using AWS CloudFront. Two implementation options are available based on your requirements.

Choose your implementation

Implementation guide

Choose your implementation

Option A: Use a subdomain

To implement a reverse proxy on a subdomain, you will first create an SSL certificate in AWS Certificate Manager, then configure a CloudFront distribution with two origins pointing to Didomi's servers. This approach uses pure CloudFront functionality without requiring any serverless functions.

  • Customer usage: /api/* and /* paths directly

  • CloudFront Distribution - Routes /api/* → api.privacy-center.org and /* → sdk.privacy-center.org

  • Route 53 - DNS management for your domain

  • Custom Origins - Direct routing to Didomi servers

Option B: Use the main domain

To implement a reverse proxy on the main domain, you will first create a Lambda@Edge function to handle URL transformation, then configure a CloudFront distribution that routes /consent/* requests through the Lambda function. The Lambda function removes the /consent/ prefix before forwarding requests to Didomi's servers.

  • Customer usage: /consent/* prefix for all CMP requests

  • CloudFront Distribution - Routes requests to appropriate origins. Matches /consent/* → routes to SDK origin

  • Lambda@Edge Function - Removes /consent/ prefix before forwarding

  • Route 53 - DNS management for your domain

  • S3 Bucket - Hosts your static UI files (not required)

  • Custom Origins - Routes to Didomi servers:

    • sdk.privacy-center.org - For SDK files

    • api.privacy-center.org - For API requests

Domain vs Subdomain Trade-offs

Implementation guide

Option A: Use a subdomain

Option B: Use the main domain

Option A: Use a subdomain

This setup creates a pure CloudFront configuration. The Didomi SDK will use /api/* and /* paths through your reverse proxy.

Step 1: Create SSL Certificate

  1. Go to AWS Certificate Manager (ACM)

    • Navigate to the us-east-1 region (N. Virginia)

    • Click "Request certificate"

  2. Request a public certificate

    • Domain name: Your domain (e.g., cmp.example.com)

    • Subject alternative names (SANs): Add .your-domain.com if you want to support subdomains

    • Validation method: DNS validation (recommended) or Email validation

  3. Validate the certificate

    • If using DNS validation: Add the CNAME records to your DNS provider

    • If using email validation: Check your email and click the validation link

    • Wait for the certificate status to change to "Issued"

  4. Copy the certificate ARN

    • Once issued, click on the certificate

    • Copy the ARN (format: arn:aws:acm:us-east-1:ACCOUNT-ID:certificate/CERTIFICATE-ID)

Step 2: Create CloudFront Distribution

  1. Go to CloudFront Console

    • Navigate to AWS CloudFront

    • Click "Create distribution"

  2. Configure Origins

    Origin 1: Didomi SDK

    • Origin domain: sdk.privacy-center.org

    • Origin name: Didomi-SDK-Origin

    • Protocol: HTTPS only

    • HTTPS port: 443

    • Minimum origin SSL protocol: TLSv1.2

  3. Origin 2: Didomi API

    • Origin domain: api.privacy-center.org

    • Origin name: Didomi-API-Origin

    • Protocol: HTTPS only

    • HTTPS port: 443

    • Minimum origin SSL protocol: TLSv1.2

  4. Configure Cache Behaviors

    Default Behavior (catch-all)

    • Path pattern: Default (*)

    • Origin: Any (will be overridden by specific behaviors)

    • Viewer protocol policy: Redirect HTTP to HTTPS

    • Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE

    • Cache policy: CachingDisabled

    • Origin request policy: CORS-S3Origin

    API Behavior

    • Path pattern: /api/*

    • Origin: Didomi-API-Origin

    • Viewer protocol policy: Redirect HTTP to HTTPS

    • Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE

    • Cache policy: CachingDisabled (no caching for API requests)

    • Origin request policy: CORS-S3Origin (forwards all headers)

    SDK Behavior

    • Path pattern: /sdk/*

    • Origin: Didomi-SDK-Origin

    • Viewer protocol policy: Redirect HTTP to HTTPS

    • Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE

    • Cache policy: CachingOptimized (for static SDK files)

    • Origin request policy: CORS-S3Origin

  5. Configure SSL Certificate

    • Alternate domain names (CNAMEs): Add your domain

    • SSL certificate: Custom SSL certificate (select your ACM certificate)

    • Security policy: TLSv1.2_2021

  6. Create Distribution

    • Click "Create distribution"

    • Wait for deployment (5-10 minutes)

Step 3: Configure DNS

  1. Get CloudFront domain name

    • Copy the distribution domain name (e.g., d1abc123def.cloudfront.net)

  2. Update DNS records

    • For subdomain: Create CNAME record: cmp.example.com → d1abc123def.cloudfront.net

    • For root domain: Create A record pointing to CloudFront IP addresses

Option B: Use the main domain

This setup includes Lambda@Edge for URL transformation. The Didomi SDK will use /consent/* prefix for all CMP requests.

Prerequisites: Complete Step 1 (SSL Certificate) from Option A above - the process is identical.

Step 1: Create S3 Bucket for UI (Optional)

Step2: Create IAM execution role

  1. Navigate to IAM Console

    • Go to AWS IAM Console

    • Click "Roles" in the left navigation

  2. Create new role

    • Click "Create role"

    • Select "AWS service" as the trusted entity type

    • Select "Lambda" use case from the service list

    • Click "Next"

  3. Skip permissions for now

    • At step 2 (Add permissions), don't add any policies yet

    • Click "Next" to proceed

  4. Configure role details

    • Enter role name: lambda-edge-execution-role (or your preferred name)

    • Optionally add a description: "Execution role for Lambda@Edge functions"

    • Click "Create role"

  5. Create custom permission policy

    • On the newly created role page, click "Add permissions" → "Create inline policy"

    • Switch to JSON view and paste the following policy:

      {
          "Version": "1",
          "Statement": [
              {
                  "Action": [
                      "logs:CreateLogGroup",
                      "logs:CreateLogStream",
                      "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
              }
          ]
      }

Step 3: Create Lambda Function

  1. Create Lambda function

    • Go to Lambda Console (us-east-1 region required for Lambda@Edge)

    • Function name: didomi-cmp-proxy

    • Runtime: Use latest LTS version

    • Architecture: x86_64 (Lambda@Edge does not support functions with an architecture of arm64)

  2. Add the index.js file to the lambda:

    1. Create a zip file (lambda.zip) with index.js at the root

  3. Upload code

    • Upload the lambda.zip file

    • Set handler: index.handler

    • Memory: 128 MB

    • Timeout: 30 seconds

  4. Set permissions

    • Execution role: Select "Use an existing role" and choose the role created in step 2 (lambda-edge-execution-role)

Lambda Function Code Explanation

The index.js file contains the core logic for the reverse proxy.

Main Handler Function

exports.handler = async (event) => {
    const request = event.Records[0].cf.request;
    const uri = request.uri;
    const method = request.method;

What it does: Extracts the request details from the CloudFront event.

// Extract path after /consent/
const pathAfterConsent = uri.substring(8); // Remove '/consent/'

// Check if this is a valid Didomi request
if (!isDidomiRequest(pathAfterConsent)) {
    return { status: '404', ... };
}

What it does:

  • Removes the /consent/ prefix from the URI

  • Validates the path matches Didomi patterns

  • Returns 404 for invalid requests

// For both API and SDK requests, keep the full path after /consent/
request.uri = `/${pathAfterConsent}`;

What it does:

  • For API requests (/consent/api/events): Preserves the api/ prefix → /api/events

  • For SDK requests (/consent/[API_KEY]/loader.js): Keeps full path → /[API_KEY]/loader.js

Request Validation

const DIDOMI_PATTERNS = [
    /^\\/.*$/,  // Accept all paths (recommended by Didomi)
    /^\\/api\\/.*$/  // API patterns
];

What it does: Validates that the request path matches expected Didomi patterns.

Step 4: Create CloudFront Distribution

  1. Follow the same process as Option A for creating the distribution and configuring the Didomi origins (steps 1-2 from Option A)

  2. Configure cache behaviors (KEY DIFFERENCES from Option A)

    API Behavior - DIFFERENT path pattern

  • Path Pattern: /consent/api/* (vs /api/* in Option A)

  • Target Origin: Didomi-API-Origin

  • Lambda@Edge Association:

    • Event: origin-request

    • Function: Your Lambda function ARN

    • Include body: true

  • Other settings: Same as Option A API behavior

SDK Behavior - DIFFERENT path pattern

  • Path Pattern: /consent/* (vs /sdk/* in Option A)

  • Target Origin: Didomi-SDK-Origin

  • Lambda@Edge Association:

    • Event: origin-request

    • Function: Your Lambda function ARN

    • Include body: true

  • Other settings: Same as Option A SDK behavior

Important: Behavior order matters - API behavior (/consent/api/) must come before SDK behavior (/consent/)

  1. Configure SSL certificate and DNS

    • Follow the same SSL certificate and DNS configuration as Option A (Steps 4-5 from Option A)

Step 5: Publish Lambda Version

  1. Publish new version

    • Go to Lambda function

    • Click "Actions" → "Publish new version"

    • Note the version number (e.g., 1)

  2. Update CloudFront

    • Go back to CloudFront distribution

    • Update Lambda function associations to use the published version

General information

Challenges and solutions

Problem
Cause
Solution

403 Forbidden for POST Requests

Legacy forwarded_values config doesn't support non-cacheable methods

Use modern cache_policy and origin_request_policy instead

Double Slash in URLs

Extra slash added during URI construction

Remove extra slash in Lambda function URI modification

Origin Switching in Lambda@Edge

Lambda@Edge doesn't support dynamic origin switching

Use separate CloudFront cache behaviors with different origins

Lambda Function Not Updating

Lambda@Edge requires published versions, not $LATEST

Always publish new versions and update CloudFront associations

CloudWatch Logs Location

Lambda@Edge logs are in us-east-1 region with different log group name

Use correct log group: /aws/lambda/us-east-1.[function-name]

Important Considerations

Regional Requirements

  • Lambda@Edge: Must be created in us-east-1 region

  • ACM Certificate: Must be in us-east-1 for CloudFront

  • CloudWatch Logs: Lambda@Edge logs are always in us-east-1

Deployment Timing

  • Lambda@Edge: Takes 5-10 minutes to propagate globally

  • CloudFront: Distribution updates take 1-2 minutes

  • DNS: Can take up to 48 hours to propagate

Security

  • HTTPS Only: Configure redirect-to-https policy

  • CORS: Lambda function adds CORS headers automatically

  • Origin Validation: Only allow Didomi domains as origins

Monitor Logs

aws logs tail /aws/lambda/us-east-1.didomi-cmp-proxy --region us-east-1 --follow

Troubleshooting

Common Issues

For Both Options:

403 Forbidden

  • Verify cache behavior allows POST requests

  • Check origin request policy includes required headers

  • Ensure origins are accessible from CloudFront

404 Not Found

  • Check if request path matches expected patterns (/api/* or /sdk/* for Option A, /consent/* for Option B)

  • Verify origins are configured correctly

  • Ensure DNS is pointing to CloudFront distribution

SSL/TLS Errors

  • Verify ACM certificate is valid and in us-east-1 region

  • Check that certificate covers your domain

  • Ensure origins use HTTPS

Option B Only (Lambda@Edge):

502 Bad Gateway

  • Check Lambda function logs in CloudWatch

  • Verify Lambda function is published (not using $LATEST)

  • Ensure CloudFront is using correct Lambda version

Lambda Execution Errors

  • Check CloudWatch logs for Lambda@Edge function

  • Verify Lambda function has proper permissions

  • Ensure Lambda code handles all request types

Debug Steps

Check CloudWatch Logs

  • Look for Lambda function execution logs

  • Check for errors in request processing

Verify CloudFront Configuration

  • Check cache behaviors are in correct order

  • Verify Lambda associations are correct

Test Direct Origin Access

  • Test if Didomi origins are accessible directly

  • Verify SSL certificates are valid


Last updated