

**Introducing a new console experience for AWS WAF**

You can now use the updated experience to access AWS WAF functionality anywhere in the console. For more details, see [Working with the console](https://docs.aws.amazon.com/waf/latest/developerguide/working-with-console.html). 

# AWS WAF mobile application integration
<a name="waf-mobile-sdk"></a>

This section introduces the topic of using the AWS WAF mobile SDKs to implement AWS WAF intelligent threat integration SDKs for Android and iOS mobile and TV apps. For TV apps, the SDKs are compatible with major smart TV platforms, including Android TV and Apple TV.
+ For Android mobile and TV apps, the SDKs work for Android API version 23 (Android version 6) and later. For information about Android versions, see [SDK Platform release notes](https://developer.android.com/tools/releases/platforms).
+ For iOS mobile apps, the SDKs work for iOS version 13 and later. For information about iOS versions, see [iOS & iPadOS Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes).
+ For Apple TV apps, the SDKs work for tvOS version 14 or later. For information about tvOS versions, see [tvOS Release Notes](https://developer.apple.com/documentation/tvos-release-notes).

With the mobile AWS WAF SDK, you can manage token authorization, and include the tokens in the requests that you send to your protected resources. By using the SDKs, you ensure that these remote procedure calls by your client contain a valid token. Additionally, when this integration is in place on your application's pages, you can implement mitigating rules in your protection pack (web ACL), such as blocking requests that don't contain a valid token.

For access to the mobile SDKs, contact support at [Contact AWS](https://aws.amazon.com/contact-us).

**Note**  
The AWS WAF mobile SDKs aren't available for CAPTCHA customization.

The basic approach for using the SDK is to create a token provider using a configuration object, then to use the token provider to retrieve tokens from AWS WAF. By default, the token provider includes the retrieved tokens in your web requests to your protected resource. 

The following is a partial listing of an SDK implementation, which shows the main components. For more detailed examples, see [Code examples for the AWS WAF mobile SDK](waf-mobile-sdk-coding-examples.md).

------
#### [ iOS ]

```
let url: URL = URL(string: "protection pack (web ACL) integration URL")!
	let configuration = WAFConfiguration(applicationIntegrationUrl: url, domainName: "Domain name")
	let tokenProvider = WAFTokenProvider(configuration)
	let token = tokenProvider.getToken()
```

------
#### [ Android ]

```
URL applicationIntegrationURL = new URL("protection pack (web ACL) integration URL");
	String domainName = "Domain name";
	WAFConfiguration configuration = WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL).domainName(domainName).build();
	WAFTokenProvider tokenProvider = new WAFTokenProvider(Application context, configuration);
	WAFToken token = tokenProvider.getToken();
```

------

# Installing the AWS WAF mobile SDK
<a name="waf-mobile-sdk-installing"></a>

This section provides instructions for installing the AWS WAF mobile SDK.

For access to the mobile SDKs, contact support at [Contact AWS](https://aws.amazon.com/contact-us).

Implement the mobile SDK first in a test environment, then in production.

**To install the AWS WAF mobile SDK**

1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

1. In the navigation pane, choose **Application integration**. 

1. In the **Intelligent threat integrations** tab, do the following: 

   1. In the pane **protection packs (web ACLs) that are enabled for application integration**, locate the protection pack (web ACL) that you're integrating with. Copy and save the protection pack (web ACL) integration URL for use in your implementation. You can also obtain this URL through the API call `GetWebACL`.

   1. Choose the mobile device type and version, then choose **Download**. You can choose any version you like, but we recommend using the latest version. AWS WAF downloads the `zip` file for your device to your standard download location.

1. In your app development environment, unzip the file to a work location of your choice. In the top-level directory of the zip file, locate and open the `README`. Follow the instructions in the `README` file to install the AWS WAF mobile SDK for use in your mobile app code. 

1. Program your app according to the guidance in the following sections.

# AWS WAF mobile SDK specification
<a name="waf-mobile-sdk-specification"></a>

This section lists the SDK objects, operations, and configuration settings for the latest available version of the AWS WAF mobile SDK. For detailed information about how the token provider and operations work for the various combinations of configuration settings, see [How the AWS WAF mobile SDK works](waf-mobile-sdk-how-it-works.md). 

**`WAFToken`**  
Holds an AWS WAF token.    
**`getValue()`**  
Retrieves the `String` representation of the `WAFToken`. 

**`WAFTokenProvider`**  
Manages tokens in your mobile app. Implement this using a `WAFConfiguration` object.    
**`getToken()`**  
If background refresh is enabled, this returns the cached token. If background refresh is disabled, this makes a synchronous, blocking call to AWS WAF to retrieve a new token.   
**`loadTokenIntoProvider(WAFToken)`**  
Loads the specified token into the `WAFTokenProvider`, replacing any token that the provider was managing. The token provider takes ownership of the new token and handles refreshing it going forward. This operation also updates the token in the cookie store, if `setTokenCookie` is enabled in the `WAFConfiguration`.  
**`onTokenReady(WAFTokenResultCallback)`**  
Instructs the token provider to refresh the token and invoke the provided callback when an active token is ready. The token provider will invoke your callback in a background thread when the token is cached and ready. Call this when your app first loads and also when it comes back to an active state. For more information about returning to an active state, see [Retrieving a token following app inactivity](waf-mobile-sdk-how-it-works.md#waf-mobile-sdk-how-back-from-inactive).   
For Android or iOS apps, you can set `WAFTokenResultCallback` to the operation that you want the token provider to invoke when a requested token is ready. Your implementation of `WAFTokenResultCallback` must take the parameters `WAFToken`, `SdkError`. For iOS apps, you can alternately create an inline function.   
**`storeTokenInCookieStorage(WAFToken)`**  
Instructs the `WAFTokenProvider` to store the specified AWS WAF token into the SDK’s cookie manager. By default, the token is only added to the cookie store when it's first acquired and when it's refreshed. If the application clears the shared cookie store for any reason, the SDK doesn't automatically add the AWS WAF token back until the next refresh. 

**`WAFConfiguration`**  
Holds the configuration for the implementation of the `WAFTokenProvider`. When you implement this, you provide your protection pack (web ACL)’s integration URL, the domain name to use in the token, and any non-default settings that you want the token provider to use.   
The following list specifies the configuration settings that you can manage in the `WAFConfiguration` object.    
**`applicationIntegrationUrl`**   
The application integration URL. Get this from the AWS WAF console or through the `getWebACL` API call.  
Required: Yes  
Type: App-specific URL. For iOS, see [iOS URL](https://developer.apple.com/documentation/foundation/url). For Android, see [java.net URL](https://docs.oracle.com/javase/7/docs/api/java/net/URL.html).   
**`backgroundRefreshEnabled`**   
Indicates whether you want the token provider to refresh the token in the background. If you set this, the token provider refreshes your tokens in the background according to the configuration settings that govern automatic token refresh activities.   
Required: No  
Type: `Boolean`  
Default value: `TRUE`  
**`domainName`**   
The domain to use in the token, which is used in token acquisition and cookie storage. For example, `example.com` or `aws.amazon.com`. This is usually the host domain of your resource that’s associated with the protection pack (web ACL), where you’ll be sending web requests. For the ACFP managed rule group, `AWSManagedRulesACFPRuleSet`, this will usually be a single domain that matches the domain in the account creation path that you provided in the rule group configuration. For the ATP managed rule group, `AWSManagedRulesATPRuleSet`, this will usually be a single domain that matches the domain in the login path that you provided in the rule group configuration.   
Public suffixes aren't allowed. For example, you can't use `gov.au` or `co.uk` as the token domain.  
The domain must be one that AWS WAF will accept, based on the protected host domain and the protection pack (web ACL)'s token domain list. For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists).  
Required: Yes  
Type: `String`   
**`maxErrorTokenRefreshDelayMsec`**   
The maximum time in milliseconds to wait before repeating a token refresh after a failed attempt. For each auto-retry for a failed attempt, it will add an exponential backoff up until the given input delay time. This value is used after token retrieval has failed and been retried `maxRetryCount` times.   
Required: No  
Type: `Integer`  
Default value: `5000` (5 seconds)  
Minimum value allowed: `1` (1 millisecond)  
Maximum value allowed: `30000` (30 seconds)  
**`maxRetryCount`**   
The maximum number of retries to perform with exponential backoff when a token is requested.   
Required: No  
Type: `Integer`  
Default value: `Infinity`  
Minimum value allowed: `0`  
Maximum value allowed: `100`  
**`setTokenCookie`**   
Indicates whether you want the SDK’s cookie manager to add a token cookie into requests and in other areas.   
With a `TRUE` value:   
+ The cookie manager adds a token cookie to all requests whose path is under the path specified in `tokenCookiePath`. 
+ The `WAFTokenProvider` operation `loadTokenIntoProvider()` updates the token in the cookie store, in addition to loading it into the token provider.
Required: No  
Type: `Boolean`  
Default value: `TRUE`  
**`tokenCookiePath`**   
Used when `setTokenCookie` is `TRUE`. Indicates the top-level path where you want the SDK’s cookie manager to add a token cookie. The manager adds a token cookie to all requests that you send to this path and to all child paths.   
For example, if you set this to `/web/login`, then the manager includes the token cookie for everything sent to `/web/login` and any of its child paths, like `/web/login/help`. It doesn't include the token for requests sent to other paths, like `/`, `/web`, or `/web/order`.   
Required: No  
Type: `String`  
Default value: `/`  
**`tokenRefreshDelaySec`**   
Used for background refresh. The maximum amount of time in seconds between background token refreshes.  
Required: No  
Type: `Integer`  
Default value: `88`  
Minimum value allowed: `88`  
Maximum value allowed: `300` (5 minutes)

## AWS WAF mobile SDK errors
<a name="waf-mobile-sdk-errors"></a>

This section lists the possible errors for the current AWS WAF mobile SDK version.

**`SdkError`**  
The error type returned when failing to retrieve a token. The Android and iOS SDK have the same error types.  
The AWS WAF mobile SDK has the following error types:    
**`invalidChallenge`**  
This error is returned when the token server returns invalid challenge data, or the response blob is mutated by an attacker.  
**`errorInvokingGetChallengeEndpoint`**  
This error is returned when the token server sends a non-success response code back to the client or when a network error occurs.  
**`invalidVerifyChallengeResponse`**  
This error is returned when there is an error retrieving the `aws-waf-token` from the AWS WAF server's verification response, or the server response was tampered with.  
**`errorInvokingVerifyEndpoint`**  
This error is returned when the client receives a bad response from the AWS WAF server or network error when verifying the solved challenge.  
**`internalError`**  
This error is returned on all other errors that might occur within the SDK itself.

**`socketTimeoutException`**  
This error is often returned when encountering network errors during token retrieval.  
This error might be caused by the following:  
+ Low network bandwidth: Confirm your network connectivity settings
+ Mutated Application Integration URL: Confirm that the integration URL is not modified from what appears on the AWS WAF console

# How the AWS WAF mobile SDK works
<a name="waf-mobile-sdk-how-it-works"></a>

This section explains how the AWS WAF mobile SDK classes, properties, and operations work together.

The mobile SDKs provide you with a configurable token provider that you can use for token retrieval and use. The token provider verifies that the requests that you allow are from legitimate customers. When you send requests to the AWS resources that you protect with AWS WAF, you include the token in a cookie, to validate the request. You can handle the token cookie manually or have the token provider do it for you.

This section covers the interactions between the classes, properties, and methods that are included in the mobile SDK. For the SDK specification, see [AWS WAF mobile SDK specification](waf-mobile-sdk-specification.md). 

## Token retrieval and caching
<a name="waf-mobile-sdk-how-token-basics"></a>

When you create the token provider instance in your mobile app, you configure how you want it to manage tokens and token retrieval. Your main choice is how to maintain valid, unexpired tokens for use in your app’s web requests:
+ **Background refresh enabled** – This is the default. The token provider automatically refreshes the token in the background and caches it. With background refresh enabled, when you call `getToken()`, the operation retrieves the cached token. 

  The token provider performs the token refresh at configurable intervals, so that an unexpired token is always available in the cache while the application is active. Background refresh is paused while your application is in an inactive state. For information about this, see [Retrieving a token following app inactivity](#waf-mobile-sdk-how-back-from-inactive).
+ **Background refresh disabled** – You can disable background token refresh, and then retrieve tokens only on demand. Tokens retrieved on demand aren't cached, and you can retrieve more than one if you want. Each token is independent of any others that you retrieve, and each has its own timestamp that's used to calculate expiration.

  You have the following choices for token retrieval when background refresh is disabled: 
  + **`getToken()`** – When you call `getToken()` with background refresh disabled, the call synchronously retrieves a new token from AWS WAF. This is a potentially blocking call that might affect app responsiveness if you invoke it on the main thread. 
  + **`onTokenReady(WAFTokenResultCallback)`** – This call asynchronously retrieves a new token and then invokes the provided result callback in a background thread when a token is ready. 

### How the token provider retries failed token retrievals
<a name="waf-mobile-sdk-how-token-retrieval-retries"></a>

The token provider automatically retries token retrieval when retrieval fails. Retries are initially performed using exponential backoff with a starting retry wait time of 100 ms. For information about exponential retries, see [Error retries and exponential backoff in AWS](https://docs.aws.amazon.com/general/latest/gr/api-retries.html).

When the number of retries reaches the configured `maxRetryCount`, the token provider either stops trying or switches to trying every `maxErrorTokenRefreshDelayMsec` milliseconds, depending on the type of token retrieval: 
+ **`onTokenReady()`** – The token provider switches to waiting `maxErrorTokenRefreshDelayMsec` milliseconds between attempts, and continues trying to retrieve the token. 
+ **Background refresh** – The token provider switches to waiting `maxErrorTokenRefreshDelayMsec` milliseconds between attempts, and continues trying to retrieve the token. 
+ **On-demand `getToken()` calls, when background refresh is disabled** – The token provider stops trying to retrieve a token and returns the previous token value, or a null value if there is no previous token. 

## Token retrieval retry scenarios
<a name="waf-mobile-sdk-how-token-retrieval-retry-scenarios"></a>

When the token provider tries to retrieve a token, it might result in auto-retries depending on where token retrieval fails in the token acquisition flow. This section lists the possible places where you might see an auto-retry.
+ **Obtaining or verifying the AWS WAF Challenge through /inputs or /verify:**
  + When a request to obtain and verify a AWS WAF challenge is made and fails, it can result in an auto-retry.
  + You might observe auto-retries happening here along with a `socketTimeoutException` error. This can have multiple causes including:
    + Low network bandwidth: Confirm your network connectivity settings
    + Mutated Application Integration URL: Confirm that the integration URL is not modified from what appears on the AWS WAF console
  + The auto-retry count is configurable with the `maxRetryCount()` function
+ **Refreshing the token:**
  + When a request to refresh the token is made through the token handler, it might result in an auto-retry.
  + The auto-retry count here is configurable with the `maxRetryCount()` function.

A configuration with no auto-retries is possible by setting `maxRetryCount(0)`.

## Token immunity time and background refresh
<a name="waf-mobile-sdk-how-token-immunity"></a>

The token immunity time that you configure in the Web ACL is independent of the token refresh interval you set in the AWS WAF mobile SDK. When you enable background refresh, the SDK refreshes the token at the interval you specify using `tokenRefreshDelaySec()`. This can result in multiple valid tokens existing simultaneously, depending on your configured immunity time.

To prevent multiple valid tokens, you can disable background refresh and use the `getToken()` function to manage the token lifecycle in your mobile app.

## Retrieving a token following app inactivity
<a name="waf-mobile-sdk-how-back-from-inactive"></a>

Background refresh is only performed while your app is considered active for your app type: 
+ **iOS** – Background refresh is performed when the app is in the foreground.
+ **Android** – Background refresh is performed when the app isn't closed, whether it's in the foreground or background.

If your app remains in any state that doesn’t support background refresh for longer than your configured `tokenRefreshDelaySec` seconds, the token provider pauses background refresh. For example, for an iOS app, if `tokenRefreshDelaySec` is 300 and the app closes or goes into the background for more than 300 seconds, the token provider stops refreshing the token. When the app returns to an active state, the token provider automatically restarts background refresh. 

When your app comes back to an active state, call `onTokenReady()` so you can be notified when the token provider has retrieved and cached a new token. Don't just call `getToken()`, because the cache might not yet contain a current, valid token. 

## Application Integration URL
<a name="waf-mobile-sdk-application-integration-url"></a>

The AWS WAF mobile SDK application integration URL points to a Web ACL that you've enabled for application integration. This URL routes requests to the correct backend server and associates them with your customer. It doesn't serve as a hard security control, so exposing an integration URL doesn't pose a security risk.

You can technically modify the provided integration URL and still obtain a token. However, we don't recommend this because you might lose visibility into challenge solve rates or encounter token retrieval failures with `socketTimeoutException` errors.

## Dependencies
<a name="waf-mobile-sdk-dependencies"></a>

Each downloadable AWS WAF mobile SDK includes a README file that lists out the dependencies for its specific version of the SDK. Refer to the README for the dependencies for your version of the mobile SDK.

## Obfuscation/ProGuard (Android SDK Only)
<a name="waf-mobile-sdk-obfuscation"></a>

If you use an obfuscation or minification product like ProGuard, you might need to exclude certain namespaces to ensure the mobile SDK works correctly. Check the README for your version of the mobile SDK to find the list of namespaces and exclusion rules.

# Code examples for the AWS WAF mobile SDK
<a name="waf-mobile-sdk-coding-examples"></a>

This section provides code examples for using the mobile SDK. 

## Initializing the token provider and getting tokens
<a name="waf-mobile-sdk-coding-basic"></a>

You initiate your token provider instance using a configuration object. Then you can retrieve tokens using the available operations. The following shows the basic components of the required code.

------
#### [ iOS ]

```
let url: URL = URL(string: "protection pack (web ACL) integration URL")!
let configuration = WAFConfiguration(applicationIntegrationUrl: url, domainName: "Domain name")
let tokenProvider = WAFTokenProvider(configuration)

//onTokenReady can be add as an observer for UIApplication.willEnterForegroundNotification
self.tokenProvider.onTokenReady() { token, error in
	if let token = token {
	//token available
	}

	if let error = error {
	//error occurred after exhausting all retries
	}
}

//getToken()
let token = tokenProvider.getToken()
```

------
#### [ Android ]

Java example:

```
String applicationIntegrationURL = "protection pack (web ACL) integration URL";
//Or
URL applicationIntegrationURL = new URL("protection pack (web ACL) integration URL");

String domainName = "Domain name";

WAFConfiguration configuration = WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL).domainName(domainName).build();
WAFTokenProvider tokenProvider = new WAFTokenProvider(Application context, configuration);

// implement a token result callback
WAFTokenResultCallback callback = (wafToken, error) -> {
	if (wafToken != null) {
	// token available
	} else {  
	// error occurred in token refresh  
	}
};

// Add this callback to application creation or activity creation where token will be used
tokenProvider.onTokenReady(callback);

// Once you have token in token result callback
// if background refresh is enabled you can call getToken() from same tokenprovider object
// if background refresh is disabled you can directly call getToken()(blocking call) for new token
WAFToken token = tokenProvider.getToken();
```

Kotlin example:

```
import com.amazonaws.waf.mobilesdk.token.WAFConfiguration
import com.amazonaws.waf.mobilesdk.token.WAFTokenProvider

private lateinit var wafConfiguration: WAFConfiguration
private lateinit var wafTokenProvider: WAFTokenProvider

private val WAF_INTEGRATION_URL = "protection pack (web ACL) integration URL"
private val WAF_DOMAIN_NAME = "Domain name"

fun initWaf() {
	// Initialize the tokenprovider instance
	val applicationIntegrationURL = URL(WAF_INTEGRATION_URL)
	wafConfiguration =
		WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL)
			.domainName(WAF_DOMAIN_NAME).backgroundRefreshEnabled(true).build()
	wafTokenProvider = WAFTokenProvider(getApplication(), wafConfiguration)
	
		// getToken from tokenprovider object
		println("WAF: "+ wafTokenProvider.token.value)
	
		// implement callback for where token will be used
		wafTokenProvider.onTokenReady {
			wafToken, sdkError ->
		run {
			println("WAF Token:" + wafToken.value)
		}
	}
}
```

------

## Allowing the SDK to provide the token cookie in your HTTP requests
<a name="waf-mobile-sdk-coding-auto-token-cookie"></a>

If `setTokenCookie` is `TRUE`, the token provider includes the token cookie for you in your web requests to all locations under the path that's specified in `tokenCookiePath`. By default,`setTokenCookie` is `TRUE` and `tokenCookiePath` is `/`. 

You can narrow the scope of the requests that include a token cookie by specifying the token cookie path, for example, `/web/login`. If you do this, check that your AWS WAF rules don't inspect for tokens in the requests that you send to other paths. When you use the `AWSManagedRulesACFPRuleSet` rule group, you configure the account registration and creation paths, and the rule group checks for tokens in requests that are sent to those paths. For more information, see [Adding the ACFP managed rule group to your web ACL](waf-acfp-rg-using.md). Similarly, when you use the `AWSManagedRulesATPRuleSet` rule group, you configure the login path, and the rule group checks for tokens in requests that are sent to that path. For more information, see [Adding the ATP managed rule group to your protection pack (web ACL)](waf-atp-rg-using.md). 

------
#### [ iOS ]

When `setTokenCookie` is `TRUE`, the token provider stores the AWS WAF token in a `HTTPCookieStorage.shared` and automatically includes the cookie in requests to the domain that you specified in `WAFConfiguration`.

```
let request = URLRequest(url: URL(string: domainEndpointUrl)!)
//The token cookie is set automatically as cookie header
let task = URLSession.shared.dataTask(with: request) { data, urlResponse, error  in
}.resume()
```

------
#### [ Android ]

When `setTokenCookie` is `TRUE`, the token provider stores the AWS WAF token in a `CookieHandler` instance that's shared application wide. The token provider automatically includes the cookie in requests to the domain that you specified in `WAFConfiguration`.

Java example:

```
URL url = new URL("Domain name");
//The token cookie is set automatically as cookie header
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.getResponseCode();
```

Kotlin example:

```
val url = URL("Domain name")
//The token cookie is set automatically as cookie header
val connection = (url.openConnection() as HttpsURLConnection)
connection.responseCode
```

If you already have the `CookieHandler` default instance initialized, the token provider will use it to manage cookies. If not, the token provider will initialize a new `CookieManager` instance with the AWS WAF token and `CookiePolicy.ACCEPT_ORIGINAL_SERVER` and then set this new instance as the default instance in `CookieHandler`.

The following code shows how the SDK initializes the cookie manager and cookie handler when they aren't available in your app. 

Java example:

```
CookieManager cookieManager = (CookieManager) CookieHandler.getDefault();
if (cookieManager == null) {
	// Cookie manager is initialized with CookiePolicy.ACCEPT_ORIGINAL_SERVER
	cookieManager = new CookieManager();
	CookieHandler.setDefault(cookieManager);
}
```

Kotlin example:

```
var cookieManager = CookieHandler.getDefault() as? CookieManager
if (cookieManager == null) {
	// Cookie manager is initialized with CookiePolicy.ACCEPT_ORIGINAL_SERVER
	cookieManager = CookieManager()
	CookieHandler.setDefault(cookieManager)
}
```

------

## Manually providing the token cookie in your HTTP requests
<a name="waf-mobile-sdk-coding-manual-token-cookie"></a>

If you set `setTokenCookie` to `FALSE`, then you need to provide the token cookie manually, as a Cookie HTTP request header, in your requests to your protected endpoint. The following code shows how to do this.

------
#### [ iOS ]

```
var request = URLRequest(url: wafProtectedEndpoint)
request.setValue("aws-waf-token=token from token provider", forHTTPHeaderField: "Cookie")
request.httpShouldHandleCookies = true
URLSession.shared.dataTask(with: request) { data, response, error in }
```

------
#### [ Android ]

Java example:

```
URL url = new URL("Domain name");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
String wafTokenCookie = "aws-waf-token=token from token provider";
connection.setRequestProperty("Cookie", wafTokenCookie);
connection.getInputStream();
```

Kotlin example:

```
val url = URL("Domain name")
val connection = (url.openConnection() as HttpsURLConnection)
val wafTokenCookie = "aws-waf-token=token from token provider"
connection.setRequestProperty("Cookie", wafTokenCookie)
connection.inputStream
```

------