Advanced Configuration

Data Enrichment

Users can use the additional activity handler to retrieve information for the request using the PXDE (PerimeterX Data Enrichment) object.
First, check that the data enrichment object is verified, then you can access its properties.

MyVerificationHandler.java:

...
public class MyVerificationHandler implements VerificationHandler {
    PXConfiguration pxConfig;
    VerificationHandler defaultVerificationHandler;

    public AutomationVerificationHandler(PXConfiguration pxConfig) throws PXException {
        this.pxConfig = pxConfig;
        PXClient pxClient = new PXHttpClient(pxConfig);
        ActivityHandler activityHandler = new DefaultActivityHandler(pxClient, pxConfig);
        this.defaultVerificationHandler = new DefaultVerificationHandler(pxConfig, activityHandler);
    }

    public boolean handleVerification(PXContext pxContext, HttpServletResponseWrapper httpServletResponseWrapper) throws PXException, IOException {
        if (pxContext.isPxdeVerified()) {
            JsonNode dataEnrichmentPayload = pxContext.getPxde();
            <handle data enrichment payload here>
        }

        return defaultVerificationHandler.handleVerification(pxContext, httpServletResponseWrapper);
    }
}

Then, in your filter:

...
PXConfiguration config = new PXConfiguration.Builder()
     ...
     .build();
PerimeterX enforcer = new PerimeterX(config);
enforcer.setVerificationHandler(new MyVerificationHandler(config));
...

Custom Parameters

With the customParametersProvider function you can add up to 10 custom parameters to be sent back to HUMAN servers.
When set, the function is called before setting the payload on every request to HUMAN servers.

MyCustomParametersProvider.java:

...
public class MyCustomParametersProvider implements CustomParametersProvider {
    public CustomParameters buildCustomParameters(PXConfiguration pxConfiguration, PXContext pxContext) {
        CustomParameters customParameters = new CustomParameters();
        customParameters.setCustomParam1("my_custom_param_1");
        customParameters.setCustomParam2("my_custom_param_2");
        ...
        customParameters.setCustomParam10("my_custom_param_10");
        return customParameters;
    }
}

Then, in your filter:

...
PXConfiguration pxConfiguration = new PXConfiguration.Builder()
     ...
     .customParametersProvider(new MyCustomParametersProvider())
     .build();
...

Multiple Application Support

Simply create multiple instances of the HUMAN class:

PerimeterX enforcerApp1 = new PerimeterX(new PXConfiguration.Builder().appId(APP_ID_1)...build(););
PerimeterX enforcerApp2 = new PerimeterX(new PXConfiguration.Builder().appId(APP_ID_2)...build(););

...

// Inside route request handler for app 1:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOExcption {
    PXContext ctx = enforcerApp1.px(req, new HttpServletResponseWrapper(resp);
    ...
}

...

// Inside route request handler for app 2:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOExcption {
    PXContext ctx = enforcerApp2.pxVerify(req, new HttpServletResponseWrapper(resp);
    if(ctx != null) {
      ...
    }
}

Credentials Intelligence

This feature extracts credentials (hashed username and password) from requests and sends them to HUMAN as additional info in the risk api call. The feature can be toggled on and off, and may be set for any number of unique paths. The settings are adjusted by modifying the custom/pxConfig JSON object.
If credentials are found to be compromised, the header px-compromised-credentials will be added to the origin request with the value 1. You may configure the name of this header with the px_compromised_credentials_header configuration.

Default Values

  • px_compromised_credentials_header: "px-compromised-credentials"
  • px_login_credentials_extraction_enabled: false
  • px_login_credentials_extraction: []
{
  ...
 " px_compromised_credentials_header": "x-px-comp-creds",
 "px_login_credentials_extraction_enabled": true,
  "px_login_credentials_extraction": [
    {
      "pathType": "regex" or null // default: null
      "path": "/login", // support regular expressions and exact path configuration
      "method": "post", // supports all http methods
      "sent_through": "body", // supported sentThroughs: body, header, query-param
      "pass_field": "password", // name (or array of names) of the password field in the request (can also be nested field using dots i.e details.password)
      "user_field": ["username", "email"] // name (or array of names) of the username field in the request (can also be nested field using dots i.e details.username)
    },
    ...
  ],
  ...
};

