From 409ca2119dbed308545f3bd3bba6c3c2cf830792 Mon Sep 17 00:00:00 2001 From: Ori Gold Date: Mon, 10 Nov 2025 13:54:06 -0800 Subject: [PATCH 1/5] chore: release v6.16.0 --- CHANGELOG.md | 2 +- pom.xml | 2 +- px_metadata.json | 2 +- web/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a49f74..51d96d1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Change Log -## [x.x.x] - YYYY-MM-DD +## [v6.16.0](https://github.com/PerimeterX/perimeterx-java-sdk/compare/6.16.0...HEAD) (2025-11-12) - Added support for data enrichment header feature (`px_data_enrichment_header_name` configuration) - Added `px_secured_pxhd_enabled` configuration option to enable secure flag on `pxhd` cookie - Added `is_sensitive_route` to risk api and async activities diff --git a/pom.xml b/pom.xml index 69125d25..cb429817 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ PerimeterX JAVA SDK com.perimeterx perimeterx-sdk - 6.15.1 + 6.16.0 jar PerimeterX Java SDK diff --git a/px_metadata.json b/px_metadata.json index beb1e147..107c7889 100644 --- a/px_metadata.json +++ b/px_metadata.json @@ -1,5 +1,5 @@ { - "version": "6.15.1", + "version": "6.16.0", "supported_features": [ "advanced_blocking_response", "batched_activities", diff --git a/web/pom.xml b/web/pom.xml index a0585a32..6134691e 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -65,7 +65,7 @@ 8 8 - 6.15.1 + 6.16.0 From c2e1529fd21d154762c7327cf5a2f03cf821cb81 Mon Sep 17 00:00:00 2001 From: Ori Gold Date: Tue, 11 Nov 2025 11:35:42 -0800 Subject: [PATCH 2/5] chore: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d96d1d..7f0afa5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Change Log ## [v6.16.0](https://github.com/PerimeterX/perimeterx-java-sdk/compare/6.16.0...HEAD) (2025-11-12) - Added support for data enrichment header feature (`px_data_enrichment_header_name` configuration) +- Added support for AD user identifiers feature - Added `px_secured_pxhd_enabled` configuration option to enable secure flag on `pxhd` cookie - Added `is_sensitive_route` to risk api and async activities - Added `additional_token_info` to risk api and async activities From b24220ef36552c9a77d13bf1a15a9e8df34ee1f4 Mon Sep 17 00:00:00 2001 From: Ori Gold Date: Tue, 11 Nov 2025 11:40:20 -0800 Subject: [PATCH 3/5] chore: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f0afa5e..a1112973 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Updated dependencies minor and patch versions (major versions unchanged) - Changed custom parameters to be of type `Object` instead of `String` to allow more flexibility - Changed first party block script in captcha template to end with expected `/captcha.js` +- Changed `RequestWrapper` to include custom headers in methods that retrieve request headers - Fixed possible connection leak issue due to unclosed responses in first party and telemetry requests - Fixed first party fuzzing errors by returning 400 on first party requests with URL length > 1000 characters From ad6611ebf8e1e1da4326e9770d6436f72e113993 Mon Sep 17 00:00:00 2001 From: Ori Gold Date: Tue, 11 Nov 2025 12:03:46 -0800 Subject: [PATCH 4/5] chore: documentation --- CONFIGURATIONS.md | 8 +++++ README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/CONFIGURATIONS.md b/CONFIGURATIONS.md index d6ba5f63..5d64eed9 100644 --- a/CONFIGURATIONS.md +++ b/CONFIGURATIONS.md @@ -53,6 +53,14 @@ Directives |loginResponseValidationStatusCode|Array of status codes that is used to validate if the login was successful.|{200}|int[] |customLoginResponseValidator|Custom class that validates if the login was successful. LoginResponseValidator must be implemented to be able to use this class.|DefaultCustomLoginResponseValidator|LoginResponseValidator |credentialsCustomExtractor|Custom class that extracts the login credentials. CredentialsExtractor must be implemented to be able to use this class.|DefaultCredentialsCustomExtractor|CredentialsExtractor +||pxDataEnrichmentHeaderName|Header name for forwarding data enrichment payload to origin server. When set, the SDK will add the PXDE payload as a header that can be forwarded to backend services.|"" (empty string)|String|Used with data enrichment feature +||securedPxhdEnabled|Enable secure flag on pxhd cookie for enhanced security in HTTPS-only environments.|false|boolean| +||pxJwtCookieName|Name of the cookie containing JWT token for user identifier extraction.|null|String|Part of Account Defender JWT user identifiers feature +||pxJwtCookieUserIdFieldName|Field name in JWT payload to extract as user ID from cookie.|null|String|Supports dot notation for nested fields (e.g., "user.id") +||pxJwtCookieAdditionalFieldNames|List of additional field names to extract from JWT cookie payload.|Empty List|List|Supports dot notation for nested fields +||pxJwtHeaderName|Name of the header containing JWT token for user identifier extraction.|null|String|Part of Account Defender JWT user identifiers feature +||pxJwtHeaderUserIdFieldName|Field name in JWT payload to extract as user ID from header.|null|String|Supports dot notation for nested fields (e.g., "sub") +||pxJwtHeaderAdditionalFieldNames|List of additional field names to extract from JWT header payload.|Empty List|List|Supports dot notation for nested fields ## Interfaces `perimeterx-java-sdk` can be tuned and set a different type of interface in order to make the module more flexible diff --git a/README.md b/README.md index 431e3c02..134a856f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # [PerimeterX](http://www.perimeterx.com) Java SDK -> Latest stable version: [v6.15.0](https://search.maven.org/#artifactdetails%7Ccom.perimeterx%7Cperimeterx-sdk%7C6.15.0%7Cjar) +> Latest stable version: [v6.16.0](https://search.maven.org/#artifactdetails%7Ccom.perimeterx%7Cperimeterx-sdk%7C6.16.0%7Cjar) ## Table of Contents @@ -152,8 +152,12 @@ Please continue reading about the various configurations available on the sdk in #### Data Enrichment - pxde(PerimeterX Data Enrichment) -Users can use the additional activity handler to retrieve information for the request using the pxde object. -First, check that the data enrichment object is verified, then you can access it's properties. +Users can access data enrichment information in two ways: + +1. **Using context.getPxde()** - Access the data enrichment payload directly in your Java code +2. **Using a custom header** - Forward the data enrichment payload as a header to another server (e.g., your origin server) + +##### Accessing Data Enrichment in Java Code MyVerificationHandler.java: ```java @@ -191,6 +195,26 @@ enforcer.setVerificationHandler(new MyVerificationHandler(config)); ... ``` +##### Forwarding Data Enrichment as a Header + +To forward the data enrichment payload to your backend/origin server, configure the header name. After `pxVerify` completes, the PXDE payload will be automatically added as a header to the request, which can then be forwarded: + +```java +PXConfiguration config = new PXConfiguration.Builder() + ... + .pxDataEnrichmentHeaderName("X-PX-Data-Enrichment") + .build(); +PerimeterX enforcer = new PerimeterX(config); + +// In your filter: +PXContext ctx = enforcer.pxVerify(request, response); + +// After pxVerify, the request now contains the data enrichment header +// and can be forwarded to your backend/origin server +// The header will be available as "X-PX-Data-Enrichment" in the request +filterChain.doFilter(request, response); +``` + #### Custom Sensitive Request With the `customIsSensitive` predicate you can force the request to be sensitive. The input of the function is the same request that sent to the method `pxVerify`. @@ -220,6 +244,8 @@ The input of the function is the same request that sent to the method `pxVerify` If the function throws exception, it is equivalent to returning empty custom params. Implementing this configuration overrides the deprecated configuration `customParameterProvider`. +Custom parameters support various types including strings, numbers, and booleans, allowing flexibility in the data sent to PerimeterX. + > **Note** > The request body can only be read once by default. If your function requires reading the body > consider using RequestWrapper which caches the body. Send the wrapped request to @@ -234,12 +260,58 @@ PXConfiguration pxConfiguration = new PXConfiguration.Builder() CustomParameters customParameters = new CustomParameters(); customParameters.setCustomParam1("example-value"); customParameters.setCustomParam2(req.getHeader("example-header")); + customParameters.setCustomParam3(123); // Numbers are supported + customParameters.setCustomParam4(true); // Booleans are supported return customParameters; }) .build(); ... ``` +#### JWT User Identifiers (Account Defender) + +The SDK can extract user identifiers from JWT tokens in cookies or headers to enhance Account Defender capabilities. This allows PerimeterX to correlate user activity across sessions and improve detection accuracy. + +Configure JWT extraction from cookies: +```java +PXConfiguration pxConfiguration = new PXConfiguration.Builder() + ... + .pxJwtCookieName("authCookie") + .pxJwtCookieUserIdFieldName("userId") + .pxJwtCookieAdditionalFieldNames(Arrays.asList("email", "role")) + .build(); +``` + +Configure JWT extraction from headers: +```java +PXConfiguration pxConfiguration = new PXConfiguration.Builder() + ... + .pxJwtHeaderName("Authorization") + .pxJwtHeaderUserIdFieldName("sub") + .pxJwtHeaderAdditionalFieldNames(Arrays.asList("exp", "iss")) + .build(); +``` + +The SDK will: +1. First attempt to extract user identifiers from the configured cookie +2. If not found, attempt to extract from the configured header +3. Support dot notation for nested fields (e.g., "user.id") +4. Automatically handle Bearer token prefixes in headers + +#### Secured PXHD Cookie + +For enhanced security in HTTPS-only environments, you can enable the secure flag on the `pxhd` cookie. This ensures the cookie is only transmitted over secure connections: + +```java +PXConfiguration pxConfiguration = new PXConfiguration.Builder() + ... + .securedPxhdEnabled(true) + .build(); +``` + +> **Note** +> Only enable this in environments where all traffic is served over HTTPS, as the cookie will not be sent over HTTP connections when this flag is enabled. + #### Multiple Application Support Simply create multiple instances of the PerimeterX class: ```java From 9815ba40c6dc55f1c10ebab31b2f0453e42a0aea Mon Sep 17 00:00:00 2001 From: Ori Gold Date: Tue, 11 Nov 2025 13:13:10 -0800 Subject: [PATCH 5/5] fix: clarifying exceptions for RequestWrapper getIntHeader() and getDateHeader() --- src/main/java/com/perimeterx/http/RequestWrapper.java | 10 +++++++--- .../java/com/perimeterx/api/RequestWrapperTest.java | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/perimeterx/http/RequestWrapper.java b/src/main/java/com/perimeterx/http/RequestWrapper.java index d9730c27..448130b2 100644 --- a/src/main/java/com/perimeterx/http/RequestWrapper.java +++ b/src/main/java/com/perimeterx/http/RequestWrapper.java @@ -76,7 +76,7 @@ public Enumeration getHeaders(String name) { } @Override - public int getIntHeader(String name) { + public int getIntHeader(String name) throws NumberFormatException { final String headerValue = getHeader(name); if (headerValue != null) { return Integer.parseInt(headerValue); @@ -85,10 +85,14 @@ public int getIntHeader(String name) { } @Override - public long getDateHeader(String name) { + public long getDateHeader(String name) throws IllegalArgumentException { final String headerValue = getHeader(name); if (headerValue != null) { - return Long.parseLong(headerValue); + try { + return Long.parseLong(headerValue); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Header " + name + " is not a valid date"); + } } return -1L; } diff --git a/src/test/java/com/perimeterx/api/RequestWrapperTest.java b/src/test/java/com/perimeterx/api/RequestWrapperTest.java index 1fea8485..ca0a5ba2 100644 --- a/src/test/java/com/perimeterx/api/RequestWrapperTest.java +++ b/src/test/java/com/perimeterx/api/RequestWrapperTest.java @@ -152,8 +152,8 @@ public void testGetDateHeader() { assertEquals(requestWrapper.getDateHeader("nonExistentHeader"), -1); try { requestWrapper.getDateHeader("stringHeader"); - fail("Expected NumberFormatException"); - } catch (NumberFormatException e) { + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { // Expected exception } }