> This page is for Applications Protection.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.humansecurity.com/llms.txt.

# How to integrate the SDK in your application

#### v1.x

This document contains installation instructions for the following mobile frameworks:

## Swift

### Supported iOS Versions

HUMAN supports iOS version 8 and higher.

### Introduction

The HUMAN iOS SDK works by constantly profiling and evaluating device behavior to ensure that the connections to your mobile APIs and services are genuine.

This process is complex and detailed yet only requires initializing a context to manage a set of secure HTTP headers which are added to all HTTP and HTTPS requests made by the mobile application to the origin server. These HTTP headers are refreshed on a regular basis by the HUMAN Manager (context) as it is profiling the end-user’s mobile device.

The HUMAN iOS SDK works well with popular HTTP request libraries for iOS including Alamofire.

### Prerequisites

The following are required to install the HUMAN iOS SDK:

* Administrative access to the HUMAN Portal to:
  * Retrieve the HUMAN application ID.
  * Set the token expiration and validity.
* An active HUMAN Enforcer.

### Integration

**Adding the iOS SDK to your project**

1. Add the iOS SDK Binary to Your Project with:

[https://github.com/PerimeterX/px-iOS-Framework](https://github.com/PerimeterX/px-iOS-Framework) (the official\
repository for hosting the iOS SDK). The repository can be integrated with CocoaPods or Carthage.

### CocoaPods

