Configuration
Building the PxConfig
The HUMAN Go Enforcer configuration is compiled into a PxConfig
struct. There are three ways to build the PxConfig
configuration struct:
- Builder: Call
NewPXConfigBuilder
with the required values, use the builder's dedicated setter functions, and finally callBuild()
- JSON: Create a JSON file with the configurations and call the
GetPxConfigFromJson()
function - Directly: Invoke
BuildPXConfig()
with amap[string]interface{}
representing the configuration
The
PxConfig
struct should be initialized using one of these three methods only. Do not initialize thePxConfig
via a struct literal.
Required values:
- px_app_id
- px_auth_token
- px_cookie_secret
App ID
The application ID. Required to build the PxConfig
struct.
// directly
pxConfig, err := perimeterx.BuildPXConfig(map[string]interface{}{
"px_app_id": "<APP_ID>",
// ...
})
// json
{
"px_app_id": "<APP_ID>",
// ...
}
// builder
pxConfig := perimeterx.NewPXConfigBuilder(map[string]interface{}{
"px_app_id": "<APP_ID>",
// ...
}).Build()
Auth Token
The token used for authorization with the HUMAN backend. Required to build the PxConfig
struct.
// directly
pxConfig, err := perimeterx.BuildPXConfig(map[string]interface{}{
"px_auth_token": "<AUTH_TOKEN>",
// ...
})
// json
{
"px_auth_token": "<AUTH_TOKEN>",
// ...
}
// builder
pxConfig := perimeterx.NewPXConfigBuilder(map[string]interface{}{
"px_auth_token": "<AUTH_TOKEN>",
// ...
}).Build()
Cookie Secret
The secret used to encrypt and decrypt the risk cookie. Required to build the PxConfig
struct.
// directly
pxConfig, err := perimeterx.BuildPXConfig(map[string]interface{}{
"px_cookie_secret": "<COOKIE_SECRET>",
// ...
})
// json
{
"px_cookie_secret": "<COOKIE_SECRET>",
// ...
}
// builder
pxConfig := perimeterx.NewPXConfigBuilder(map[string]interface{}{
"px_cookie_secret": "<COOKIE_SECRET>",
// ...
}).Build()
Module Enabled
A boolean flag to enable/disable the HUMAN Enforcer.
Default: true
SetModuleEnabled(false) // Builder
{"px_module_enabled": false} // JSON file
pxConfig["px_module_enabled"]= false //Direct
Module Mode
Sets the working mode of the Enforcer.
Values:
"monitor"
- Monitor Mode"active_blocking"
- Blocking Mode
While ModuleMode is on ("monitor"
), all requests will undergo the full inspection cycle yet will never be blocked. Setting the ModuleMode flag to "active blocking" will activate the module to enforce the blocking score. The HUMAN module will block users crossing the block score threshold that you define. If a user crosses the minimum block score then the user will receive the captcha/block page.
Default: "monitor"
SetModuleMode("active_blocking") // Builder
{"px_module_mode": "active_blocking"} // JSON file
pxConfig["px_module_mode"] = "active_blocking" //Direct
Blocking Score
Sets the minimum blocking score of a request, which can be set to any integer between 0 and 100.
Default: 100
SetBlockingScore(70) // Builder
{"px_blocking_score": 70} // JSON file
pxConfig["px_blocking_score"] = 70 //Direct
Sensitive Routes
List of route prefixes. The HUMAN module will always match the request URI with this list, and if a match is found, will create a server-to-server call, even if the cookie is valid and its score is low. Ensures that routes that are more sensitive to attacks will always undergo the full enforcement cycle.
Default: Empty
SetSensitiveRoutes([]string{"/example", "/very/important"}) // Builder
{"px_sensitive_routes": []string{"/example", "/very/important"}} // JSON file
pxConfig["px_sensitive_routes"] = []string{"/example", "/very/important"} //Direct
Sensitive Routes Regex
List of regular expressions. The HUMAN module will always match the request URI with this list, and if a match is found, will create a server-to-server call, even if the cookie is valid and its score is low. Ensures that routes that are more sensitive to attacks will always undergo the full enforcement cycle.
Default: Empty
SetSensitiveRoutes([]string{"^/example.*", "^/very/important.*"}) // Builder
{"px_sensitive_routes": []string{"^/example.*", "^/very/important.*"}} // JSON file
pxConfig["px_sensitive_routes"] = []string{"^/example.*", "^/very/important.*"} //Direct
Monitored Routes
List of route prefixes. The HUMAN module will always match the request URI with this list, and if a match is found, the request will be treated as if in monitor mode.
Default: Empty list
SetMonitoredRoutes([]string{"/monitored-route"}) // Builder
{"px_monitored_routes": []string{"/monitored-route"}} // JSON file
pxConfig["px_monitored_routes"] = []string{"/monitored-route"} //Direct
Monitored Routes Regex
List of regular expressions. The HUMAN module will always match the request URI with this list, and if a match is found, the request will be treated as if in monitor mode.
Default: Empty list
SetMonitoredRoutesRegex([]string{"^/monitored-route.*"}) // Builder
{"px_monitored_routes_regex": []string{"^/monitored-route.*"}} // JSON file
pxConfig["px_monitored_routes_regex"] = []string{"^/monitored-route.*"} //Direct
Bypass Monitor Mode
There is an option to add a header that will force blocking flow when the enforcer is in monitor mode using the px_bypass_monitor_header
configuration.
Default: Empty
SetBypassMonitorHeader("x-px-block") // Builder
{"px_bypass_monitor_header": "x-px-block"} // JSON file
pxConfig["px_bypass_monitor_header"] = "x-px-block" //Direct
Enforced Routes
List of route prefixes. The HUMAN module will always match the request URI with this list, and if a match is found, the request will be treated as if in active_blocking mode.
Default: Empty list
SetEnforcedRoutes([]string{"/enforced-route"}) // Builder
{"px_enforced_routes": []string{"/enforced-route"}} // JSON file
pxConfig["px_enforced_routes"] = []string{"/enforced-route"} //Direct
Enforced Routes Regex
List of regular expressions. The HUMAN module will always match the request URI with this list, and if a match is found, the request will be treated as if in active_blocking mode.
Default: Empty list
SetEnforcedRoutes([]string{"^/enforced-route.*"}) // Builder
{"px_enforced_routes": []string{"^/enforced-route.*"}} // JSON file
pxConfig["px_enforced_routes"] = []string{"^/enforced-route.*"} //Direct
Filter By Route
An array of route prefixes that are always allowed and not validated by the HUMAN enforcer.
Each string value of a path will be treated as a prefix.
Default: Empty
SetWhitelistRoutes([]string{"/example", "/not/important"}) // Builder
{"px_filter_by_route": []string{"/example", "/not/important"}} // JSON file
pxConfig["px_filter_by_route"] = []string{"/example", "/not/important"} //Direct
Filter By Route Regex
An array of regular expressions that are always allowed and not validated by the HUMAN enforcer. A regular expression can be defined directly as an expression, and will be treated as is.
Default: Empty
SetWhitelistRoutesRegex([]string{"^/example.*", "^/not/important"}) // Builder
{"px_filter_by_route_regex": []string{"^/example$", "/not/important"}} // JSON file
pxConfig["px_filter_by_route_regex"] = []string{"^/example", "^/not/important"} //Direct
Filter By HTTP Method
List of HTTP methods. The HUMAN module will always match the request method with this list, and if a match is found, will pass the request. The list is case-insensitive.
Default: Empty list
SetFilterByHttpMethods([]string{"OPTIONS", "TRACE"}) // Builder
{"px_filter_by_http_method": []string{"OPTIONS", "TRACE"}} // JSON file
pxConfig["px_filter_by_http_method"] = []string{"OPTIONS", "TRACE"} //Direct
Filter By User Agent
List of User Agents. The HUMAN module will always match the request user agent with this list, and if a match is found, will pass the request. The list is case-insensitive.
Default: Empty list
SetFilterByUserAgents([]string{"test-agent", "FilteredAgent"}) // Builder
{"px_filter_by_user_agent": []string{"test-agent", "FilteredAgent"}} // JSON file
pxConfig["px_filter_by_user_agent"] = []string{"test-agent", "FilteredAgent"} //Direct
Filter By IP
List of IPs or IP ranges. The HUMAN module will always match the extracted IP with this list, and if a match is found, will pass the request.
Default: Empty list
SetFilterByIps([]string{"10.21.21.21", "21.0.0.0/8"}) // Builder
{"px_filter_by_ip": []string{"10.21.21.21", "21.0.0.0/8"}} // JSON file
pxConfig["px_filter_by_ip"] = []string{"10.21.21.21", "21.0.0.0/8"} //Direct
Filter By Extension
A list of static file extensions to filter.
Default: [".css", ".bmp", ".tif", ".ttf", ".docx", ".woff2", ".js", ".pict", ".tiff", ".eot", ".xlsx", ".jpg", ".csv", ".eps", ".woff", ".xls", ".jpeg", ".doc", ".ejs", ".otf", ".pptx", ".gif", ".pdf", ".swf", ".svg", ".ps", ".ico", ".pls", ".midi", ".svgz", ".class", ".png", ".ppt", ".mid", ".webp", ".jar", ".map"]
SetExtensionsToBeFiltered([]string{"css", "bmp", "tif"}) // Builder
{"px_filter_by_extension": []string{"css", "bmp", "tif"}} // JSON file
pxConfig["px_filter_by_extension"] = []string{"css", "bmp", "tif"} //Direct
Sensitive Headers
A list of sensitive headers can be configured to prevent specific headers from being sent to HUMAN servers. Filtering cookie headers for privacy is set by default, and can be overridden on the pxConfig variable.
Default: ["cookie", "cookies"]
SetSensitiveHeaders([]string{"a-secret-header", "other-secret-header"}) // Builder
{"px_sensitive_headers": []string{"a-secret-header", "other-secret-header"}} // JSON file
pxConfig["px_sensitive_headers"] = []string{"a-secret-header", "other-secret-header"} //Direct
IP Headers
Extracting the real IP address from a request. The user's IP can be passed to the HUMAN module by passing a list of headers to extract the real IP from, ordered by priority.
Note: It is important that the real connection IP is properly extracted when your server is behind a load balancer or CDN. In order to properly perform processing and detection on server-to-server calls, HUMAN module needs the real user's IP.
Default: Empty
SetIPHeaders([]string{"X-Forwarded-For", "X-Real-Ip"}) // Builder
{"px_ip_headers": []string{"X-Forwarded-For", "X-Real-Ip"}} // JSON file
pxConfig["px_ip_headers"] = []string{"X-Forwarded-For", "X-Real-Ip"} //Direct
First Party Enabled
First Party Mode enables the module to send/receive data to/from the sensor, acting as a reverse proxy for client requests and sensor activities.
Default: true
SetFirstPartyEnabled(false) // Builder
{"px_first_party_enabled": false} // JSON file
pxConfig["px_first_party_enabled"] = false //Direct
First Party Timeout
First Party requests have a timeout that can be controlled in cases that the enforcer takes too long to read the server's response. This timeout is measured in ms and in configured in px_first_party_timeout
.
Default: 4000
SetFirstPartyTimeout(10000) // Builder
{"px_first_party_timeout": 10000} // JSON file
pxConfig["px_first_party_timeout"] = 10000 // Direct
Enrich Custom Parameters
Custom parameters allow you to add up to 10 custom parameters to be sent back to HUMAN servers. When set, the EnrichCustomParams function is called before setting the payload on every request to HUMAN servers.
Default: Empty
The configured custom parameters function must have a signature complying with the CustomParamsHandler
type:
type CustomParamsHandler func(map[string]interface{}, *http.Request) map[string]interface{}
func enrichCustomParams(customParams map[string]interface{}, originalRequest *http.Request) map[string]interface{} {
customParams["custom_param1"] = "string" // hard-coded string
customParams["custom_param2"] = 12 // hard-coded int
customParams["custom_param3"] = originalRequest.Method // value from the original request
return customParams
}
SetEnrichCustomParams(enrichCustomParams) // Builder
// Not available for JSON file
pxConfig["px_enrich_custom_parameters"] = enrichCustomParams //Direct
CSS Ref
Modifies a custom CSS by adding the CSSRef directive and providing a valid URL to the CSS.
Default: Empty
SetCSSRef("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css") // Builder
{"px_css_ref": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"} // JSON file
pxConfig["px_css_ref"] = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" //Direct
JS Ref
Adds a custom JS file by adding JSRef directive and providing the JS file that is loaded with the block page.
Default: Empty
SetJsRef("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js") // Builder
{"px_js_ref": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"} // JSON file
pxConfig["px_js_ref"] = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" //Direct
Custom Logo
The logo is displayed at the top of the the block page.
Default: Empty
SetCustomLogo("https://s.perimeterx.net/logo.png") // Builder
{"px_custom_logo": "https://s.perimeterx.net/logo.png"} // JSON file
pxConfig["px_custom_logo"] = "https://s.perimeterx.net/logo.png" //Direct
S2S Timeout
The time in milliseconds to wait for the HUMAN S2S (Server-to-Server) API response. The API is called when a Risk Cookie does not exist, or is expired or invalid.
Default: 1000
SetS2STimeout(250) // Builder
{"px_s2s_timeout": 250} // JSON file
pxConfig["px_s2s_timeout"] = 250 //Direct
Logger Severity
Sets the logger severity level mode.
Values:
"none"
- HUMAN logger will not output any logs"error"
- HUMAN logger will log errors only and fatal events (e.g.,panic
)"debug"
- HUMAN logger will output detailed logs for debugging purposes
Default: "error"
SetLoggerSeverityLevel("debug") // Builder
{"px_logger_severity": "debug"} // JSON file
pxConfig["px_logger_severity"] = "debug" //Direct
Custom Cookie Header
A case-insensitive header name that contains HUMAN cookies. If this header exists on the request, the cookies in the header value will be processed along with those found on the Cookie header. If any duplicate cookies are found, those in the custom cookie header will take precedence.
Default: "x-px-cookies"
SetCustomCookieHeader("x-custom-cookies") // Builder
{"px_custom_cookie_header": "x-custom-cookies"} // JSON file
pxConfig["px_custom_cookie_header"] = "x-custom-cookies" //Direct
Block Invalid Cookie
When set to true
, the enforcer will not perform risk api calls when cookie decryption or validation fail. Instead, it will immediately serve a block page.
Default: false
SetBlockInvalidCookie(true) // Builder
{"px_block_invalid_cookie": true} // JSON file
pxConfig["px_block_invalid_cookie"] = true //Direct
Custom Verification Handler
A custom verification handler is a function that can be called by the HUMANModule inside the default verification handler to enable additional functionality.
Default: Empty
The verification handler must have a signature complying with the VerificationHandler
type:
type VerificationHandler func(PxConfig, *PxContext, *http.Response, *http.Request)
Example usage:
func customVerificationHandler (config perimeterx.PxConfig, context *perimeterx.PxContext, w *http.Response, r *http.Request) {
if context.Headers.Get("must-have-this-header") == "" {
perimeterx.Block(context, w)
}
}
SetCustomVerificationHandler(customVerificationHandler) // Builder
// Not available for JSON file
pxConfig["px_custom_verification_handler"] = customVerificationHandler //Direct
Data Enrichment
PX data enrichment, the data enrichment cookie is attached to S2S calls as a way to transfer additional data between the Enforcer and HUMAN collector. The data it contains is set by the collector according to the setting in the portal and is available on the cookie as a JSON object. While this functionality is mostly controlled by the collector, you may want access to the PXDE values after activities have been sent, in the additional activity handler.
The data enrichment payload can also be processed with CustomVerificationHandler
.
Below is an example that includes the pre-condition checks to process the data enrichment payload and enrich the request headers.
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,
"blockScript": 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.
In addition, you can add the _pxOnCaptchaSuccess
callback function on the window object of your Captcha page to react according to the Captcha status. For example when using a modal, you can use this callback to close the modal once the Captcha is successfully solved.
An example of using the _pxOnCaptchaSuccess
callback is as follows:
window._pxOnCaptchaSuccess = function (isValid) {
if (isValid) {
alert('yay');
} else {
alert('nay');
}
};
For details on how to create a custom Captcha page, refer to the documentation.
If you wish to disable this behavior when the Accept
header has the value of application/json, set the following configuration:
SetAdvancedBlockingResponseEnabled(false) // Builder
{"px_advanced_blocking_response_enabled": false} // JSON file
pxConfig["px_advanced_blocking_response_enabled"] = false //Direct
User Identifiers (JWT)
The User Identifiers are used by HUMAN to identify clients during and across sessions. The identifiers are:
- JWT - JSON Web Token is an encrypted token that holds a JSON object which contains metadata on the user request, including the app user ID. It can be stored in a cookie or header.
- CTS - Cross Tab Session represented by a token that is stored on the pxcts cookie. (No configuration necessary.)
To extract the desired fields from the JWT (either as a request header or as a cookie), you must configure:
- The name of the cookie or header where the JWT token can be found
- The field name in the JWT payload representing the user ID
- Any additional field values in the JWT payload that should be reported
Default: Empty
For cookie-based JWT tokens:
// Builder
SetJwtCookieName("jwt_cookie")
SetJwtCookieUserIdFieldName("user_id")
SetJwtCookieAdditionalFieldNames([]string{"field1", "field2.subfield1"})
// JSON file
{
"px_jwt_cookie_name": "jwt_cookie",
"px_jwt_cookie_user_id_field_name": "user_id",
"px_jwt_cookie_additional_field_names": ["field1", "field2.subfield1"]
}
// Direct
pxConfig["px_jwt_cookie_name"] = "jwt_cookie"
pxConfig["px_jwt_cookie_user_id_field_name"] = "user_id"
pxConfig["px_jwt_cookie_additional_field_names"] = []string{"field1", "field2.subfield1"}
For header-based JWT tokens:
// Builder
SetJwtHeaderName("x-jwt-token-header")
SetJwtHeaderUserIdFieldName("user_id")
SetJwtHeaderAdditionalFieldNames([]string{"field1", "field2.subfield1"})
// JSON file
{
"px_jwt_header_name": "x-jwt-token-header",
"px_jwt_header_user_id_field_name": "user_id",
"px_jwt_header_additional_field_names": ["field1", "field2.subfield1"]
}
// Direct
pxConfig["px_jwt_header_name"] = "x-jwt-token-header"
pxConfig["px_jwt_header_user_id_field_name"] = "user_id"
pxConfig["px_jwt_header_additional_field_names"] = []string{"field1", "field2.subfield1"}
CORS Support Enabled
Enables default CORS block headers on CORS requests. Also allows for the activation of other CORS features, such as adding custom block headers custom handling or filtering of preflight requests.
Default: false
SetCorsSupportEnabled(true) // Builder
{"px_cors_support_enabled": true} // JSON file
pxConfig["px_cors_support_enabled"] = true //Direct
CORS Preflight Request Filter Enabled
When enabled, filters preflight requests from the enforcement flow. (Note: If a custom preflight handler is set, it will be invoked.)
Default: false
SetCorsFilterPreflightRequestsEnabled(true) // Builder
{"px_cors_preflight_request_filter_enabled": true} // JSON file
pxConfig["px_cors_preflight_request_filter_enabled"] = true //Direct
CORS Custom Preflight Handler
A custom function that is triggered and can return a custom response for preflight requests. If nil is returned, no response will be returned and the enforcer flow will continue.
Note: The custom preflight handler will be invoked even if the CORS preflight filter configuration is enabled. If the filter is enabled and the handler returns nil, the request will be filtered.
Default: nil
// Builder
SetCorsCustomPreflightHandler(func(request *http.Request) *http.Response {
if shouldRespond {
return &http.Response{} // custom response
}
return nil
})
//Direct
pxConfig["px_cors_custom_preflight_handler"] = func(request *http.Request) *http.Response {
if shouldRespond {
return &http.Response{} // custom response
}
return nil
}
CORS Create Custom Block Headers
If CORS support is enabled, block responses will include the following two headers by default.
Access-Control-Allow-Origin - req.Header.Get("Origin")
Access-Control-Allow-Credentials - true
However, it is possible to customize the headers returned on block responses. This function returns headers that should be added to all block responses to CORS requests.
Default: nil
// Builder
SetCorsCreateCustomCorsHeaders(func(request *http.Request, context *perimeterx.PxContext) http.Header {
return http.Header{
"X-Custom-Origin": []string{req.Header.Get("Origin")}
}
})
// Direct
pxConfig["px_cors_create_custom_block_response_headers"] = func(request *http.Request, context *perimeterx.PxContext) http.Header {
return http.Header{
"X-Custom-Origin": []string{req.Header.Get("Origin")}
}
}
Credential 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 pxConfig.
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: CILoginMap{}
px_credentials_intelligence_version: "v2"
px_send_raw_username_on_additional_s2s_activity: false
px_additional_s2s_activity_header_enabled: false
px_login_successful_reporting_method: "status"
px_login_successful_body_regex: nil
px_login_successful_header_name: "x-px-login-successful"
px_login_successful_header_value: "1"
px_login_successful_status: []int{200}
px_custom_credentials_extractor: nil
{
// ...
"px_compromised_credentials_header": "x-px-comp-creds",
"px_login_credentials_extraction_enabled": true,
"px_login_credentials_extraction": [
{
"pathType": "regex" // default: "exact"
"path": "/login", // support regular expressions and exact path configuration
"method": "post", // supports all http methods
"sent_through": "body", // supported values: 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)
},
// ...
],
// ...
}
Builder example:
credentialsExtractionDetails := []interface{}{map[string]interface{}{
"pathType": "direct",
"path": "/login",
"method": "post",
"pass_field": "password",
"user_field": []string{"username", "email"},
}}
NewPXConfigBuilder(...).
SetLoginCredentialsExtractionEnabled(true).
SetLoginCredentialsExtractionDetails(credentialsExtractionDetails).
Build()
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 struct to extract the username and password. The struct should implement CredentialsExtractor
interface and override the ExtractCredentials
method. The method accepts the http.Request
as a parameter and return the LoginCredentials
. If extraction is unsuccessful, the function should return nil
.
type MyCredentialsExtractor struct {
username string
password string
}
func (myCredentialsExtractor MyCredentialsExtractor) ExtractCredentials(request *http.Request) *perimeterx.LoginCredentials {
//write extraction logic here
return &perimeterx.LoginCredentials{Username: myCredentialsExtractor.username, Password: myCredentialsExtractor.password}
}
SetCustomCredentialsExtractor(MyCredentialsExtractor) // Builder
// Not available for JSON file
pxConfig["px_custom_credentials_extractor"] = MyCredentialsExtractor //Direct
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: UnknownLoginResponseValidationMethod
SetLoginResponseValidationMethod("body") // Builder
{"px_login_successful_reporting_method": "body"} // JSON file
pxConfig["px_login_successful_reporting_method"] = "body" //Direct
Using the ResponseWriterWrapper and the PostEnforce() Function
Since the
http.ResponseWriter
does not store response data, it is imperative to wrap it with theResponseWriterWrapper
and pass the wrapper to thehandler
function. This way, the data in theResponseWriterWrapper
struct can be queried in the enforcer'sPostEnforce()
function to determine whether the login was successful or not and send theadditional_s2s
activity accordingly.
func middleware(handler http.HandlerFunc) http.HandlerFunc {
return func (w http.ResponseWriter, r *http.Request) {
// ...
if resp != nil {
// ...
} else {
// wrap response writer prior before calling handler
responseWriterWrapper := perimeterx.NewResponseWriterWrapper(w)
// defer a call to PostEnforce and pass in the response writer wrapper
defer enforcer.PostEnforce(responseWriterWrapper, context, runtime)
// pass the response writer wrapper to the handler
handler(responseWriterWrapper, r)
}
}
}
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: [200]
SetLoginResponseValidationStatusCode([]int{200}) // Builder
{"px_login_successful_status": []int{200}} // JSON file
pxConfig["px_login_successful_status"] = []int{200} //Direct
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"
SetHeaderNameToValidateLoginResponse("x-px-login-successful") // Builder
{"px_login_successful_header_name": "x-px-login-successful"} // JSON file
pxConfig["px_login_successful_header_name"] = "x-px-login-successful" //Direct
SetHeaderValueToValidateLoginResponse("1") // Builder
{"px_login_successful_header_value": "1"} // JSON file
pxConfig["px_login_successful_header_value"] = "1" //Direct
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 for true. If no match is found, the login successful status is set to false.
Default: nil
SetRegexPatternToValidateLoginResponseBody("/login.*") // Builder
{"px_login_successful_body_regex": "/login.*"} // JSON file
pxConfig["px_login_successful_body_regex"] = "/login.*" //Direct
Custom
Provide a custom implementation of the LoginResponseValidator
interface and override IsSuccessfulLogin
which receives ResponseWriterWrapper
and returns a bool
.
Default: nil
type MyCustomLoginResponseValidator struct {}
func (clrv MyCustomLoginResponseValidator) IsSuccessfulLogin(response perimeterx.ResponseWriterWrapper) bool {
// validation login
return false
}
SetCustomLoginResponseValidator(MyCustomLoginResponseValidator) // Builder
//Not available for JSON file
pxConfig["px_custom_login_response_validation"] = MyCustomLoginResponseValidator //Direct
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: false
SetAdditionalS2SActivityHeaderEnabled(true) // Builder
{"px_additional_s2s_activity_header_enabled": true} // JSON file
pxConfig["px_additional_s2s_activity_header_enabled"] = true //Direct
GraphQL
For those using GraphQL endpoints, it is possible to trigger server-to-server risk calls on particular operation types or names. Like the sensitive routes feature, a request that contains an operation of the configured type or name will trigger risk and client activity requests to HUMAN servers every time that operation is performed.
The risk and the client activity requests will contain a list of the one or more graphql operations, each including the name, type and if it's sensitive.
If an operation type (e.g., query
, mutation
, subscription
) is configured in px_sensitive_graphql_operation_types
, all GraphQL operations of that type will be treated as sensitive. If an operation name is configured in px_sensitive_graphql_operation_names
or px_sensitive_graphql_operation_names_regex
, all GraphQL operations with that name will be treated as sensitive.
This feature only applies to request's route that match the regex route configured in px_graphql_routes
.
If a list of keywords to be extracted is configured in px_graphql_keywords
, they will be extracted from query and operation names.
A custom function for extraction of keywords from queries can be configured for the enforcer using the px_extract_graphql_keywords
configuration. It will be called when extracting keywords from incoming graphql queries.
The configured keywords extraction function must have a signature complying with the CustomGraphqlKeywordsExtractor
type:
type CustomGraphqlKeywordsExtractor func(query string) []string
Example for custom keywords extractor:
func customGraphqlKeywordsExtractor(query string) []string {
re := regexp.MustCompile(`\b(field1|field2)\b`)
matches := re.FindAllString(query, -1)
return matches
}
SetCustomGraphqlKeywordsExtractor(customGraphqlKeywordsExtractor) // Builder
// Not available for JSON file
pxConfig["px_extract_graphql_keywords"] = customGraphqlKeywordsExtractor //Direct
Default Values:
px_graphql_enabled: true
px_graphql_routes: regexp.Compile(".*graphql.*")
px_sensitive_graphql_operation_types: Empty
px_sensitive_graphql_operation_names: Empty
px_sensitive_graphql_operation_names_regex: Empty
px_graphql_keywords: Empty
px_extract_graphql_keywords: Empty
//Builder
NewPXConfigBuilder(...).
SetGraphqlEnabled(true).
SetGraphqlRoutes([]string{"/graphql.*", "/gql.*"}).
SetSensitiveGraphqlOperationTypes([]string{"query","mutation"}).
SetSensitiveGraphqlOperationNames([]string{"LoginOperation", "AccountInfoQuery"}).
SetSensitiveGraphqlOperationNamesRegex([]string{"/.example.*"}).
SetGraphqlKeywords([]string{"keyword1","keyword2"}).
Build()
// JSON file
{
...
px_sensitive_graphql_operation_types: ["query","mutation"],
px_sensitive_graphql_operation_names: ["LoginOperation", "AccountInfoQuery"],
px_sensitive_graphql_operation_names_regex: ["/.example.*],
px_graphql_enabled: true,
px_graphql_routes: ["/graphql.*", "/gql.*"],
px_graphql_keywords: ["keyword1","keyword2"],
...
};
// Direct
pxConfig["px_graphql_enabled"] = true
pxConfig["px_graphql_routes"] = []string{"/graphql.*", "/gql.*"}
pxConfig["px_sensitive_graphql_operation_types"] = []string{"query","mutation"}
pxConfig["px_sensitive_graphql_operation_names"] = []string{"LoginOperation", "AccountInfoQuery"}
pxConfig["px_sensitive_graphql_operation_names_regex"] = []string{"/.example.*"}
pxConfig["px_graphql_keywords"]: []string{"keyword1","keyword2"}
Logger Auth Token
The token used to authenticate with HUMAN's enforcer logging services. This value is required for setting up the header-based logger feature as well as configuring the enforcer from the HUMAN Portal.
Default: ""
SetLoggerAuthToken("<LOGGER_AUTH_TOKEN>") // Builder
{"px_logger_auth_token": "<LOGGER_AUTH_TOKEN>"} // JSON file
pxConfig["px_logger_auth_token"] = "<LOGGER_AUTH_TOKEN>" //Direct
Remote Config Auth Token
The token used to authenticate the enforcer with the HUMAN remote configuration service. This value is required for configuring the enforcer from the HUMAN Portal.
Default: ""
SetRemoteConfigAuthToken("<REMOTE_CONFIG_AUTH_TOKEN>") // Builder
{"px_remote_config_auth_token": "<REMOTE_CONFIG_AUTH_TOKEN>"} // JSON file
pxConfig["px_remote_config_auth_token"] = "<REMOTE_CONFIG_AUTH_TOKEN>" //Direct
Remote Config Timeout
The amount of time, in milliseconds, to wait for a remote config update request.
Default: 5000
SetRemoteConfigTimeout(3000) // Builder
{"px_remote_config_timeout": 3000} // JSON file
pxConfig["px_remote_config_timeout"] = 3000 //Direct
Remote Config Max Age
The maximum length of time, in seconds, between requests to update the remote config.
Default: 600
SetRemoteConfigMaxAgeSeconds(300) // Builder
{"px_remote_config_max_age_seconds": 300} // JSON file
pxConfig["px_remote_config_max_age_seconds"] = 300 //Direct
Additional Activity Handler
The additional activity handler is a custom function passed to the enforcer. The enforcer runs this callback after sending page_requested
or block
activity to the collector, and before forwarding the request to the next step in the pipeline. A common use case of the additional activity handler is to set the score as a variable or header. Then the application can read the score and do what is defined within the application's logic.
The configured additional activity handler function must have a signature complying with the AdditionalActivityHandler
type:
type AdditionalActivityHandler func(ConfigParams, *PxContext, *http.Request)
Default: null
Example for additional activity handler:
func additionalActivityHandler(configParams perimeterx.ConfigParams, context *perimeterx.PxContext, request *http.Request) {
url := configParams.CollectorHost + "/internal"
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
_, clientErr := client.Do(req)
if clientErr != nil {
log.Fatal("Failed to send additional activity handler request, error :: ", clientErr)
}
}
SetAdditionalActivityHandler(additionalActivityHandler) // Builder
// Not available for JSON file
pxConfig["px_additional_activity_handler"] = additionalActivityHandler //Direct
Updated 20 days ago