Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 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 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
Expand All @@ -10,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

Expand Down
8 changes: 8 additions & 0 deletions CONFIGURATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>|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<String>|Supports dot notation for nested fields

## <a name="interfaces"></a> Interfaces
`perimeterx-java-sdk` can be tuned and set a different type of interface in order to make the module more flexible
Expand Down
78 changes: 75 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -152,8 +152,12 @@ Please continue reading about the various configurations available on the sdk in

#### <a name="data-enrichment"></a> 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
Expand Down Expand Up @@ -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);
```

#### <a name="custom-sensitive-request"></a> 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`.
Expand Down Expand Up @@ -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
Expand All @@ -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();
...
```

#### <a name="jwt-user-identifiers"></a> 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

#### <a name="secured-pxhd"></a> 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.

#### <a name="multi-app-support"></a> Multiple Application Support
Simply create multiple instances of the PerimeterX class:
```java
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<name>PerimeterX JAVA SDK</name>
<groupId>com.perimeterx</groupId>
<artifactId>perimeterx-sdk</artifactId>
<version>6.15.1</version>
<version>6.16.0</version>

<packaging>jar</packaging>
<description>PerimeterX Java SDK</description>
Expand Down
2 changes: 1 addition & 1 deletion px_metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "6.15.1",
"version": "6.16.0",
"supported_features": [
"advanced_blocking_response",
"batched_activities",
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/com/perimeterx/http/RequestWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public Enumeration<String> 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);
Expand All @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/com/perimeterx/api/RequestWrapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
2 changes: 1 addition & 1 deletion web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<com.perimeterx.version>6.15.1</com.perimeterx.version>
<com.perimeterx.version>6.16.0</com.perimeterx.version>
</properties>

</project>