Add `pod 'PerimeterX'` to your\
[Podfile](https://guides.cocoapods.org/syntax/podfile.html).

```none
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your App Name>' do
    pod 'PerimeterX'
end
```

You can now run `pod update` and once completed don’t forget to close and reopen your Xcode workspace.

### Carthage

Add the following to the app's Cartfile:

```none
`binary "https://raw.githubusercontent.com/PerimeterX/px-iOS-Framework/master/PerimeterX.json"`
```

Then run

```none
`carthage update --platform iOS`
```

2. Once the binary is added to your project, resync the build files to ensure the package is downloaded.
3. The SDK is now installed, and there should not be any build errors when compiling your application.

### Adding the Manager Object

1. In your *AppDelegate.swift* file import the PerimeterX library.\
   `import PerimeterX`
2. In your *AppDelegate.swift* file, add the *PXManagerDelegate*\
   extension using the example below.

```none
extension AppDelegate:PXManagerDelegate {
    func managerReady(_ httpHeaders: [AnyHashable : Any]!) {
        print("PerimeterX - managerReady: \(httpHeaders)")
    }

    func newHeaders(_ httpHeaders: [AnyHashable : Any]!) {
        print("PerimeterX - new headers: \(httpHeaders)")
    }
}
```

* When initializing the *PXManagerDelegate* instance the *managerReady* is called when the first set of PerimeterX HTTP headers are available.
* Setting the *newHeaders* is required to ensures that the *PXManagerDelegate* will notify the application that a refresh to the HTTP headers occurred. This is based on the token validity time set in the HUMAN portal.
* Action in the *newHeaders* method is optional. (reference the code example above).

### Initializing the Manager

In your main application function in *AppDelegate.swift* you must now initialize the *PXManager* object inside the *didFinishLaunchingWithOptions* handler:

```none
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // PerimeterX SDK should start here
    if let pxmanager = PXManager.sharedInstance() {
        pxmanager.delegate = self
        pxmanager.start(with: "PX12345678") //Takes your PerimeterX Application ID
    }

    return true
}
```

### Adding the PerimeterX HTTP Headers to the HTTP Requests

1. Once the Manager is initialized, add PerimeterX HTTP Headers to your network manager headers.\
   You are now set to start your requests.
2. The PerimeterX HTTP headers can be retrieved by calling *httpHeaders()* and will return a dictionary of type *String*: *String*.

> **Note**
>
> It is not recommended for the application to make network calls going through PX Enforcer without PerimeterX headers.

**Using Volley**

To add the PerimeterX HTTP headers to a request using AlamoFire, use the following example:

```none
let pxHeaders: HTTPHeaders = (PXManager.sharedInstance().httpHeaders() as? HTTPHeaders)!

Alamofire.request(url, encoding: JSONEncoding.default, headers: pxHeaders).responseJSON { response in
    print(response.request)  // original URL request
    print(response.response) // HTTP URL response
    print(response.data)     // server data
}
```

### Managing Requests Denied by HUMAN

When a HTTP request is denied by HUMAN, a 403 response code is sent in the HTTP response along with a JSON body encoded as a UTF-8 that is parsed and used by the HUMAN iOS SDK. The parsed JSON is then used to render a WebView to either challenge (with CAPTCHA) the visitor, or block the visitor from continuing in the application. If the user solves the presented challenge they will return to the application. If the user fails the CAPTCHA challenge they continue to be challenged until they pass the verification screen.

### Implementing the Error Handler

The *PXManager* object checks the body of the returned error message by calling the *checkError()* method, and passing in the body as *response.dictionaryObject*. This will return an object type of *PXBlockType*.

The *PXBlockType* object is processed by calling *handle()* method of the *PXManager*, and passing four arguments: *PXBlockType*, *UIViewControler*, *successHandler*, *failureHandler*.

The *handle()* method renders the WebView containing the CAPTCHA challenge.

```none
let pxHeaders: HTTPHeaders = (PXManager.sharedInstance().httpHeaders() as? HTTPHeaders)!

let url = "https://example.com/demo/api"

Alamofire.request(url, encoding: JSONEncoding.default, headers: pxHeaders).responseJSON { response in

    guard let statusCode = (response.response?.statusCode) else {
        print("Error - statusCode is missing from the response...");
        return
    }

   if statusCode == 403 {
        print("status is 403")
        let response = JSON(data: response.data!)
        let blockRepsponse = PXManager.sharedInstance().checkError(response.dictionaryObject) // Check the type of error with the SDK

        if (blockRepsponse?.type == PXBlockType.Block || blockRepsponse?.type == PXBlockType.Captcha) {
            PXManager.sharedInstance().handle(blockRepsponse, with: self, captchaSuccess: {
                print("success")

            }, captchaClose: {
                print("failure")
            })
        }
    }

    // do something here
}
```

Depending on how your application is built, an attacker can be blocked on any network call your application makes. The attacker can be blocked while the application is loading, and the only thing the user sees is the splash screen. The attacker can be in a background thread when the application makes API calls to retrieve a session token or to request data from the server to be presented on the screen.

You can choose what screen to display after the blocked user successfully solves a CAPTCHA challenge. The user can be redirected to their previous activity and retry the network calls that were blocked. The user can be returned to their previous activity and have to repeat the action that was blocked. The user can be redirected to a different screen.

### WebView Integration

**Added in version: v1.15.1**

If your application includes a WKWebView, you need to allow HUMAN SDK to handle the session connection between the web view and the application.\
This is done automatically by starting the SDK with the `PXManager.startWith` method.\
If your web view needs to handle deprecated TLS connections, make sure to implement `webView:authenticationChallenge:shouldAllowDeprecatedTLS` delegate method. The current implementation does not allow deprecated TLS versions.

### Adding Custom Parameters

**Added in version:** v1.4.1

Custom parameters allow you to collect and send specific information, be it device or app related, that may be used later for aggregations and intelligence. Using *PXManager*'s **setCustomParametersDictionary()** method you can specify up to 10 custom parameters to be sent to HUMAN servers on every network request.

**setCustomParametersDictionary()** accepts a *Dictionary* of type \[String:String] with all the keys beginning with *custom\_param* followed by a number (1-10).

It is also important to note that the **setCustomParametersDictionary()** method is set once inside the *didFinishLaunchingWithOptions* handler, **before** calling the *start* method.

The following example adds 2 custom parameters:

```none
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // PerimeterX SDK should start here
    if let pxmanager = PXManager.sharedInstance() {
        pxmanager.delegate = self
        pxmanager.setCustomParametersDictionary(["custom_param1": "John Bradley", "custom_param2": "New York"])
        pxmanager.start(with: "PX12345678") //Takes your PerimeterX Application ID
    }

    return true
}
```

### Support Account Defender (From version 1.16.3)

To enable this feature a user ID must be set. That can be done by calling the `PXAccountDefenderManager.setUserId` function and providing the user ID. When the user ID is changed, the function should be called again with the updated user ID. If the user logged out, the function should be called with nil. This function should be called after the `PXManager.startWith function`.\
To register outgoing URL requests, call the `PXAccountDefenderManager.registerOutgoingUrlRequest` function with the URL. This function should be called only when Account Defender is enabled (user ID is set).

### User Agent Convention

HUMAN uses the application's user agent to identify and differentiate between application versions. For accurate detection it is important that the user agent your application reports is informative. Here is the recommended convention:

![](/_fern-img/e24ec945217d210a6ff7c9e2eaec07775ebb8a05d6418a57aaffbc41059b626c.webp)

### Doctor App

The "Doctor App" is a tool to help you verify the mobile SDK integration by simulating a typical user flow in your application. To enable this feature, add the `enableDoctorCheck = true` parameter in the start method.

> **Important**
>
> This feature is for development purposes only and should not be shipped with your application to the application store.

Example:

```swift
PXManager.sharedInstance().start(with: "[YOUR_APP_ID]", enableDoctorCheck: true)
```

**Flow:**

1. Welcome screen: In this screen you select whether to start a new test or load the summary of the previous test, if one exists.
2. Instructions screen: In this screen you get detailed instructions on how the Doctor app works
3. Test selection screen: In this screen you choose which type of test to execute. Options are:\
   a. Native app framework - test your native URL requests.\
   b. Web view framework - test your web view's URL requests.\
   After executing either test, you will return to this screen to be able to execute the other test or to continue and review the test results in the summary screen.\
   ![image.png](/_fern-img/375728715e5072c250d1a19f9cfbc1bb76d00df8986375922f9e461e2889a408.webp)
4. Summary screen: In this screen you are able to view the results of the executed tests. You can go into details regarding each test and get troubleshooting tips in case a test failed to help you analyze what is causing this issue.\
   ![image.png](/_fern-img/2a7eaf8fdac4718ce2d75c5baf425618485f1cca8b0232c401ed02dd2fccf758.webp)

> **Important**
>
> When you exit the doctor app, your application will also terminate. Just remember to switch the 'enableDoctorCheck' parameter to false when you finish validating your integration with HUMAN mobile SDK.

### Verifying Your Integration

Validating that PXManager is Loaded Properly

**Checking the ManagerReady Callback**

To verify that SDK is implemented correctly, print a line to the console when the *ManagerReady* callback is fired.

```none
func managerReady(_ httpHeaders: [AnyHashable : Any]!) {
    print("PerimeterX - managerReady: \(httpHeaders)")
}
```

A log line similar to the example below should be displayed.

```none
PerimeterX - managerReady: Optional([AnyHashable("X-PX-AUTHORIZATION"): 3:09bfe0fa40fafa8b79946854c29c25860b7dc5c014f49254a44291d7ab11eaaf:B2MMdZOi252Q4KD/2w53kyFUtk5mQz36psSTsPUJ3A8kxefY9tN6M4c7iW0wHnYjQJ94OecOG0tqTu6MEUFvug==:1000:KZ9rHK/mDjaY0KeqHosaoUytDjBbqyJXx2dPYvudp3M8uXJzEYoEZQRiFC8KimtwgbEqoRiRW3nTzKs3FyKJLgsYACSLrFvx+yyT3CWOQr9JkccNTe0W9+JkVko3SrPJp2+XFje9wp5rRShkPX2FV1dpa23CdMnyP92k/ZYWOeI=])
```

### Validating that PerimeterX HTTP Headers Are Part of Your Request

Connections to API endpoint can be inspected using a local proxy such as CharlesProxy\_.\
When inspecting requests look for the HTTP header named X-PX-AUTHORIZATION.

> **Note**
>
> Requests to the perimeterx.net domain are also pinned to a specific SSL certificate and cannot be inspected with [Charles Proxy](https://www.charlesproxy.com/). If you have enabled SSL proxy for all domains you must exclude perimeterx.net.

![](/_fern-img/c4536ce6fac50e3e69c2b0080680da3b1a52ce3eacbbc7c9e2eea3e64b124389.webp)

If this header is not present go back to the application code responsible for making the request and review to verify the headers were added to the request properly.

### Validating Denied Requests

Denied requests will have one of two possible actions, block or challenge, and both should be validated to ensure the request is properly handled.

### Console Developer Testing Tools

Developers integrating with the HUMAN Mobile SDK can be given access to the HUMAN Portal in a developer role. They then have access to the Developer section, which contains the Mobile Enforcement Verification tool. This tool allows a developer the ability to mark their requests to be denied for testing purposes.\
The testing tool is necessary to validate denied requests.

> **Note**
>
> Make sure the enforcer you are testing against is set to blocking mode before proceeding with the instructions.

1. Access the tool at [https://console.humansecurity.com/botDefender/developer](https://console.humansecurity.com/botDefender/developer)
2. Locate your test device's Visitor ID \<glossary:VID>, and click the \<glossary:VID>Extractor button.\
   This will launch the \<glossary:VID>Extractor model:\
   ![image.png](/_fern-img/eff34bbcf7bfc42a1994250f7949fecf89963efd2383ca5fe52c8beab5c6f7b1.webp)
3. Insert your IP address and click *Search*. This locates all \<glossary:VID>for your APP ID.
4. Click *Select* to return to the tool with the App ID and \<glossary:VID>fields populated.\
   ![image.png](/_fern-img/d6d807bc5e4efdc11fe8ef4f2a5d88371fadc0db46383184cc74ccd5d85591bc.webp)
5. When the App ID and \<glossary:VID>are available, you can start validating denied requests.\
   ![image.png](/_fern-img/1c47fbc60854666d06a8065d41fa5e9914aed0cadd415ebd7e9ca18e2094d896.webp)

### Validating a Challenge Response

To validate a challenge response:

1. Click CAPTCHA in the test tool and wait for the green toast notification to confirm you are ready to continue.\
   ![image.png](/_fern-img/96f912560f5830f59eb873a3b3e71187d8e6193226f5cb8190c614abdabc617a.webp)
2. When the next HUMAN token refresh occurs in your mobile application you will receive the CAPTCHA WebView.
3. To force a token refresh simply exit and relaunch the application.
4. Solve the challenge presented and verify that you are able to return to the application and continue using it.\
   ![image.png](/_fern-img/57434e281192ea247302b9ea090d3f590fcc6d26d5d4f077e07555e90e005eaf.webp)

### Validating a Blocking Response

To validate a blocking response:

1. Click *Block* in the test tool and wait for the green toast notification to confirm you are ready to continue.\
   ![image.png](/_fern-img/59323e2140beb1a4d8d01d244432e5c114b7a5049295da7dfd74d2bd7c158ca0.webp)
2. When the next HUMAN token refresh occurs in your mobile application you will receive the block WebView.
3. To force a token refresh simply relaunch the application. Once you are blocked you cannot continue.
4. To release from blocking, exit the application, click the *Clear* button, and reload the application to verify that the clean token was received and the application is operating as expected.\
   ![image.png](/_fern-img/2e8c1c5e355e5781166cb1b1a1484f257f246af1c000c20963e7b2773e43ddcd.webp)

### Appendix

**Configuring an iOS Emulator to use Charles Proxy**

To configure your iOS Emulator set the HTTP proxy settings on your computer. The emulator will use your computer’s local network connection.

In order to intercept HTTPS requests follow the guidelines at [https://www.charlesproxy.com/documentation/using-charles/ssl-certificates](https://www.charlesproxy.com/documentation/using-charles/ssl-certificates).

**Deactivating the PX Mobile Sensor Remotely**

In certain cases, the PX Mobile Sensor (SDK) may need to be deactivated remotely, and the app run without any sensor intervention.

This can be done based on any combination of the following parameters:

1. AppID
2. Operating System
3. Operating System Version
4. SDK Version
5. App Version

To deactivate the PX Mobile Sensor, contact your assigned focal point within HUMAN. Portal support to allow deactivation via the Portal will be added in the future.

## React Native

### Supported iOS Versions

HUMAN supports iOS version 9 and higher.

### Introduction

The HUMAN iOS SDK works by constantly profiling and evaluating device behavior to ensure that the connections to your mobile APIs and services are genuine.

This process is complex and detailed yet only requires initializing a context to manage a set of secure HTTP headers which are added to all HTTP and HTTPS requests made by the mobile application to the origin server. These HTTP headers are refreshed on a regular basis by the HUMAN Manager (context) as it is profiling the end-user’s mobile device.

### Prerequisites

The following are required to install the HUMAN iOS SDK:

* Administrative access to the HUMAN Portal to:
  * Retrieve the HUMAN application ID.
  * Set the token expiration and validity.
* An active HUMAN Enforcer.
* A sandbox or staging environment for development and testing (recommended).
* React Native dependencies

### Integration

**Adding the iOS SDK to your project**

1. Add the HUMAN iOS SDK Binary to Your Project with:\
   [https://github.com/PerimeterX/px-iOS-Framework](https://github.com/PerimeterX/px-iOS-Framework) (the official repository for hosting the PerimeterX iOS SDK).\
   The repository can be integrated with CocoaPods or Carthage.

### CocoaPods

Add `pod 'PerimeterX'` to your\
`Podfile < >`\_\_.

```none
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your App Name>' do
    pod 'PerimeterX'
end
```

You can now run `pod update` and once completed don’t forget to close and reopen your Xcode workspace.

### Carthage

Add the following to the app's Cartfile:

```none
binary "https://raw.githubusercontent.com/PerimeterX/px-iOS-Framework/master/PerimeterX.json"
```

Then run

```none
carthage update --platform iOS
```

2. Once the binary is added to your project, resync the build files to ensure the package is downloaded.
3. The SDK is now installed, and there should not be any build errors when compiling your application.

### Adding the Manager Object

1. In your \_AppDelegate.m\_file import the library.

   ```none
   #import <PerimeterX/PerimeterX.h>
   ```
2. In your \_AppDelegate.m\_file, add the following mandatory methods using the example below.

   ```none
   -(void) newHeaders:(NSDictionary *)httpHeaders {
       NSLog(@"PXManagerDelegate: newHeaders: %@", httpHeaders);
   }

   -(void) managerReady:(NSDictionary *)httpHeaders {
       NSLog(@"PXManagerDelegate: managerReady: %@", httpHeaders);
   }
   ```

* When adding the *PXManagerDelegate* extension the following two functions are required: *managerReady* and *newHeaders*.
* The *managerReady* is called when the first set of PerimeterX HTTP headers are available.
* Setting the *newHeaders* is required to ensure that the *PXManagerDelegate* will notify the application that a refresh to the HTTP headers occurred. This is based on the token validity time set in the HUMAN portal.
* Action in the *newHeaders* method is optional. (reference the code example above).

### Initializing the Manager

In *AppDelegate.m* you must now initialize the *PXManager* object inside the *didFinishLaunchingWithOptions* handler:

```none
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // Override point for customization after application launch.
     PXManager *pxManager = [PXManager sharedInstance];
     pxManager.delegate = self;
     [pxManager startWith: @"PX123456"]; // Defines your PerimeterX Application ID

     return YES;
 }
```

### Creating a Bridge For The Native Methods

1. In your project, create a new file called `PXBridge.h`with the following content:

   ```none
   #import <Foundation/Foundation.h>
   #import <React/RCTBridgeModule.h>


   NS_ASSUME_NONNULL_BEGIN

   @interface PXBridge : NSObject<RCTBridgeModule>

   @end

   NS_ASSUME_NONNULL_END
   ```
2. Create the implementation of `PXBridge` by creating a file called `PXBridge.m` with the following content:

```none
#import "PXBridge.h"
  #import "React/RCTLog.h"
  #import <PerimeterX/PerimeterX.h>

  @implementation PXBridge

  RCT_EXPORT_MODULE();



  RCT_REMAP_METHOD(getHttpHeaders,
                   getHttpHeaders_resolver:(RCTPromiseResolveBlock)resolve
                   getHttpHeaders_rejecter:(RCTPromiseRejectBlock)reject)
  {
    PXManager *pxManager = [PXManager sharedInstance];
    NSDictionary *httpHeaders = [pxManager httpHeaders];
    resolve(httpHeaders);
  }

  RCT_EXPORT_METHOD(verifyResponse:(NSDictionary *)response
                    verifyResponse_resolver:(RCTPromiseResolveBlock)resolve
                    verifyResponse_rejecter:(RCTPromiseRejectBlock)reject)
  {
    PXManager *pxManager = [PXManager sharedInstance];
    PXBlockResponse *blockResponse = [pxManager checkError:response];
    if (blockResponse.type == Block || blockResponse.type == Captcha) {
      dispatch_async(dispatch_get_main_queue(), ^{
      UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
      [[PXManager sharedInstance] handleBlockResponse:blockResponse with:rootViewController captchaSuccess:^{
        NSLog(@"captcha success");
        resolve(@"success");
      } captchaClose:^ {
        NSLog(@"captcha closed");
        NSError *error = [NSError errorWithDomain:@"perimeterx.sdk" code:11 userInfo:NULL];
        reject(@"captcha closed", @"challenge page closed",error);
      }];
  });
}
    else {
      NSLog(@"Not a PerimeterX Response");
      resolve(@"NotPXBlock");
    }
  }
  @end
```

The bridge exposes the minimal methods required for the SDK to operate:

* `getHttpHeaders` - returns a JSON file containing the PerimeterX HTTP headers.
* `verifyResponse` - verifies the 403 response and based on its content - either returns the response unchanged or calls the SDK's `handleBlockResponse` method.

### Adding the PerimeterX HTTP Headers to the HTTP Requests

Once the PerimeterX Manager is initialized, you need to add the PerimeterX HTTP Headers to every network request your app is making. These headers can be retrieved by calling the `[pxManager httpHeaders]` method of the SDK, which is exposed to the JavaScript side by the bridge created in the earlier step.

**Using Axios**

To add the PerimeterX HTTP headers to every request using Axios, use the following example:

```none
import {NativeModules} from 'react-native';

axios.interceptors.request.use(async (config) => {
    const pxHeaderResponse = await NativeModules.PXBridge.getHttpHeaders();
    for (var prop in pxHeaderResponse) {
        config.headers[prop] = pxHeaderResponse[prop];
    }
    return config;
}, function (error) {
    throw error;
});
```

**Using Fetch**

To add the PerimeterX HTTP headers to a fetch request, either add the headers directly to each fetch request, or create a wrapper like the following example:

```none
async function callFetch() {
    const url = '                                      ';
    const pxHeaderResponse = await NativeModules.PXBridge.getHttpHeaders();
    let headers = {};
    for (var prop in pxHeaderResponse) {
        headers[prop] = pxHeaderResponse[prop];
    }
    let result;
    try {
        result = await fetch(url,{
            method: 'GET',
            headers: headers
        })
        let jsonResult = await result.json();
        return jsonResult;
    } catch (e) {
        throw e;
    }
}
```

### Managing Requests Denied by HUMAN

When a HTTP request is denied by HUMAN a 403 response code is sent in the HTTP response along with a JSON body encoded as a UTF-8 that is parsed and used by the HUMAN iOS SDK. The parsed JSON is then used to render a WebView to either challenge (with CAPTCHA) the visitor, or block the visitor from continuing in the application. If the user solves the presented challenge they will return to the application. If the user fails the CAPTCHA challenge they continue to be challenged until they pass the verification screen.

### Implementing the Error Handler

The *PXManager* object checks the body of the returned error message by calling **\[\[PXManager sharedInstance] checkError:body]** and if the 403 error originates from HUMAN, the **\[\[PXManager sharedInstance] handleBlockResponse:blockResponse]** method. A combination of these methods is exposed to the JavaScript side from the native bridge.

The easiest way to implement the error handler in React Native is through the use of Axios's response interceptor.

**Using Axios**

```none
axios.interceptors.response.use((response) => {
    return response;
}, async (error) => {
    if (error.response.status === 403) {
        let result = await NativeModules.PXBridge.verifyResponse(error.response.data);
        if (result == "NotPXBlock") {
            throw error;
        }
    } else {
        throw error;
    }
});
```

**Using Fetch**

```none
async function callFetch() {
    const url = '                                      ';
    const pxHeaderResponse = await NativeModules.PXBridge.getHttpHeaders();
    let headers = {};
    for (var prop in pxHeaderResponse) {
        headers[prop] = pxHeaderResponse[prop];
    }
    let result;
    try {
        result = await fetch(url,{
            method: 'GET',
            headers: headers
        })
        let jsonResult = await result.json();
        return jsonResult;
    } catch (error) {
        if (error.response.status === 403) {
            let result = await NativeModules.PXBridge.verifyResponse(error.response.data);
            if (result == "NotPXBlock") {
                throw error;
            }
        } else {
            throw error;
        }
    }
}
```

### Adding Custom Parameters

**Added in version:** v1.4.1

Custom parameters allow you to collect and send specific information, be it device or app related, that may be used later for aggregations and intelligence. Using *PXManager*'s **setCustomParametersDictionary()** method you can specify up to 10 custom parameters to be sent to HUMAN servers on every network request.

**setCustomParametersDictionary()** accepts a *NSDictionary* of type \[String:String] with all the keys beginning with *custom\_param* followed by a number (1-10).

It is also important to note that the **setCustomParametersDictionary()** method is set once inside the *didFinishLaunchingWithOptions* handler, **before** calling the *start* method.

The following example adds 2 custom parameters:

```none
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    PXManager *pxManager = [PXManager sharedInstance];
    pxManager.delegate = self;
    [pxManager setCustomParametersDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"John Bradley",@"custom_param1", @"New York", @"custom_param2", nil]];
    [pxManager startWith: @"PX123456"]; // Defines your PerimeterX Application ID

    return YES;
}
```

### WebView Integration

**Added in version: v1.15.1**

If your application includes a WKWebView, you need to allow HUMAN SDK to handle the session connection between the web view and the application.\
This is done automatically by starting the SDK with the `PXManager.startWith` method.\
If your web view needs to handle deprecated TLS connections, make sure to implement `webView:authenticationChallenge:shouldAllowDeprecatedTLS` delegate method. The current implementation does not allow deprecated TLS versions.

### Support Account Defender (From version 1.16.3)

To enable this feature a user ID must be set. That can be done by calling the `PXAccountDefenderManager.setUserId` function and providing the user ID. When the user ID is changed, the function should be called again with the updated user ID. If the user logged out, the function should be called with nil. This function should be called after the `PXManager.startWith` function.\
To register outgoing URL requests, call the `PXAccountDefenderManager.registerOutgoingUrlRequest` function with the URL. This function should be called only when Account Defender is enabled (user ID is set).

### User Agent Convention

HUMAN uses the application's user agent to identify and differentiate between application versions. For accurate detection it is important that the user agent your application reports is informative. Here is the recommended convention:

### Doctor App

The "Doctor App" is a tool to help you verify the mobile SDK integration by simulating a typical user flow in your application. To enable this feature, add the `enableDoctorCheck = true` parameter in the start method.

> **Important**
>
> This feature is for development purposes only and should not be shipped with your application to the application store.

Example:

```objectivec
[PXManager.sharedInstance startWith:@"[YOUR_APP_ID]" enableDoctorCheck:YES];
```

**Flow:**

1. Welcome screen: In this screen you select whether to start a new test or load the summary of the previous test, if one exists.
2. Instructions screen: In this screen you get detailed instructions on how the Doctor app works
3. Test selection screen: In this screen you choose which type of test to execute. Options are:\
   a. Native app framework - test your native URL requests.\
   b. Web view framework - test your web view's URL requests.\
   After executing either test, you will return to this screen to be able to execute the other test or to continue and review the test results in the summary screen.\
   ![image.png](/_fern-img/375728715e5072c250d1a19f9cfbc1bb76d00df8986375922f9e461e2889a408.webp)
4. Summary screen: In this screen you are able to view the results of the executed tests. You can go into details regarding each test and get troubleshooting tips in case a test failed to help you analyze what is causing this issue.\
   ![image.png](/_fern-img/2a7eaf8fdac4718ce2d75c5baf425618485f1cca8b0232c401ed02dd2fccf758.webp)

> **Important**
>
> When you exit the doctor app, your application will also terminate. Just remember to switch the 'enableDoctorCheck' parameter to false when you finish validating your integration with HUMAN mobile SDK.

### Verifying Your Integration

Validating that PXManager is Loaded Properly

**Checking the ManagerReady Callback**

To verify that SDK is implemented correctly, print a line to the console when the *ManagerReady* callback is fired.

```none
-(void) managerReady:(NSDictionary *)httpHeaders {
    NSLog(@"PXManagerDelegate: managerReady: %@", httpHeaders);
}
```

A log line similar to the example below should be displayed.

```none
2017-10-10 15:13:22.536 PX Obj C[64870:23419637] PXManagerDelegate: managerReady: {
    "X-PX-AUTHORIZATION" = "3:497f904bae55a3cca2800da80892a72ba25e5e4beef6798722f0e7743a760b67:pZ98scNgg8mc7LOY74h1uHV1/mybppJORCzop3OSiIbQXnfQI3p12kFMrO+4HuOHt1KD+3oUW8rO+Cvj1kBjag==:1000:7Tonf5zinmI8mX7Y7LynB4pWi56rtqbCp8krXnaeq1TsN07XXeMM9OgnVUmmAq2kEhd0DPDkh+CAVZ+OS0L24cMtlTbJNo0mpbqj9YvAhXwoV2jUT1er9XS+AO1Kq0IERgyaufKQGjwIjXzXVP7zdcG3JuB4m9LyHT1WiWTdLRw=";
}
```

### Validating that PerimeterX HTTP Headers Are Part of Your Request

Connections to your API endpoint can be inspected using a local proxy such as CharlesProxy\_.\
When inspecting requests look for the HTTP header named X-PX-AUTHORIZATION.

**Please note** requests to the perimeterx.net domain are also pinned to a specific SSL certificate and cannot be inspected with [Charles Proxy](https://www.charlesproxy.com/). If you have enabled SSL proxy for all domains you must exclude perimeterx.net.

If this header is not present go back to the application code responsible for making the request and review to verify the headers were added to the request properly.

### Validating Denied Requests

Denied requests will have one of two possible actions, block or challenge, and both should be validated to ensure the request is properly handled.

### Console Developer Testing Tools

Developers integrating with the HUMAN Mobile SDK can be given access to the HUMAN Portal in a developer role. They then have access to the Developer section, which contains the Mobile Enforcement Verification tool. This tool allows a developer the ability to mark their requests to be denied for testing purposes.\
The testing tool is necessary to validate denied requests.

> **Note**
>
> Make sure the enforcer you are testing against is set to blocking mode before proceeding with the instructions.

1. Access the tool at [https://console.humansecurity.com/botDefender/developer](https://console.humansecurity.com/botDefender/developer).
2. Locate your test device's Visitor ID \<glossary:VID>, and click the \<glossary:VID> Extractor button.\
   This will launch the \<glossary:VID>Extractor model:
3. Insert your IP address and click *Search*. This locates all \<glossary:VID>s for your APP ID.
4. Click *Select* to return to the tool with the App ID and \<glossary:VID> fields populated.
5. When the App ID and \<glossary:VID> are available, you can start validating denied requests.

### Validating a Challenge Response

To validate a challenge response:

1. Click CAPTCHA in the test tool and wait for the green toast notification to confirm you are ready to continue.
2. When the next HUMAN token refresh occurs in your mobile application you will receive the CAPTCHA WebView.
3. To force a token refresh simply exit and relaunch the application.
4. Solve the challenge presented and verify that you are able to return to the application and continue using it.

### Validating a Blocking Response

To validate a blocking response:

1. Click\_Block\_ in the test tool and wait for the green toast notification to confirm you are ready to continue.
2. When the next HUMAN token refresh occurs in your mobile application you will receive the block WebView.
3. To force a token refresh simply relaunch the application. Once you are blocked you cannot continue.
4. To release from blocking, exit the application, click the *Clear* button, and reload the application to verify that the clean token was received and the application is operating as expected.

### Appendix

**Configuring an iOS Emulator to use Charles Proxy**

To configure your iOS Emulator set the HTTP proxy settings on your computer. The emulator will use your computer’s local network connection.

In order to intercept HTTPS requests follow the guidelines at [https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/](https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/).

**Deactivating the PX Mobile Sensor Remotely**

In certain cases, the PX Mobile Sensor (SDK) may need to be deactivated remotely, and the app run without any sensor intervention.

This can be done based on any combination of the following parameters:

1. AppID
2. Operating System
3. Operating System Version
4. SDK Version
5. App Version

To deactivate the PX Mobile Sensor, [contact us](/applications/human-customer-support) or your assigned focal point within HUMAN. Portal support to allow deactivation via the Portal will be added in the future

## Objective-C

### Supported iOS Versions

HUMAN supports iOS version 8 and higher.

### Introduction

The HUMAN iOS SDK works by constantly profiling and evaluating device behavior to ensure that the connections to your mobile APIs and services are genuine.

This process is complex and detailed yet only requires initializing a context to manage a set of secure HTTP headers which are added to all HTTP and HTTPS requests made by the mobile application to the origin server. These HTTP headers are refreshed on a regular basis by the HUMAN Manager (context) as it is profiling the end-user’s mobile device.

The HUMAN iOS SDK works well with popular HTTP request libraries for iOS including [AFNetworking](https://github.com/AFNetworking/AFNetworking)

### Prerequisites

The following are required to install the HUMAN iOS SDK:

* Administrative access to the HUMAN Portal to:
  * Retrieve the HUMAN application ID.
  * Set the token expiration and validity.
* An active HUMAN Enforcer.
* A sandbox or staging environment for development and testing (recommended).

### Integration

**Adding the iOS SDK to your project**

1. Add the HUMAN iOS SDK Binary to Your Project with:\
   [https://github.com/PerimeterX/px-iOS-Framework](https://github.com/PerimeterX/px-iOS-Framework) (the official repository for hosting the HUMAN iOS SDK). The repository can be integrated with CocoaPods or Carthage.

### CocoaPods

Add `pod 'PerimeterX'` to your [Podfile](https://guides.cocoapods.org/syntax/podfile.html)

```none
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your App Name>' do
    pod 'PerimeterX'
end
```

You can now run `pod update` and once completed don’t forget to close and reopen your Xcode workspace.

### Carthage

Add the following to the app's Cartfile:

```none
binary "https://raw.githubusercontent.com/PerimeterX/px-iOS-Framework/master/PerimeterX.json"
```

Then run

```none
carthage update --platform iOS
```

2. Once the binary is added to your project, resync the build files to ensure the package is downloaded.
3. The SDK is now installed, and there should not be any build errors when compiling your application.

### Adding the Manager Object

1. In your *AppDelegate.m* file import the library.

```none
#import <PerimeterX/PerimeterX.h>
```

2. In your *AppDelegate.m* file, add the following mandatory methods using the example below.

```none
-(void) newHeaders:(NSDictionary *)httpHeaders {
    NSLog(@"PXManagerDelegate: newHeaders: %@", httpHeaders);
}

-(void) managerReady:(NSDictionary *)httpHeaders {
    NSLog(@"PXManagerDelegate: managerReady: %@", httpHeaders);
}
```

* When adding the *PXManagerDelegate* extension the following two functions are required: *managerReady* and *newHeaders*.
* The *managerReady* is called when the first set of PerimeterX HTTP headers are available.
* Setting the *newHeaders* is required to ensures that the *PXManagerDelegate* will notify the application that a refresh to the HTTP headers occurred. This is based on the token validity time set in the HUMAN portal.
* Action in the *newHeaders* method is optional. (reference the code example above).

### Initializing the Manager

In *AppDelegate.m* you must now initialize the *PXManager* object inside the *didFinishLaunchingWithOptions* handler:

```none
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    PXManager *pxManager = [PXManager sharedInstance];
    pxManager.delegate = self;
    [pxManager startWith: @"PX123456"]; // Defines your PerimeterX Application ID

    return YES;
}
```

### Adding the PerimeterX HTTP Headers to the HTTP Requests

1. Once the Manager is initialized, add PerimeterX HTTP Headers to your network manager headers.\
   You are now set to start your requests.
2. The PerimeterX HTTP headers can be retrieved by calling \*\* \[pxManager httpHeaders]\*\* and will return a NSDictionary of type *String*: *String*.

> **Note**
>
> It is not recommended for the application to make network calls going through PX Enforcer without PerimeterX headers.

**Using AFNetworking**

To add the PerimeterX HTTP headers to a request using AFNetworking, use the following example:

```none
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

PXManager *pxManager = [PXManager sharedInstance];
NSDictionary *httpHeaders = [pxManager httpHeaders];
if (httpHeaders != nil) {
    for (NSString *key in httpHeaders) {
        [manager.requestSerializer setValue: httpHeaders[key] forHTTPHeaderField: key];
    }
}

[manager GET:url parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    NSLog(@"Result: %@", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];
```

### Managing Requests Denied by HUMAN

When a HTTP request is denied by HUMAN a 403 response code is sent in the HTTP response along with a JSON body encoded as a UTF-8 that is parsed and used by the HUMAN iOS SDK. The parsed JSON is then used to render a WebView to either challenge (with CAPTCHA) the visitor, or block the visitor from continuing in the application. If the user solves the presented challenge they will return to the application. If the user fails the CAPTCHA challenge they continue to be challenged until they pass the verification screen.

### Implementing the Error Handler

The *PXManager* object checks the body of the returned error message by calling **\[\[PXManager sharedInstance] checkError:body]** and passing in the body as a *NSDictionary*. This will return an object type of *PXBlockResponse*.

You then must pass the returned object to **P\[\[PXManager sharedInstance] handleBlockResponse:blockResponse]** to render the correct response. **\[\[PXManager sharedInstance] handleBlockResponse:blockResponse]** requires four arguments: *PXBlockResponse*, *UIViewControler*, *successHandler*, *failureHandler*.

See the example below:

```none
NSString *url = @"https://perimeterx.example.com/demo/api/";

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

PXManager *pxManager = [PXManager sharedInstance];
NSDictionary *httpHeaders = [pxManager httpHeaders];
if (httpHeaders != nil) {
    for (NSString *key in httpHeaders) {
        [manager.requestSerializer setValue: httpHeaders[key] forHTTPHeaderField: key];
    }
}

[manager GET:url parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    NSLog(@"Result: %@", responseObject);
} failure:^(NSURLSessionTask *task, NSError *error) {
    NSLog(@"Error: %@", error);
    NSInteger statusCode = 0;
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;

    if ([httpResponse isKindOfClass:[NSHTTPURLResponse class]]) {
        statusCode = httpResponse.statusCode;
    }

    if (statusCode == 403) {
        NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
        NSError* err;
        NSDictionary *bodyJson = [NSJSONSerialization JSONObjectWithData:responseData
                                                                 options:kNilOptions
                                                                   error:&err];

        PXBlockResponse *blockResponse = [[PXManager sharedInstance] checkError:bodyJson];
        if (blockResponse.type == Block || blockResponse.type == Captcha) {
            [[PXManager sharedInstance] handleBlockResponse:blockResponse with:self captchaSuccess:^{
                NSLog(@"captcha success");
            } captchaFailure:^{
                NSLog(@"captcha failure");
                // This callback is for tracking purpose only, there is no action needed here.
            }];
        }
        else {
            NSLog(@"Not a PerimeterX Response");
        }
    }
}];
```

Depending on how your application is built, an attacker can be blocked on any network call your application makes. The attacker can be blocked while the application is loading, and the only thing the user sees is the splash screen. The attacker can be in a background thread when the application makes API calls to retrieve a session token or to request data from the server to be presented on the screen.

You can choose what screen to display after the blocked user successfully solves a CAPTCHA challenge. The user can be redirected to their previous activity and retry the network calls that were blocked. The user can be returned to their previous activity and have to repeat the action that was blocked. The user can be redirected to a different screen.

### WebView Integration

If your application includes a WebView, it is recommended to connect the application and the web sessions. To do this, pass the cookie **\_pxmvid** with the value of the \<glossary:VID> when loading the WebView in the **viewDidLoad** method.

WebView integration requires PX js client v.3.23 or above.

The \<glossary:VID> can be accessed using **\[PXManager sharedInstance] getVid]**.

```none
- (void)viewDidLoad {
    [super viewDidLoad];
    //Set _pxmvid cookie when VID is not nil
    if ([PXManager sharedInstance] getVid]) {
        NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
        [cookieProperties setObject:@"_pxmvid" forKey:NSHTTPCookieName];
        [cookieProperties setObject:[PXManager sharedInstance] getVid] forKey:NSHTTPCookieValue];
        [cookieProperties setObject:@"www.perimeterx.com" forKey:NSHTTPCookieDomain]; //Change according to the required Domain
        [cookieProperties setObject:@"www.perimeterx.com" forKey:NSHTTPCookieOriginURL]; //Change according to the required URL
        [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
        [cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
        [cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:3600] forKey:NSHTTPCookieExpires]; //Set the expiration to one hour

        NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }

    NSString *urlString = @"https://www.perimeterx.com/"; //Replace with your URL
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    [_webView loadRequest:urlRequest];
}
```

### Adding Custom Parameters

**Added in version:** v1.4.1

Custom parameters allow you to collect and send specific information, be it device or app related, that may be used later for aggregations and intelligence. Using *PXManager*'s **setCustomParametersDictionary()** method you can specify up to 10 custom parameters to be sent to HUMAN servers on every network request.

**setCustomParametersDictionary()** accepts a *NSDictionary* of type \[String:String] with all the keys beginning with *custom\_param* followed by a number (1-10).

It is also important to note that the **setCustomParametersDictionary()** method is set once inside the *didFinishLaunchingWithOptions* handler, **before** calling the *start* method.

The following example adds 2 custom parameters:

```none
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    PXManager *pxManager = [PXManager sharedInstance];
    pxManager.delegate = self;
    [pxManager setCustomParametersDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"John Bradley",@"custom_param1", @"New York", @"custom_param2", nil]];
    [pxManager startWith: @"PX123456"]; // Defines your PerimeterX Application ID

    return YES;
}
```

### WebView Integration

**Added in version: v1.15.1**

If your application includes a WKWebView, you need to allow HUMAN SDK to handle the session connection between the web view and the application.\
This is done automatically by starting the SDK with the `PXManager.startWith` method.\
If your web view needs to handle deprecated TLS connections, make sure to implement `webView:authenticationChallenge:shouldAllowDeprecatedTLS` delegate method. The current implementation does not allow deprecated TLS versions.

### Support Account Defender (From version 1.16.3)

To enable this feature a user ID must be set. That can be done by calling the `PXAccountDefenderManager.setUserId` function and providing the user ID. When the user ID is changed, the function should be called again with the updated user ID. If the user logged out, the function should be called with nil. This function should be called after the `PXManager.startWith` function.\
To register outgoing URL requests, call the `PXAccountDefenderManager.registerOutgoingUrlRequest` function with the URL. This function should be called only when Account Defender is enabled (user ID is set).

### User Agent Convention

HUMAN uses the application's user agent to identify and differentiate between application versions. For accurate detection it is important that the user agent your application reports is informative. Here is the recommended convention:

![](/_fern-img/e24ec945217d210a6ff7c9e2eaec07775ebb8a05d6418a57aaffbc41059b626c.webp)

### Doctor App

The "Doctor App" is a tool to help you verify the mobile SDK integration by simulating a typical user flow in your application. To enable this feature, add the `enableDoctorCheck = true` parameter in the start method.

IMPORTANT NOTICE

This feature is for development purposes only and should not be shipped with your application to the application store.

Example:

```objectivec
[PXManager.sharedInstance startWith:@"[YOUR_APP_ID]" enableDoctorCheck:YES];
```

\


**Flow:**

1. Welcome screen: In this screen you select whether to start a new test or load the summary of the previous test, if one exists.
2. Instructions screen: In this screen you get detailed instructions on how the Doctor app works
3. Test selection screen: In this screen you choose which type of test to execute. Options are:
   1. Native app framework - test your native URL requests.
   2. Web view framework - test your web view's URL requests.\
      After executing either test, you will return to this screen to be able to execute the other test or to continue and review the test results in the summary screen.\
      ![](/_fern-img/375728715e5072c250d1a19f9cfbc1bb76d00df8986375922f9e461e2889a408.webp)
4. Summary screen: In this screen you are able to view the results of the executed tests. You can go into details regarding each test and get troubleshooting tips in case a test failed to help you analyze what is causing this issue.\
   ![](/_fern-img/2a7eaf8fdac4718ce2d75c5baf425618485f1cca8b0232c401ed02dd2fccf758.webp)

> **Important**
>
> When you exit the doctor app, your application will also terminate. Just remember to switch the 'enableDoctorCheck' parameter to false when you finish validating your integration with HUMAN mobile SDK.

### Verifying Your Integration

Validating that PXManager is Loaded Properly

### Checking the ManagerReady Callback

To verify that SDK is implemented correctly, print a line to the console when the *ManagerReady* callback is fired.

```none
-(void) managerReady:(NSDictionary *)httpHeaders {
    NSLog(@"PXManagerDelegate: managerReady: %@", httpHeaders);
}
```

A log line similar to the example below should be displayed.

```none
2017-10-10 15:13:22.536 PX Obj C[64870:23419637] PXManagerDelegate: managerReady: {
    "X-PX-AUTHORIZATION" = "3:497f904bae55a3cca2800da80892a72ba25e5e4beef6798722f0e7743a760b67:pZ98scNgg8mc7LOY74h1uHV1/mybppJORCzop3OSiIbQXnfQI3p12kFMrO+4HuOHt1KD+3oUW8rO+Cvj1kBjag==:1000:7Tonf5zinmI8mX7Y7LynB4pWi56rtqbCp8krXnaeq1TsN07XXeMM9OgnVUmmAq2kEhd0DPDkh+CAVZ+OS0L24cMtlTbJNo0mpbqj9YvAhXwoV2jUT1er9XS+AO1Kq0IERgyaufKQGjwIjXzXVP7zdcG3JuB4m9LyHT1WiWTdLRw=";
}
```

### Validating that PerimeterX HTTP Headers Are Part of Your Request

Connections to your API endpoint can be inspected using a local proxy such as CharlesProxy\_.\
When inspecting requests look for the HTTP header named X-PX-AUTHORIZATION.

> **Note**
>
> Requests to the perimeterx.net domain are also pinned to a specific SSL certificate and cannot be inspected with [Charles Proxy](https://www.charlesproxy.com/). If you have enabled SSL proxy for all domains you must exclude perimeterx.net.

![](/_fern-img/c4536ce6fac50e3e69c2b0080680da3b1a52ce3eacbbc7c9e2eea3e64b124389.webp)

If this header is not present go back to the application code responsible for the making the request and review to verify the headers were added to the request properly.

### Validating Denied Requests

Denied requests will have one of two possible actions, block or challenge, and both should be validated to ensure the request is properly handled.

### Console Developer Testing Tools

Developers integrating with the HUMAN Mobile SDK can be given access to the HUMAN Portal in a developer role. They then have access to the Developer section, which contains the Mobile Enforcement Verification tool. This tool allows a developer the ability to mark their requests to be denied for testing purposes.\
The testing tool is necessary to validate denied requests.

> **Note**
>
> Make sure the enforcer you are testing against is set to blocking mode before proceeding with the instructions.

1. Access the tool at [https://console.humansecurity.com/botDefender/developer](https://console.humansecurity.com/botDefender/developer).
2. Locate your test device's Visitor ID \<glossary:VID>, and click the \<glossary:VID> Extractor button.\
   ![](/_fern-img/eff34bbcf7bfc42a1994250f7949fecf89963efd2383ca5fe52c8beab5c6f7b1.webp)\
   This will launch the \<glossary:VID> Extractor model:
3. Insert your IP address and click *Search*. This locates all \<glossary:VID>s for your APP ID.
4. Click *Select* to return to the tool with the App ID and \<glossary:VID> fields populated.\
   ![](/_fern-img/d6d807bc5e4efdc11fe8ef4f2a5d88371fadc0db46383184cc74ccd5d85591bc.webp)
5. When the App ID and \<glossary:VID> are available, you can start validating denied requests.\
   ![](/_fern-img/1c47fbc60854666d06a8065d41fa5e9914aed0cadd415ebd7e9ca18e2094d896.webp)

### Validating a Challenge Response

To validate a challenge response:

1. Click CAPTCHA in the test tool and wait for the green toast notification to confirm you are ready to continue.\
   ![](/_fern-img/96f912560f5830f59eb873a3b3e71187d8e6193226f5cb8190c614abdabc617a.webp)
2. When the next HUMAN token refresh occurs in your mobile application you will receive the CAPTCHA WebView.
3. To force a token refresh simply exit and relaunch the application.
4. Solve the challenge presented and verify that you are able to return to the application and continue using it.\
   ![](/_fern-img/57434e281192ea247302b9ea090d3f590fcc6d26d5d4f077e07555e90e005eaf.webp)

### Validating a Blocking Response

To validate a blocking response:

1. Click *Block* in the test tool and wait for the green toast notification to confirm you are ready to continue.\
   ![](/_fern-img/59323e2140beb1a4d8d01d244432e5c114b7a5049295da7dfd74d2bd7c158ca0.webp)
2. When the next HUMAN token refresh occurs in your mobile application you will receive the block WebView.
3. To force a token refresh simply relaunch the application. Once you are blocked you cannot continue.
4. To release from blocking, exit the application, click the *Clear* button, and reload the application to verify that the clean token was received and the application is operating as expected.\
   ![](/_fern-img/2e8c1c5e355e5781166cb1b1a1484f257f246af1c000c20963e7b2773e43ddcd.webp)

### Appendix

**Configuring an iOS Emulator to use Charles Proxy**

To configure your iOS Emulator set the HTTP proxy settings on your computer. The emulator will use your computer’s local network connection.

In order to intercept HTTPS requests follow the guidelines at [https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/](https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/).

**Deactivating the PX Mobile Sensor Remotely**

In certain cases, the PX Mobile Sensor (SDK) may need to be deactivated remotely, and the app run without any sensor intervention.

This can be done based on any combination of the following parameters:

1. AppID
2. Operating System
3. Operating System Version
4. SDK Version
5. App Version

To deactivate the PX Mobile Sensor, contact your assigned focal point within HUMAN. Portal support to allow deactivation via the Portal will be added in the future.