Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a6b6402
docs: update README with rebranding and updated documentation links
TheUnderScorer Mar 27, 2026
ce70161
docs: fix README badge links to reflect correct repository paths
TheUnderScorer Mar 27, 2026
bbca13c
docs: update package description for rebranding
TheUnderScorer Mar 27, 2026
822466f
chore: update CloudFormation template to make request path parameters…
TheUnderScorer Mar 30, 2026
dc29d6c
feat: skip creation of V3 routes when related variables are undefined
TheUnderScorer Mar 30, 2026
7510903
test: add support for CloudFront E2E tests with V4-only configuration…
TheUnderScorer Mar 30, 2026
7ec4b00
refactor: split CloudFront V4-only configuration into separate Terraf…
TheUnderScorer Mar 30, 2026
b3eb445
refactor: rename CloudFront V4 URL property for consistency
TheUnderScorer Mar 30, 2026
73db3de
test: add V4-only flag to mock tests and separate Terraform resource …
TheUnderScorer Mar 30, 2026
5518b87
refactor: align environment variable formatting and clean up dependen…
TheUnderScorer Mar 31, 2026
e64066b
test: update V4-only mock test to include additional configurations i…
TheUnderScorer Mar 31, 2026
6e99c00
chore: add `ts-node` dependency and update `pnpm-lock.yaml` with new …
TheUnderScorer Mar 31, 2026
cd10c34
test: fix V4-only mock test arguments handling and rename CloudFront …
TheUnderScorer Mar 31, 2026
95a3196
chore: relocate `ts-node` from dependencies to devDependencies and up…
TheUnderScorer Mar 31, 2026
1109c3c
test: use `pnpm exec` for running mock tests in Terraform configurations
TheUnderScorer Mar 31, 2026
cc35cbb
test: refine v3/v4 CloudFront URL handling in mock tests
TheUnderScorer Mar 31, 2026
6a93b2c
refactor: remove unused `hasVariable` method from `customer-variables…
TheUnderScorer Mar 31, 2026
0c2b2fd
chore: link INTER-1944
TheUnderScorer Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yummy-bananas-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fingerprint/aws-cloudfront-proxy': minor
---

Skip creation of V3-related routes if related variables are empty
16 changes: 8 additions & 8 deletions .github/workflows/terraform-e2e-tests-on-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Configure AWS credentials from dev account
uses: aws-actions/configure-aws-credentials@v4
with:
Expand All @@ -33,19 +33,19 @@ jobs:
version: 9

- run: pnpm install

- run: pnpm exec playwright install
working-directory: e2e/tests

- run: pnpm build && bash scripts/preparePackage.sh

- run: pnpm build
working-directory: e2e/website
env:
env:
VITE_API_KEY: ${{ secrets.PUBLIC_API_KEY }}
VITE_SCRIPT_URL_PATTERN: /fpjs/agent?apiKey=<apiKey>&version=<version>&loaderVersion=<loaderVersion>
VITE_ENDPOINT: /fpjs/result?region=us

- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.11.0"
Expand All @@ -62,7 +62,7 @@ jobs:
run: gmake ENV=${{ env.ENV }} TIER=${{ env.TIER }} REGION=${{ env.REGION }} apply-auto-approve
env:
TF_VAR_fpjs_shared_secret: ${{ secrets.PROXY_SECRET }}

mock-warden-e2e-tests:
runs-on: ubuntu-latest
needs: e2e-tests
Expand All @@ -86,7 +86,7 @@ jobs:
with:
version: 9

- run: pnpm install && npm install ts-node -g
- run: pnpm install

- run: pnpm build:release
env:
Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,34 @@
</picture>
</a>
<p align="center">
<a href="https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration"><img src="https://img.shields.io/github/v/release/fingerprintjs/fingerprint-pro-cloudfront-integration" alt="Current version"></a>
<a href="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration/coverage"><img src="https://fingerprintjs.github.io/fingerprint-pro-cloudfront-integration/coverage/badges.svg" alt="coverage"></a>
<a href="https://github.com/fingerprintjs/aws-cloudfront-proxy"><img src="https://img.shields.io/github/v/release/fingerprintjs/aws-cloudfront-proxy" alt="Current version"></a>
<a href="https://fingerprintjs.github.io/aws-cloudfront-proxy/coverage"><img src="https://fingerprintjs.github.io/aws-cloudfront-proxy/coverage/badges.svg" alt="coverage"></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/:license-mit-blue.svg" alt="MIT license"></a>
<a href="https://discord.gg/39EpE2neBg"><img src="https://img.shields.io/discord/852099967190433792?style=logo&label=Discord&logo=Discord&logoColor=white" alt="Discord server"></a>
</p>

# Fingerprint Pro CloudFront Integration
# Fingerprint CloudFront Proxy Integration

[Fingerprint](https://fingerprint.com/) is a device intelligence platform offering industry-leading accuracy.

Fingerprint Pro CloudFront Integration is responsible for
The Fingerprint CloudFront Integration is responsible for

- Proxying download requests of the latest Fingerprint Pro JS Agent between your site and Fingerprint CDN.
- Proxying identification requests and responses between your site and Fingerprint Pro's APIs.
- Proxying download requests of the latest Fingerprint JS Agent between your site and Fingerprint CDN.
- Proxying identification requests and responses between your site and Fingerprint's APIs.

This [improves](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2#the-benefits-of-using-the-cloudfront-integration) both accuracy and reliability of visitor identification and bot detection on your site.
This [improves](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2#the-benefits-of-using-the-cloudfront-integration) both accuracy and reliability of visitor identification and bot detection on your site.

> [!IMPORTANT]
> CloudFront integration v1 has been [deprecated](https://dev.fingerprint.com/docs/cloudfront-proxy-integration).
> This repository now contains the source code for [CloudFront Integration v2](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2).
> If you are currently using v1, see our guide for [Migrating CloudFront proxy integration from v1 to v2](https://dev.fingerprint.com/docs/cloudfront-integration-migration-from-v1-to-v2).
> CloudFront integration v1 has been [deprecated](https://docs.fingerprint.com/docs/cloudfront-proxy-integration).
> This repository now contains the source code for [CloudFront Integration v2](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2).
> If you are currently using v1, see our guide for [Migrating CloudFront proxy integration from v1 to v2](https://docs.fingerprint.com/docs/v3/cloudfront-integration-migration-from-v1-to-v2).

## Requirements

- AWS Account

> [!IMPORTANT]
> The AWS CloudFront Proxy Integration is accessible and exclusively supported for customers on the Enterprise Plan. Other customers are encouraged to use [Custom subdomain setup](https://dev.fingerprint.com/docs/custom-subdomain-setup) or [Cloudflare Proxy Integration](https://dev.fingerprint.com/docs/cloudflare-integration).
> The AWS CloudFront Proxy Integration is accessible and exclusively supported for customers on the Enterprise Plan. Other customers are encouraged to use [Custom subdomain setup](https://docs.fingerprint.com/docs/custom-subdomain-setup) or [Cloudflare Proxy Integration](https://docs.fingerprint.com/docs/cloudflare-integration).

> [!WARNING]
> The underlying data contract in the identification logic can change to keep up with browser updates. Using the AWS CloudFront Proxy Integration might require occasional manual updates on your side. Ignoring these updates will lead to lower accuracy or service disruption.
Expand All @@ -44,14 +44,14 @@ This [improves](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2
To set up CloudFront integration, you need to:

1. Create the required resources in your AWS infrastructure — a CloudFormation stack and a CloudFront distribution.
2. Configure the Fingerprint Pro JS Agent on your site to communicate with your created Lambda@Edge function using the [scriptUrlPattern](https://dev.fingerprint.com/reference/load-function#scripturlpattern) and [endpoint](https://dev.fingerprint.com/reference/load-function#endpoint) parameters.
2. Configure the Fingerprint JS Agent on your site to communicate with your created Lambda@Edge function using the [endpoints](https://docs.fingerprint.com/reference/js-agent-v4-start-function#endpoints) parameter.

See [CloudFront Proxy Integration guide](https://dev.fingerprint.com/docs/cloudfront-proxy-integration-v2) in our documentation for step-by-step instructions. If you have any questions, reach out to our [support team](https://fingerprint.com/support/).
See [CloudFront Proxy Integration guide](https://docs.fingerprint.com/docs/cloudfront-proxy-integration-v2) in our documentation for step-by-step instructions. If you have any questions, reach out to our [support team](https://fingerprint.com/support/).

### Deployment using Terraform

If you prefer to deploy the integration using Terraform, see the [Terraform module repository](https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration) and the related [Terraform guide](https://dev.fingerprint.com/docs/aws-cloudfront-integration-via-terraform).
If you prefer to deploy the integration using Terraform, see the [Terraform module repository](https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration) and the related [Terraform guide](https://docs.fingerprint.com/docs/aws-cloudfront-integration-via-terraform).

## License

This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/fingerprint-pro-cloudfront-integration/blob/main/LICENSE) file for more info.
This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/aws-cloudfront-proxy/blob/main/LICENSE) file for more info.
12 changes: 6 additions & 6 deletions cloudformation/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ Parameters:
Default: ""
Type: String
FpjsGetResultPath:
AllowedPattern: ^([a-zA-Z0-9\-])+$
Description: request path used to send identification requests (aka FPJS_GET_RESULT_PATH)
Default: "result"
AllowedPattern: ^$|^([a-zA-Z0-9\-])+$
Description: (Optional) request path used to send V3 identification requests (aka FPJS_GET_RESULT_PATH)
Default: ""
Type: String
FpjsAgentDownloadPath:
AllowedPattern: ^([a-zA-Z0-9\-])+$
Description: request path used to send ProCDN requests (aka FPJS_AGENT_DOWNLOAD_PATH)
Default: "agent"
AllowedPattern: ^$|^([a-zA-Z0-9\-])+$
Description: (Optional) request path used to send V3 ProCDN requests (aka FPJS_AGENT_DOWNLOAD_PATH)
Default: ""
Type: String
FpjsPreSharedSecret:
AllowedPattern: ^([a-zA-Z0-9\-])+$
Expand Down
10 changes: 10 additions & 0 deletions e2e/infra/terraform/cloudfront_invalidate.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
resource "null_resource" "invalidate_with_secret_cache_v4_only" {
triggers = {
run_id = timestamp()
}

provisioner "local-exec" {
command = "aws cloudfront create-invalidation --distribution-id ${aws_cloudfront_distribution.with_secret_v4_only.id} --paths '/*'"
}
}

resource "null_resource" "invalidate_with_secret_cache" {
triggers = {
run_id = timestamp()
Expand Down
80 changes: 80 additions & 0 deletions e2e/infra/terraform/cloudfront_v4.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
resource "aws_cloudfront_distribution" "with_secret_v4_only" {
enabled = true
is_ipv6_enabled = true
comment = "CloudFront distribution for E2E Tests using Secrets Manager with V4 only"
default_root_object = "index.html"

default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = aws_s3_bucket.website_bucket.bucket_domain_name
viewer_protocol_policy = "redirect-to-https"

forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
}

depends_on = [
aws_s3_bucket_policy.website_bucket_policy
]

origin {
domain_name = aws_s3_bucket.website_bucket.bucket_domain_name
origin_id = aws_s3_bucket.website_bucket.bucket_domain_name
}

restrictions {
geo_restriction {
restriction_type = "none"
}
}

origin {
domain_name = var.fpjs_origin_name
origin_id = var.fpjs_origin_id
custom_origin_config {
origin_protocol_policy = "https-only"
http_port = 80
https_port = 443
origin_ssl_protocols = ["TLSv1.2"]
}
custom_header {
name = "FPJS_SECRET_NAME"
value = module.fingerprint_cloudfront_integration_v4_only.fpjs_secret_manager_arn
}
custom_header {
name = "fpjs_debug"
value = "true"
}
}

ordered_cache_behavior {
path_pattern = "${var.fpjs_behavior_path}*"

allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
cached_methods = ["GET", "HEAD"]
cache_policy_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_cache_policy_id
origin_request_policy_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_origin_request_policy_id
target_origin_id = module.fingerprint_cloudfront_integration_v4_only.fpjs_origin_id
viewer_protocol_policy = "https-only"
compress = true

lambda_function_association {
event_type = "origin-request"
lambda_arn = module.fingerprint_cloudfront_integration_v4_only.fpjs_proxy_lambda_arn
include_body = true
}
}

viewer_certificate {
cloudfront_default_certificate = true
}
}

output "cloudfront_with_secret_url_v4_only" {
value = aws_cloudfront_distribution.with_secret_v4_only.domain_name
}
9 changes: 9 additions & 0 deletions e2e/infra/terraform/fingerprint.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ module "fingerprint_cloudfront_integration" {

fpjs_agent_download_path = var.fpjs_agent_download_path
fpjs_get_result_path = var.fpjs_get_result_path
fpjs_shared_secret = var.fpjs_shared_secret
fetch_lambda_from_s3 = false
local_lambda_path = "../../../lambda_latest.zip"
}

// TODO After release, replace with source from above
module "fingerprint_cloudfront_integration_v4_only" {
source = "git::https://github.com/fingerprintjs/terraform-aws-fingerprint-cloudfront-proxy-integration.git?ref=feature/add-v4-support"

fpjs_shared_secret = var.fpjs_shared_secret
fetch_lambda_from_s3 = false
local_lambda_path = "../../../lambda_latest.zip"
Expand Down
71 changes: 57 additions & 14 deletions e2e/infra/terraform/tests.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ resource "null_resource" "tests" {
command = "pnpm test"
working_dir = "../../tests"
environment = {
CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name
CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name
CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name
CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name
CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret_v4_only.domain_name
}
}
triggers = {
Expand All @@ -16,24 +17,62 @@ resource "null_resource" "tests" {

# Make sure that we run this after cloudfront is ready
depends_on = [
aws_cloudfront_distribution.with_headers, aws_cloudfront_distribution.with_secret,
null_resource.invalidate_with_headers_cache, null_resource.invalidate_with_secret_cache
aws_cloudfront_distribution.with_headers,
aws_cloudfront_distribution.with_secret,
aws_cloudfront_distribution.with_secret_v4_only,

null_resource.invalidate_with_headers_cache,
null_resource.invalidate_with_secret_cache,
null_resource.invalidate_with_secret_cache_v4_only
]
}

resource "null_resource" "mock-warden-tests" {
count = var.run_mock_warden_tests ? 1 : 0

provisioner "local-exec" {
command = "ts-node e2e/scripts/mockTests.ts --project tsconfig.json"
command = "pnpm exec ts-node e2e/scripts/mockTests.ts --project tsconfig.json"
working_dir = "../../../"
environment = {
CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name
CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name
CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret_v4_only.domain_name
FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path
FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path
FPJS_GET_RESULT_PATH = var.fpjs_get_result_path
API_URL = var.mock_warden_url
}
}

triggers = {
# We need to define this to run on every `terraform apply`
run_id = timestamp()
}

# Make sure that we run this after cloudfront is ready
depends_on = [
aws_cloudfront_distribution.with_headers,
aws_cloudfront_distribution.with_secret,
null_resource.invalidate_with_headers_cache,
null_resource.invalidate_with_secret_cache
]
}

resource "null_resource" "mock-warden-tests-v4" {
count = var.run_mock_warden_tests ? 1 : 0

provisioner "local-exec" {
command = "pnpm exec ts-node e2e/scripts/mockTests.ts --project tsconfig.json"
working_dir = "../../../"
environment = {
CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name
CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name
FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path
FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path
FPJS_GET_RESULT_PATH = var.fpjs_get_result_path
API_URL = var.mock_warden_url
CLOUDFRONT_WITH_HEADERS_URL = aws_cloudfront_distribution.with_headers.domain_name
CLOUDFRONT_WITH_SECRETS_URL = aws_cloudfront_distribution.with_secret.domain_name
CLOUDFRONT_WITH_SECRETS_V4_URL = aws_cloudfront_distribution.with_secret.domain_name
V4_ONLY = "true"
FPJS_BEHAVIOR_PATH = var.fpjs_behavior_path
FPJS_AGENT_DOWNLOAD_PATH = var.fpjs_agent_download_path
FPJS_GET_RESULT_PATH = var.fpjs_get_result_path
API_URL = var.mock_warden_url
}
}

Expand All @@ -44,7 +83,11 @@ resource "null_resource" "mock-warden-tests" {

# Make sure that we run this after cloudfront is ready
depends_on = [
aws_cloudfront_distribution.with_headers, aws_cloudfront_distribution.with_secret,
null_resource.invalidate_with_headers_cache, null_resource.invalidate_with_secret_cache
aws_cloudfront_distribution.with_headers,
aws_cloudfront_distribution.with_secret,
aws_cloudfront_distribution.with_secret_v4_only,
null_resource.invalidate_with_headers_cache,
null_resource.invalidate_with_secret_cache,
null_resource.invalidate_with_secret_cache_v4_only
]
}
}
Loading
Loading