📘

Important Notice

Define regular expression "path": When using pathType "regex" the path attribute should contain regular expression as a string pattern without slashes and without flags (i.e, instead of /ab+c/i configure "ab+c"). Regular expressions are treated as case-insensitive by the enforcer by default.

Configure user_field or pass_field as an array when the same login endpoint can have two or more different field names as input.

It is also possible to define a custom class to extract the username and password. The class should implement CredentialsExtractor interface and override the extractCredentials method. The method accepts the HttpServletRequest object as a parameter and return the LoginCredentialsClass. If extraction is unsuccessful, the function should return null.

public class DefaultCredentialsCustomExtractor implements CredentialsExtractor {

    @Override
    public LoginCredentials extractCredentials(HttpServletRequest request) {
        return null;
    }
}

Additional S2S Activity

To enhance detection on login credentials extraction endpoints, the following additional information is sent to HUMAN via an additional_s2s activity:

  • Response Code - The numerical HTTP status code of the response.
  • Login Success - A boolean indicating whether the login completed successfully. See the options listed below for how to provide this data.
  • Raw Username - The original username used for the login attempt. In order to report this information, make sure the configuration px_send_raw_username_on_additional_s2s_activity is set to true.

Login Success Reporting

There are a number of different possible ways to report the success or failure of the login attempt. If left empty, the login successful status will always be reported as false.

Default: Empty

private LoginResponseValidationReportingMethod loginResponseValidationReportingMethod = LoginResponseValidationReportingMethod.STATUS

Status
Provide a status or array of statuses that represent a successful login. If a response's status code matches the provided value or one of the values in the provided array, the login successful status is set to true. Otherwise, it's set to false.

Note: To define a range of statuses, use the custom reporting method.

Default Values

px_login_successful_status: 200

private int[] loginResponseValidationStatusCode = {200};

Header

Provide a header name and value. If the header exists on the response and matches the provided value, the login successful status is set to true. If the header is not found on the response, or if the header value does not match the value in the configuration, the login successful status is set to false.

Default Values

px_login_successful_header_name: x-px-login-successful

px_login_successful_header_value: 1

private String headerNameToValidateLoginResponse = "x-px-login-successful";
private String headerValueToValidateLoginResponse = "1";

Body

Provide a string or regular expression with which to parse the response body. If a match is found, the login successful status is set to true. If no match is found, the login successful status is set to false.

Default Values

px_login_successful_body_regex: Empty

private String regexPatternToValidateLoginResponseBody = "You logged in successfully!" // string or RegExp

Custom

Provide a custom class that implements LoginResponseValidator and override isSuccessfulLogin which receives HttpServletResponseWrapper and returns a boolean.

Default Values

px_login_successful_custom_callback: null

public class DefaultCustomLoginResponseValidator implements LoginResponseValidator {

    @Override
    public boolean isSuccessfulLogin(HttpServletResponseWrapper response) {
        return false;
    }
}

Additional S2S Activity Headers

Rather than sending the additional_s2s activity automatically, it is instead possible to generate the base additional_s2s activity along with the URL endpoint, and pass them to the origin server as headers on the original HTTP request. When enabled, the module will add two new headers to the original request and send them to the origin:

  • px-additional-activity, a stringified JSON activity that should be sent.
  • px-additional-activity-url, the complete URL endpoint to which the JSON object should be sent.

Note: Enabling this feature will disable the automatic sending of the additional_s2s activity.

Default Values

px_additional_s2s_activity_header_enabled: false

private boolean additionalS2SActivityHeaderEnabled = true;

