{"id":22096109,"url":"https://github.com/HumanSecurity/perimeterx-php-sdk","last_synced_at":"2025-07-24T22:31:39.556Z","repository":{"id":9323062,"uuid":"60750664","full_name":"PerimeterX/perimeterx-php-sdk","owner":"PerimeterX","description":"PerimeterX PHP SDK","archived":false,"fork":false,"pushed_at":"2022-12-06T12:12:55.000Z","size":577,"stargazers_count":16,"open_issues_count":1,"forks_count":15,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-04-14T05:01:19.853Z","etag":null,"topics":["enforcer","perimeterx"],"latest_commit_sha":null,"homepage":"http://www.perimeterx.com","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PerimeterX.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-06-09T04:52:13.000Z","updated_at":"2024-01-12T18:08:23.000Z","dependencies_parsed_at":"2023-01-13T15:17:20.289Z","dependency_job_id":null,"html_url":"https://github.com/PerimeterX/perimeterx-php-sdk","commit_stats":null,"previous_names":[],"tags_count":69,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PerimeterX%2Fperimeterx-php-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PerimeterX%2Fperimeterx-php-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PerimeterX%2Fperimeterx-php-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PerimeterX%2Fperimeterx-php-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PerimeterX","download_url":"https://codeload.github.com/PerimeterX/perimeterx-php-sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227482495,"owners_count":17779968,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["enforcer","perimeterx"],"created_at":"2024-12-01T04:09:42.470Z","updated_at":"2025-07-24T22:31:33.845Z","avatar_url":"https://github.com/PerimeterX.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/PerimeterX/perimeterx-php-sdk.svg?branch=master)](https://travis-ci.org/PerimeterX/perimeterx-php-sdk)\n\n![image](https://storage.googleapis.com/perimeterx-logos/primary_logo_red_cropped.png)\n\n#\n\n# [PerimeterX](http://www.perimeterx.com) PHP SDK\n\n\u003e Latest stable version: [v3.10.2](https://packagist.org/packages/perimeterx/php-sdk#3.10.1)\n\n## Table of Contents\n\n-   [Usage](#usage)\n\n*   [Dependencies](#dependencies)\n*   [Installation](#installation)\n*   [Basic Usage Example](#basic-usage)\n\n-   [Upgrading](#upgrade)\n-   [Configuration](#configuration)\n\n*   [Blocking Score](#blocking-score)\n*   [Extracting Recomended Action](#block-action)\n*   [Custom Block Page](#custom-block-page)\n*   [Custom Block Action](#custom-block)\n*   [Extracting Real IP Address](#real-ip)\n*   [Custom URI](#custom-uri)\n*   [Filter Sensitive Headers](#sensitive-headers)\n*   [Sensitive Route](#sensitive-routes)\n*   [API Timeouts](#api-timeout)\n*   [Activities API Timeouts](#activities-api-timeout)\n*   [First Party](#first-party)\n*   [First Party for Code Defender](#first-party-code-defender)\n*   [Send Page Activities](#send-page-activities)\n*   [Additional Page Activity Handler](#additional-page-activity-handler)\n*   [Data-Enrichment](#data-enrichment)\n*   [Enrich Custom Params](#enrich-custom-params)\n*   [Login Credentials Extraction](#login-credentials-extraction)\n*   [Additional S2S Activity](#additional-s2s-activity)\n*   [Logging](#logging)\n*   [Module Mode](#module-mode)\n*   [Debug Mode](#debug-mode)\n*   [Guzzle Client Handler](#guzzle-client-handler)\n*   [Custom Block URL](#custom-block-url)\n*   [Defer Activities Sending](#defer-activities)\n*   [Advanced Blocking Response Flag](#enable-abr)\n*   [Return Response Flag](#return-response)\n*   [Test Block Flow on Monitoring Mode](#bypass-monitor-header)\n\n-   [Advanced Blocking Response](#advanced-blocking-response)\n-   [Additional Information](#additional-information)\n-   [Contributing](#contributing)\n\n*   [Tests](#tests)\n\n\u003ca name=\"Usage\"\u003e\u003c/a\u003e\n\n## \u003ca name=\"dependencies\"\u003e\u003c/a\u003e Dependencies\n\n-   [v5.6 \u003c= PHP \u003c= v7.0.15](http://php.net/downloads.php)\n\n## \u003ca name=\"installation\"\u003e\u003c/a\u003e Installation\n\nInstallation can be done using Composer.\n\n```sh\n$ composer require perimeterx/php-sdk\n```\n\nIt can also be done by downloading the sources for this repository, and running `composer install`.\n\n### \u003ca name=\"basic-usage\"\u003e\u003c/a\u003e Basic Usage Example\n\n```php\nuse Perimeterx\\Perimeterx;\n\n$perimeterxConfig = [\n    'app_id' =\u003e 'APP_ID',\n    'cookie_key' =\u003e 'COOKIE_SECRET',\n    'auth_token' =\u003e 'AUTH_TOKEN',\n    'blocking_score' =\u003e 60,\n    'module_mode' =\u003e Perimeterx::$ACTIVE_MODE\n];\n\n/* Obtain PerimeterX SDK instance */\n$px = Perimeterx::Instance($perimeterxConfig);\n\n/* run verify at the beginning of a page request */\n$px-\u003epxVerify();\n```\n\n## \u003ca name=\"upgrade\"\u003e\u003c/a\u003e Upgrading\n\nDownload the new version from packagist.\n\nFor more information contact [PerimeterX Support](support@perimeterx.com).\n## \u003ca name=\"configuration\"\u003e\u003c/a\u003e Configuration Options\n\n### Configuring Required Parameters\n\nConfiguration options are set on the `$perimeterxConfig` variable.\n\n#### Required parameters:\n\n-   app_id\n-   cookie_key\n-   auth_token\n-   module_mode\n\nAll parameters are obtainable via the PerimeterX Portal. (Applications and Policies pages)\n\n#### \u003ca name=\"blocking-score\"\u003e\u003c/a\u003e Changing the Minimum Score for Blocking\n\n**Default blocking value:** 100\n\n```php\n$perimeterxConfig = [\n\t..\n    'blocking_score' =\u003e 75\n    ..\n]\n```\n\n#### \u003ca name=\"custom-block\"\u003e\u003c/a\u003e Custom Blocking Actions\n\nIn order to customize the action performed on a valid block value, use the 'custom_block_handler' option, and provide a user-defined function.\n\nThe custom handler should contain the action to be taken, when a visitor receives a score higher than the 'blocking_score' value.\nCommon customization options are presenting of a reCAPTCHA, or supplying a custom branded block page.\n\n**Default block behaviour:** return an HTTP status code of 403 and serve the PerimeterX block page.\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_block_handler'] = function ($pxCtx)\n{\n    $block_score = $pxCtx-\u003egetScore();\n    $block_uuid = $pxCtx-\u003egetUuid();\n\n    // user defined logic goes here\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n###### Examples\n\n**Serving a Custom HTML Page**\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_block_handler'] = function ($pxCtx)\n{\n    $block_score = $pxCtx-\u003egetScore();\n    $block_uuid = $pxCtx-\u003egetUuid();\n    $full_url = $pxCtx-\u003egetFullUrl();\n\n    $html = '\u003cdiv\u003eAccess to ' . $full_url . ' has been blocked.\u003c/div\u003e ' +\n                  '\u003cdiv\u003eBlock reference - ' . $block_uuid . ' \u003c/div\u003e ' +\n                  '\u003cdiv\u003eBlock score - ' . $block_score . '\u003c/div\u003e';\n\n    //echo $html;\n    header(\"Status: 403\");\n    die();\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n## \u003ca name=\"custom-block-page\"\u003e\u003c/a\u003e Customizing Default Block Pages\n\n**Custom logo insertion**\nAdding a custom logo to the blocking page is by providing the pxConfig a key `custom_logo` , the logo will be displayed at the top div of the the block page\nThe logo's `max-heigh` property would be 150px and width would be set to `auto`\n\nThe key `custom_logo` expects a valid URL address such as `https://s.perimeterx.net/logo.png`\n\nExample below:\n\n```php\n$perimeterxConfig = [\n    'app_id' =\u003e 'APP_ID',\n    'cookie_key' =\u003e 'COOKIE_SECRET',\n    'auth_token' =\u003e 'AUTH_TOKEN',\n    'blocking_score' =\u003e 60,\n    'custom_logo' =\u003e 'LOGO_URL'\n];\n```\n\n** Custom JS/CSS **\n\nThe block page can be modified with a custom CSS by adding to the `pxConfig` the key `css_ref` and providing a valid URL to the css\nIn addition there is also the option to add a custom JS file by adding `js_ref` key to the `pxConfig` and providing the JS file that will be loaded with the block page, this key also expects a valid URL\n\nOn both cases if the URL is not a valid format an exception will be thrown\n\nExample below:\n\n```php\n$perimeterxConfig = [\n    'app_id' =\u003e 'APP_ID',\n    'cookie_key' =\u003e 'COOKIE_SECRET',\n    'auth_token' =\u003e 'AUTH_TOKEN',\n    'blocking_score' =\u003e 60,\n    'css_ref' =\u003e 'CSS_URL',\n    'js_ref' =\u003e 'JS_URL'\n];\n```\n\nSide notes: Custom logo/js/css can be added together\n\n**No Blocking, Monitor Only**\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_block_handler'] = function ($pxCtx)\n    $block_score = $pxCtx-\u003egetScore();\n    $block_uuid = $pxCtx-\u003egetUuid();\n    $full_url = $pxCtx-\u003egetFullUrl();\n\n    // user defined logic goes here\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n\u003ca name=\"block-action\"\u003e\u003c/a\u003e**Extracting Recomended Action**\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_block_handler'] = function ($pxCtx) {\n    $block_score = $pxCtx-\u003egetScore();\n    $block_uuid = $pxCtx-\u003egetUuid();\n    $action = $pxCtx-\u003egetBlockAction();\n\n    /* user defined logic comes here */\n    error_log('px score for user is ' . $block_score);\n    error_log('px recommended action for user is ' . $action);\n    error_log('px page uuid is ' . $block_uuid);\n\n    switch ($action) {\n        case \"block\":\n            log(\"do block\");\n            break;\n        case \"captcha\":\n            log(\"do captcha\");\n            break;\n        default:\n            log(\"unknown action\");\n        }\n    }\n```\n\n#### \u003ca name=\"module-mode\"\u003e\u003c/a\u003e Module Mode\n\n**Default mode:** `Perimeterx::$MONITOR_MODE`\n\n**Possible Values:**\n\n-   `Perimeterx::$ACTIVE_MODE` - Module blocks users crossing the predefined block threshold. Server-to-server requests are sent synchronously.\n-   `Perimeterx::$MONITOR_MODE` - Module does not block users crossing the predefined block threshold. The pxCustomBlockHandler function will be eval'd in case one is supplied, upon crossing the defined block threshold.\n\n```php\n$perimeterxConfig = [\n\t..\n    'module_mode' =\u003e Perimeterx::$ACTIVE_MODE\n    ..\n]\n```\n\n#### \u003ca name=\"real-ip\"\u003e\u003c/a\u003eExtracting the Real User IP Address\n\n\u003e Note: IP extraction, according to your network setup, is very important. It is common to have a load balancer/proxy on top of your applications, in which case the PerimeterX module will send the system's internal IP as the user's. In order to properly perform processing and detection on server-to-server calls, PerimeterX module needs the real user's IP.\n\nThe user's IP can be passed to the PerimeterX module using a custom user defined function on the $perimeterxConfig variable, or by passing a list of headers to extract the real IP from, ordered by priority.\n\n**Default with no predefined header:** `$_SERVER['REMOTE_ADDR']`\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_user_ip'] = function ($pxCtx)\n{\n    $headers = getallheaders();\n\n    /* using a socket ip */\n    $ip = $_SERVER['REMOTE_ADDR'];\n\n    /* using an ip from a x-forwarded-for header */\n    $xff = explode(\",\", $headers['X-Forwarded-For']);\n    $ip = $xff[count($xff)-1];\n\n    /* using an ip from a custom header */\n    $ip = $headers['X-REAL-CLIENT-IP'];\n\n    return $ip;\n};\n\n$perimeterxConfig = [\n\t..\n    'ip_headers' =\u003e ['X-TRUE-IP', 'X-Forwarded-For']\n    ..\n]\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n#### \u003ca name=\"custom-uri\"\u003e\u003c/a\u003eCustom URI\n\nThe URI can be returned to the PerimeterX module, using a custom user function, defined on the $perimeterxConfig variable.\n\n**Default:** `$_SERVER['REQUEST_URI']`\n\n```php\n/**\n * @param \\Perimeterx\\PerimeterxContext $pxCtx\n */\n$perimeterxConfig['custom_uri'] = function ($pxCtx)\n{\n    return $_SERVER['HTTP_X_CUSTOM_URI'];\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n#### \u003ca name=\"sensitive-headers\"\u003e\u003c/a\u003e Filter sensitive headers\n\nA list of sensitive headers can be configured to prevent specific headers from being sent to PerimeterX servers (lower case header names). Filtering cookie headers for privacy is set by default, and can be overridden on the $perimeterxConfig variable.\n\n**Default: cookie, cookies**\n\n```php\n$perimeterxConfig = [\n\t..\n    'sensitive_headers' =\u003e ['cookie', 'cookies', 'secret-header']\n    ..\n]\n```\n\n#### \u003ca name=\"sensitive-routes\"\u003e\u003c/a\u003e Sensitive Routes\n\nList of routes prefix. The Perimeterx module will always match request uri by this prefix list and if match was found will create a server-to-server call for, even if the cookie score is low and valid.\n\n**Default: None**\n\n```php\n$perimeterxConfig = [\n\t..\n    'sensitive_routes' =\u003e ['/login', '/user/profile']\n    ..\n]\n```\n\n#### \u003ca name=\"api-timeout\"\u003e\u003c/a\u003eAPI Timeouts\n\n\u003e Note: Controls the timeouts for PerimeterX requests. The API is called when a Risk Cookie does not exist, or is expired or invalid.\n\nThe API Timeout, in seconds (float), to wait for the PerimeterX server API response.\n\n**Default:** 1\n\n```php\n$perimeterxConfig = [\n\t..\n    'api_timeout' =\u003e 2\n    ..\n]\n```\n\nThe API Connection Timeout, in seconds (float), to wait for the connection to the PerimeterX server API.\n\n**Default:** 1\n\n```php\n$perimeterxConfig = [\n    ..\n    'api_connect_timeout' =\u003e 2\n    ..\n]\n```\n\n#### \u003ca name=\"activities-api-timeout\"\u003e\u003c/a\u003eActivities API Timeouts\n\n\u003e Note: Controls the timeouts for PerimeterX activities requests.\n\nThe activities API Timeout, in seconds (float), to wait for the PerimeterX server API response.\n\n**Default:** 1\n\n```php\n$perimeterxConfig = [\n    ..\n    'activities_timeout' =\u003e 2\n    ..\n]\n```\n\nThe activities API Connection Timeout, in seconds (float), to wait for the connection to the PerimeterX server API.\n\n**Default:** 1\n\n```php\n$perimeterxConfig = [\n    ..\n    'activities_connect_timeout' =\u003e 2\n    ..\n]\n```\n\n#### \u003ca name=\"first-party\"\u003e\u003c/a\u003eFirst Party\n\nA boolean flag to enable/disable first party mode.\n\n**Default:** true\n\n```php\n$perimeterxConfig = [\n    ..\n    'px_first_party_enabled' =\u003e false\n    ..\n]\n```\n\n#### \u003ca name=\"first-party-code-defender\"\u003e\u003c/a\u003eFirst Party for Code Defender\n\nA boolean flag to enable/disable first party mode for Code Defender.\n\n**Default:** false\n\n```php\n$perimeterxConfig = [\n    ..\n    'px_cd_first_party_enabled' =\u003e true\n    ..\n]\n```\n\n#### \u003ca name=\"send-page-activities\"\u003e\u003c/a\u003e Send Page Activities\n\nA boolean flag to enable or disable sending of activities and metrics to\nPerimeterX on each page request. Enabling this feature will provide data\nthat populates the PerimeterX portal with valuable information, such as the\namount of requests blocked and additional API usage statistics.\n\n**Default:** false\n\n```php\n$perimeterxConfig = [\n\t..\n    'send_page_activities' =\u003e true\n    ..\n]\n```\n\n#### \u003ca name=\"additional-page-activity-handler\"\u003e\u003c/a\u003e Additional Page Activity Handler\n\nAdding an additional activity handler is done by setting 'additional_activity_handler' with a user defined function on the '$perimeterxConfig' variable. The 'additional_activity_handler' function will be executed before sending the data to the PerimeterX portal.\n\n**Default:** Only send activity to PerimeterX as controlled by '$perimeterxConfig'.\n\n```php\n/**\n * @param string            $activityType\n * @param PerimeterxContext $pxCtx\n * @param array             $details\n */\n$perimeterxConfig['additional_activity_handler'] = function ($activityType, $pxCtx, $details)\n{\n    // user defined logic comes here\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n###### Additional Activity Handler Usage Examples\n\n**Log Activity**\n\n```php\n/**\n * @param string            $activityType\n * @param PerimeterxContext $pxCtx\n * @param array             $details\n */\n$perimeterxConfig['additional_activity_handler'] = function ($activityType, $pxCtx, $details) use ($logger)\n{\n    if ($activityType === 'block') {\n        $logger-\u003ewarning('PerimeterX {activityType} details', ['activityType' =\u003e $activityType, 'details' =\u003e $details]);\n    } else {\n        $logger-\u003einfo('PerimeterX {activityType} details', ['activityType' =\u003e $activityType, 'details' =\u003e $details]);\n    }\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n**Send Activity to statsd**\n\n```php\n/**\n * @param string            $activityType\n * @param PerimeterxContext $pxCtx\n * @param array             $details\n */\n$perimeterxConfig['additional_activity_handler'] = function ($activityType, $pxCtx, $details) use ($statsd)\n{\n    $statsd-\u003eincrement('perimeterx_activity.' . $activityType);\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n#### \u003ca name=\"data-enrichment\"\u003e\u003c/a\u003e Data-Enrichment\n\nUser can use the additional activity handler to retrieve information for the request using the data-enrichment object.\nfirst, validate the data enrichment object is verified, then you can access it's properties.\n\n**Default:** false\n\n```php\n/**\n * @param string            $activityType\n * @param PerimeterxContext $pxCtx\n * @param array             $details\n */\n$perimeterxConfig['additional_activity_handler'] = function ($activityType, $pxCtx, $details) use ($logger)\n{\n    if($pxCtx-\u003egetDataEnrichmentVerified()) {\n    \t$pxde = $pxCtx-\u003egetDataEnrichment();\n        if($pxde-\u003ef_type == 'blacklist') {\n        \t$logger-\u003einfo('Filtered request with id: {$pxde-\u003ef_id} at: {$pxde-\u003etimestamp}');\n        }\n    }\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n#### \u003ca name=\"enrich-custom-params\"\u003e\u003c/a\u003e Enrich Custom Params\n\nWith the `enrich_custom_params` function you can add up to 10 custom parameters to be sent back to PerimeterX servers.\nWhen set, the function is called before seting the payload on every request to PerimetrX servers. The parameters should be passed according to the correct order (1-10).\n\n**Default:** not set\n\n```php\n/**\n * @param array             $customParamsArray\n */\n$perimeterxConfig['enrich_custom_params'] = function ($customParamsArray)\n{\n    // user defined logic comes here\n};\n\n$px = Perimeterx::Instance($perimeterxConfig);\n$px-\u003epxVerify();\n```\n\n###### Enrich Custom Params Usage Examples\n\n```php\n/**\n * @param array             $customParamsArray\n */\n$perimeterxConfig['enrich_custom_params'] = function ($customParamsArray)\n{\n    $customParamsArray['custom_param1'] = \"UserId\";\n    $customParamsArray['custom_param2'] = \"SesionId\";\n    return $customParamsArray;\n};\n```\n\n### \u003ca name=\"login-credentials-extraction\"\u003e\u003c/a\u003e Login Credentials Extraction\n\nThis feature extracts credentials (hashed username and password) from requests and sends them to PerimeterX 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 `px_login_credentials_extraction_enabled` and `px_login_credentials_extraction` properties on the `$perimeterxConfig` array.\n\nIf credentials are found to be compromised, the field `px-compromised-credentials` will be added to the `$_REQUEST` object with the value `\"1\"`. You may configure the name of this field with the `px_compromised_credentials_header` configuration.\n\n**Default:**\n\npx_login_credentials_extraction_enabled: false\n\npx_login_credentials_extraction: []\n\npx_compromised_credentials_header: \"px-compromised-credentials\"\n\n```php\n$perimeterxConfig['px_compromised_credentials_header'] = 'px-comp-creds';\n$perimeterxConfig['px_login_credentials_extraction_enabled'] = true;\n$perimeterxConfig['px_login_credentials_extraction'] = [\n    [\n        \"path\" =\u003e \"/login\",           // login path, automatically added to sensitive routes\n        \"method\" =\u003e \"POST\",           // supported methods: POST\n        \"sent_through\" =\u003e \"body\",     // supported sent_throughs: body, header, query-param\n        \"pass_field\" =\u003e \"password\",   // name of the password field in the request\n        \"user_field\" =\u003e \"username\"    // name of the username field in the request\n    ], [ ... ], ...\n]\n```\n\nIt is also possible to define a custom callback to extract the username and password. The function should return an associative\narray with the keys `user` and `pass`. If extraction is unsuccessful, the function should return `null`.\n\n```php\n$perimeterxConfig['px_enable_login_creds_extraction'] = true;\n$perimeterxConfig['px_login_creds_extraction'] = [\n    [\n        \"path\" =\u003e \"/login\",                 // login path\n        \"method\" =\u003e \"POST\",                 // supported methods: POST\n        \"callback_name\" =\u003e \"extractCreds\"   // name of custom extraction callback\n    ], ...\n];\n\nfunction extractCreds() {\n    // custom implementation resulting in $username and $password\n    if (empty($username) || empty($password)) {\n        return null;\n    }\n    return [\n        \"user\" =\u003e $username,\n        \"pass\" =\u003e $password\n    ];\n}\n```\n\n### \u003ca name=\"additional-s2s-activity\"\u003e\u003c/a\u003e Additional S2S Activity\n\nTo enhance detection on login credentials extraction endpoints, the following additional information is sent to PerimeterX\nvia an `additional_s2s` activity:\n\n* __Response Code__ - The numerical HTTP status code of the response. This is sent automatically.\n* __Login Success__ - A boolean indicating whether the login completed successfully. See the options listed below for how to provide this data.\n* __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`.\n#### Login Success Reporting\n\nThere are a number of different possible ways to report the success or failure of the login attempt. If left empty, the\nlogin successful status will always be reported as `false`.\n\n**Default**: Empty\n\n```php\n$perimeterxConfig['px_login_successful_reporting_method'] = 'status';\n```\n\n__Status__\n\nProvide a status or array of statuses that represent a successful login. If a response's status code matches the provided\nvalue or one of the values in the provided array, the login successful status is set to `true`. Otherwise, it's set to `false`.\n\n\u003e Note: To define a range of statuses, use the `custom` reporting method.\n\n**Default Values**\n\npx_login_successful_status: 200\n\n```php\n$perimeterxConfig['px_login_successful_reporting_method'] = 'status';\n$perimeterxConfig['px_login_successful_status'] = [200, 202]; // number or array of numbers\n```\n\n__Header__\n\nProvide a header name and value. If the header exists on the response (accessed via the `headers_list()` function ) 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`.\n\n**Default Values**\n\npx_login_successful_header_name: x-px-login-successful\n\npx_login_successful_header_value: 1\n\n```php\n$perimeterxConfig['px_login_successful_reporting_method'] = 'header';\n$perimeterxConfig['px_login_successful_header_name'] = 'login-successful';\n$perimeterxConfig['px_login_successful_header_value'] = 'true';\n```\n\n__Custom__\n\nProvide a custom callback that returns a boolean indicating if the login was successful. The value of the configuration field can be either an anonymous function or the name of the defined function as a string.\n\n**Default Values**\n\npx_login_successful_custom_callback: null\n\n```php\n$perimeterxConfig['px_login_successful_reporting_method'] = 'custom';\n\n// anonymous callback function\n$perimeterxConfig['px_login_successful_custom_callback'] = function() {\n    // ...\n    return $isLoginSuccessful;\n};\n\n// name of defined function as string\n$perimeterxConfig['px_login_successful_custom_callback'] = 'isLoginSuccessfulCallback';\n\nfunction isLoginSuccessfulCallback() {\n    // ...\n    return $isLoginSuccessful;\n}\n```\n\n#### Raw Username\n\nWhen enabled, the raw username used for logins on login credentials extraction endpoints will be reported to PerimeterX\nif (1) the credentials were identified as compromised, and (2) the login was successful as reported via the property above.\n\n**Default**: false\n\n```php\n$perimeterxConfig['px_send_raw_username_on_additional_s2s_activity'] = true;\n```\n\n#### Manually Sending Additional S2S Activity\n\nBy default, this `additional_s2s` activity is sent automatically. If it is preferable to send this activity manually,\nit's possible to disable automatic sending by configuring the value of `px_automatic_additional_s2s_activity_enabled` to `false`.\n\n**Default Value*: true\n\n```php\n$perimeterxConfig['px_automatic_additional_s2s_activity_enabled'] = false;\n```\n\n\nThe activity can then be sent manually by invoking the function `$px-\u003epxSendAdditionalS2SActivity()`, which accepts the following parameters:\n\n| Parameter Name | Type | Required | Default Value |\n| :--            | :--  | :--      | :-- |\n| `$responseStatusCode` | int | yes | n/a |\n| `$wasLoginSuccessful` | bool | no | null |\n\n__Example Usage__\n\n```php\n// $px is an instance of the Perimeterx class\n\nfunction handleLogin() {\n    // login flow resulting in boolean $isLoginSuccessful\n    $px-\u003epxSendAdditionalS2SActivity($isLoginSuccessful ? 200 : 401, $isLoginSuccessful);\n}\n```\n\nIf further flexibility is needed, a JSON representation of the `additional_s2s` activity can be added to the `$_REQUEST` array. This activity can then be sent to another server if needed, parsed, modified, and sent via XHR POST as a JSON to PerimeterX. To do this, disable automatic sending and enable the additional activity header configuration.\n\n**Default Value**\n\npx_additional_s2s_activity_header_enabled: false\n\n```php\n$perimeterxConfig['px_automatic_additional_s2s_activity_enabled'] = false;\n$perimeterxConfig['px_additional_s2s_activity_header_enabled'] = true;\n```\n\nThe activity payload and URL destination will then be available by accessing `$_REQUEST['px-additional-activity']` and `$_REQUEST['px-additional-activity-url']`, respectively.\n\n```php\nfunction handleLogin() {\n    // custom flow resulting in boolean $isLoginSuccessful\n    $activity = json_decode($_REQUEST['px-additional-activity'], true);\n    $activity['additional']['http_status_code'] = http_status_code();\n    $activity['additional']['login_successful'] = $isLoginSuccessful;\n\n    if ($isLoginSuccessful \u0026\u0026 $activity['additional']['credentials_compromised']) {\n        $activity['additional']['raw_username'] = $_REQUEST['username'];\n    }\n\n    $url = $_REQUEST['px-additional-activity-url'];\n    $headers = [\n        'Content-Type: application/json',\n        'Authorization: Bearer ' . $_ENV['PX_AUTH_TOKEN']\n    ];\n    $body = json_encode($activity);\n\n    sendPostRequest($url, $headers, $body);\n}\n\nfunction sendPostRequest($url, $headers, $body) {\n    $curl = curl_init($url);\n    curl_setopt($curl, CURLOPT_URL, $url);\n    curl_setopt($curl, CURLOPT_POST, true);\n    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);\n    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);\n    curl_setopt($curl, CURLOPT_POSTFIELDS, $body);\n    curl_exec($curl);\n}\n```\n\n#### \u003ca name=\"logging\"\u003e\u003c/a\u003e Logging\n\nLog messages via an implementation of `\\Psr\\Log\\LoggerInterface` (see [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) for full interface specification). By default, an instance of `\\Perimeterx\\PerimeterxLogger` is used which will log all message via PHP's `error_log` function.\n\n**Default:** `\\Perimeterx\\PerimeterxLogger` instance\n\n```php\n$perimeterxConfig = [\n    ..\n    'logger' =\u003e new \\My\\Psr\\Log\\ConcreteLogger()\n    ..\n]\n```\n\n#### \u003ca name=\"debug-mode\"\u003e\u003c/a\u003e Debug Mode\n\nEnables debug logging mode.\n\n**Default:** false\n\n```php\n$perimeterxConfig = [\n\t..\n    'debug_mode' =\u003e true\n    ..\n]\n```\n\nOnce enabled, debug messages coming out from PerimeterX should be in the following template:\n\n`[PerimeterX - DEBUG][APP_ID] - MESSAGE` - for debug messages\n\n`[PerimeterX - ERROR][APP_ID] - MESSAGE` - for error messages\n\nAn example\nlog for an high score cookie:\n\n```\n[Mon Dec  4 14:03:50 2017] [PerimeterX - DEBUG][APP_ID] -Starting request verification\n[Mon Dec  4 14:03:50 2017] [PerimeterX - DEBUG][APP_ID] -Request context created successfully\n[Mon Dec  4 14:03:50 2017] [PerimeterX - DEBUG][APP_ID] -No Captcha cookie present on the request\n[Mon Dec  4 14:03:50 2017] [PerimeterX - DEBUG][APP_ID] -Cookie V3 found, Evaluating\n[Mon Dec  4 14:03:50 2017] [PerimeterX - DEBUG][APP_ID] -Cookie evaluation ended successfully, risk score: 100\n[Mon Dec  4 14:03:51 2017] [PerimeterX - DEBUG][APP_ID] -Enforcing action: Captcha page is served\n```\n\n#### \u003ca name=\"guzzle-client-handler\"\u003e\u003c/a\u003e Guzzle Client Handler\n\nAllows setting a handler to the Guzzle client object.\n\n**Default:** false\n\n```php\n\n$container = [];\n$history = Middleware::history($container);\n$handler = HandlerStack::create();\n$handler-\u003epush($history);\n\n\n$perimeterxConfig = [\n    ..\n    'guzzle_handler' =\u003e $handler\n    ..\n]\n```\n\n#### \u003ca name=\"custom-block-url\"\u003e\u003c/a\u003e Custom Block URL\n\nYou can customize the block page to meet branding and message requirements by specifying the URL of the block page HTML file.\nThe enforcer will redirect to the block page defined in the `custom_block_url` variable. The defined block page will display a 307 (Temporary Redirect) HTTP Response Code.\n\n**Default:** not set\n\n```php\n\n$perimeterxConfig = [\n    ..\n    'custom_block_url' =\u003e '/block.html'\n    ..\n]\n```\n\n#### \u003ca name=\"enable-abr\"\u003e\u003c/a\u003e Advanced Blocking Response Flag\n\nEnables/disables the Advanced Blocking Response functionality.\n\n**Default:** false\n\n```php\n$perimeterxConfig = [\n    ..\n    'enable_json_response' =\u003e true\n    ..\n]\n```\n\n#### \u003ca name=\"return-response\"\u003e\u003c/a\u003e Return Response Flag\n\nEnables/disables the ability to return the response back (useful for frameworks like Symfony) instead of running `die()`.\n\n**Default:** false\n\n```php\n$perimeterxConfig = [\n    ..\n    'return_response' =\u003e true\n    ..\n]\n```\n\n#### \u003ca name=\"defer-activities\"\u003e\u003c/a\u003e Defer Activities Sending\n\nSpecifies if sending page activities should be deferred until shutdown or not.\n\n**Default:** true\n\n```php\n$perimeterxConfig = [\n    ..\n    'defer_activities' =\u003e false\n    ..\n]\n```\n\n\n#### \u003ca name=\"bypass-monitor-header\"\u003e\u003c/a\u003e Test Block Flow on Monitoring Mode\n\nAllows you to test an enforcer’s blocking flow while you are still in Monitor Mode.\n\nWhen the header name is set (eg. `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.\nTo stay in Monitor Mode, set the header value to `0`.\n\nThe Header name is configurable using the `bypass_monitor_header` property.\n\n**Default:** not set\n\n```php\n$perimeterxConfig = [\n    ..\n    'bypass_monitor_header' =\u003e 'x-px-block'\n    ..\n]\n```\n\n## \u003ca name=\"advanced-blocking-response\"\u003e\u003c/a\u003e Advanced Blocking Response\n\nIn 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 continaing 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:\n\n```javascript\n{\n    \"appId\": String,\n    \"jsClientSrc\": String,\n    \"firstPartyEnabled\": Boolean,\n    \"vid\": String,\n    \"uuid\": String,\n    \"hostUrl\": String,\n    \"blockScript\": String\n}\n```\n\nOnce 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.\n\nIn 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 successfullt solved. \u003cbr/\u003e An example of using the `_pxOnCaptchaSuccess` callback is as follows:\n\n```javascript\nwindow._pxOnCaptchaSuccess = function (isValid) {\n    if (isValid) {\n        alert('yay');\n    } else {\n        alert('nay');\n    }\n};\n```\n\nTo enable Advanced Blocking Response see the [Advanced Blocking Response Flag](#enable-abr) section.\n\nFor details on how to create a custom Captcha page, refer to the [documentation](https://docs.perimeterx.com/pxconsole/docs/customize-challenge-page)\n\n## \u003ca name=“additional-information”\u003e\u003c/a\u003e Additional Information\n\n### URI Delimiters\n\nPerimeterX processes URI paths with general- and sub-delimiters according to RFC 3986. General delimiters (e.g., `?`, `#`) are used to separate parts of the URI. Sub-delimiters (e.g., `$`, `\u0026`) are not used to split the URI as they are considered valid characters in the URI path.\n\n## \u003ca name=\"contributing\"\u003e\u003c/a\u003e Contributing\n\nThe following steps are welcome when contributing to our project.\n\n### Fork/Clone\n\nFirst and foremost, [Create a fork](https://guides.github.com/activities/forking/) of the repository, and clone it locally.\nCreate a branch on your fork, preferably using a self descriptive branch name.\n\n### Code/Run\n\nHelp improve our project by implementing missing features, adding capabilites or fixing bugs.\n\nTo run the code, simply follow the steps in the [installation guide](#installation). Grab the keys from the PerimeterX Portal, and try refreshing your page several times continously. If no default behaviours have been overriden, you should see the PerimeterX block page. Solve the CAPTCHA to clean yourself and start fresh again.\n\nFeel free to check out the [Example App](https://github.com/PerimeterX/perimeterx-php-sdk/blob/master/examples/integration-example.php), to have a feel of the project.\n\n### \u003ca name=\"tests\"\u003e\u003c/a\u003eTest\n\n\u003e Tests for this project are written using PHPUnit.\n\n**Dont forget to test**. The project relies heavily on tests, thus ensuring each user has the same experience, and no new features break the code.\nBefore you create any pull request, make sure your project has passed all tests, and if any new features require it, write your own.\n\nTo run any of the tests in the available suite, first open the `bootstrap.php.dist` file, and change the values according to the in-file insturctions. Then, rename the `bootstrap.php.dist` to `bootstrap.php`.\nFinally, run the `phpunit tests/PerimeterxCookieValidatorTest` command to run all tests, or `phpunit \u003ctestName\u003e` to execute a specific test (e.g. `phpunit PerimeterxCookieTest`)\n\nTo run coverage tests, run `phpunit --coverage-html tests/coverage`. This will create a directory tests/coverage with an html coverage for inspection.\n\n### Pull Request\n\nAfter you have completed the process, create a pull request to the Upstream repository. Please provide a complete and thorough description, explaining the changes. Remember this code has to be read by our maintainers, so keep it simple, smart and accurate.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHumanSecurity%2Fperimeterx-php-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHumanSecurity%2Fperimeterx-php-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHumanSecurity%2Fperimeterx-php-sdk/lists"}