The px-additional-activity header value is a stringified JSON object that looks like this. Only the fields indicated with // MODIFY should be changed prior to sending. Other fields should not be altered in any way.

{
  "type": "additional_s2s",
  "timestamp": 1637000000,
  "socket_ip": "1.1.1.1",
  "px_app_id": "PX_APP_ID",
  "url": "https://www.example.com/the-target-url",
  "vid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "details": {
    "client_uuid": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "request_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "ci_version": "v1",
    "http_status_code": null, // MODIFY, number (e.g., 200, 401, 404, etc.)
    "login_successful": null, // MODIFY, boolean (e.g., true, false)
    "raw_username": null // MODIFY, string (e.g., "[email protected]")
  }
}

After parsing the object and adding the appropriate http_status_code and login_successful fields in the origin server, send the JSON object as an HTTP POST request to the URL provided in the px-additional-activity-url header.

📘

Note

The POST request should be sent with the Content-Type: application/json and Authorization: Bearer <PX_AUTH_TOKEN> headers.

Raw Username

When enabled, the raw username used for logins on login credentials extraction endpoints will be reported to HUMAN if (1) the credentials were identified as compromised, and (2) the login was successful as reported via the property above.

Default: false

private boolean addRawUsernameOnAdditionalS2SActivity = true;

Wrappers implementation

Credentials Intelligence require reading the login request and response. In order to apply this and enable reading multiple times two wrappers were created: RequestWrapper and ResponseWrapper. The wrappers should be used inside an interceptor in the following manner.

This should be added before the request is verified by the enforcer:

request = new RequestWrapper((HttpServletRequest) request);

This should be added after the response was sent to the client:

response = new ResponseWrapper((HttpServletResponse) response);
pxFilter.pxPostVerify((ResponseWrapper) response, context);
.

Example for implementation inside interceptor:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // The request wrapper enables to read the request multiple times.
        request = new RequestWrapper((HttpServletRequest) request);

        try {
            PXContext pxContext = this.enforcer.pxVerify((HttpServletRequest) servletRequest, new HttpServletResponseWrapper((HttpServletResponse) servletResponse));

            boolean isHandledResponse = pxContext.isHandledResponse();
            if (isHandledResponse) {
                return;
            }

            filterChain.doFilter(servletRequest, servletResponse);

         // This enables to read the response, it should happen after the response was already sent to the client
            response = new ResponseWrapper((HttpServletResponse) response);
         pxFilter.pxPostVerify((ResponseWrapper) response, context);
        } catch (Exception e) {
            // Fail open in case of Exception
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

Test Block Flow on Monitoring Mode

Allows you to test an enforcer’s blocking flow while you are still in Monitor Mode. When the header name is set(e.g., x-px-block) and the value is set to 1, when there is a block response (for example from using a User-Agent header with the value of PhantomJS/1.0) the Monitor Mode is bypassed and full block mode is applied. If one of the conditions is missing you will stay in Monitor Mode. This is done per request. To stay in Monitor Mode, set the header value to 0.

The Header Name is configurable using the px_bypass_monitor_header property.

Default: Empty

private String bypassMonitorHeader = "x-px-block";

Advanced Blocking Response

In special cases, (such as XHR post requests) a full Captcha page render might not be an option. In such cases, using the Advanced Blocking Response returns a JSON object containing all the information needed to render your own Captcha challenge implementation, be it a popup modal, a section on the page, etc. The Advanced Blocking Response occurs when a request contains the Accept header with the value of application/json. A sample JSON response appears as follows:

{
    "appId": String,
    "jsClientSrc": String,
    "firstPartyEnabled": Boolean,
    "vid": String,
    "uuid": String,
    "hostUrl": String,
    "altBlockScript": String,
    "customLogo": String
}

Once you have the JSON response object, you can pass it to your implementation (with query strings or any other solution) and render the Captcha challenge.

Default Values

px_advanced_blocking_response: true