---
title: Handlers
description: Handler objects process a request and context, and return a response. The way the response is created depends on the type of handler.
component: pinggateway
version: 2023.11
page_id: pinggateway:reference:Handlers
canonical_url: https://docs.pingidentity.com/pinggateway/2026/reference/Handlers.html
llms_txt: https://docs.pingidentity.com/pinggateway/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: 2023-10-25T18:01:40Z
superseded_by: https://docs.pingidentity.com/pinggateway/2026/reference/Handlers.html
section_ids:
  Chain: Chain
  Chain-usage: Usage
  Chain-properties: Properties
  Chain-example: Example
  Chain-moreinfo: More information
  ClientHandler: ClientHandler
  ClientHandler-usage: Usage
  ClientHandler-properties: Properties
  ClientHandler-moreinfo: More information
  DesKeyGenHandler: DesKeyGenHandler (deprecated)
  DesKeyGenHandler-usage: Usage
  DesKeyGenHandler-moreinfo: More information
  DispatchHandler: DispatchHandler
  DispatchHandler-usage: Usage
  DispatchHandler-properties: Properties
  DispatchHandler-example: Example
  DispatchHandler-moreinfo: More information
  ForgeRockClientHandler: ForgeRockClientHandler
  ForgeRockClientHandler-example: Example
  ForgeRockClientHandler-moreinfo: More information
  IdentityAssertionHandlerTechPreview: IdentityAssertionHandlerTechPreview
  IdentityAssertionHandlerTechPreview-usage: Usage
  IdentityAssertionHandlerTechPreview-example: Example
  IdentityAssertionHandlerTechPreview-moreinfo: More information
  JwkSetHandler: JwkSetHandler
  JwkSetHandler-usage: Usage
  JwkSetHandler-example: Examples
  JwkSetHandler-moreinfo: More information
  ResourceHandler: ResourceHandler
  ResourceHandler-usage: Usage
  ResourceHandler-properties: Properties
  ResourceHandler-example: Example
  ResourceHandler-moreinfo: More information
  ReverseProxyHandler: ReverseProxyHandler
  ReverseProxyHandler-usage: Usage
  ReverseProxyHandler-properties: Properties
  ReverseProxyHandler-moreinfo: More information
  Route: Route
  Route-usage: Usage
  Route-properties: Properties
  prom-route-metrics-prom: Route metrics at the Prometheus Scrape Endpoint
  prom-route-metrics-crest: Route Metrics at the Common REST Monitoring Endpoint
  route-conditions: Example conditions and requests
  Router: Router
  Router-usage: Usage
  Router-properties: Properties
  prom-router-metrics-prom: Router metrics at the Prometheus Scrape Endpoint
  prom-router-metrics-crest: Router metrics at the Common REST Monitoring Endpoint
  example: Example
  Router-moreinfo: More information
  SamlFederationHandler: SamlFederationHandler (deprecated)
  SamlFederationHandler-usage: Usage
  SamlFederationHandler-properties: Properties
  SamlFederationHandler-example: Example
  ScriptableHandler: ScriptableHandler
  ScriptableHandler-usage: Usage
  ScriptableHandler-properties: Properties
  ScriptableHandler-moreinfo: More information
  SequenceHandler: SequenceHandler
  SequenceHandler-usage: Usage
  SequenceHandler-properties: Properties
  SequenceHandler-moreinfo: More information
  StaticResponseHandler: StaticResponseHandler
  StaticResponseHandler-usage: Usage
  StaticResponseHandler-properties: Properties
  StaticResponseHandler-example: Example
  StaticResponseHandler-moreinfo: More information
---

# Handlers

Handler objects process a request and context, and return a response. The way the response is created depends on the type of handler.

## Chain

Dispatches a request and context to an ordered list of filters, and then finally to a handler.

Filters process the incoming request and context, pass it on to the next filter, and then to the handler. After the handler produces a response, the filters process the outgoing response and context as it makes its way to the client. Note that the same filter can process both the incoming request and the outgoing response but most filters do one or the other.

A Chain can be placed in a configuration anywhere that a handler can be placed.

Unlike ChainOfFilters, Chain finishes by dispatching the request to a handler. For more information, refer to [ChainOfFilters](Filters.html#ChainOfFilters).

### Usage

```json
{
     "name": string,
     "type": "Chain",
     "config": {
         "filters": [ Filter reference, ... ],
         "handler": Handler reference
     }
}
```

### Properties

* `"filters"`: *array of Filter [references](preface.html#definition-reference), required*

  An array of names of filter objects defined in the heap, and inline filter configuration objects.

  The chain dispatches the request to these filters in the order they appear in the array.

  See also [Filters](Filters.html).

* `"handler"`: *Handler [reference](preface.html#definition-reference), required*

  The [Handler](#) to which the Chain dispatches the request after it has traversed the specified filters.

  Provide the name of a Handler object defined in the heap or an inline Handler configuration object.

### Example

```json
{
     "name": "LoginChain",
     "type": "Chain",
     "config": {
         "filters": [ "LoginFilter" ],
         "handler": "ReverseProxyHandler"
     }
}
```

### More information

[org.forgerock.openig.filter.ChainHandlerHeaplet](../_attachments/apidocs/org/forgerock/openig/filter/ChainHandlerHeaplet.html)

## ClientHandler

Sends requests to third-party services that are accessible through HTTP, and reconstructs the response from the received bytes. A third-party service is one that IG calls for data, such as an HTTP API or AM, or one to which IG submits data. When IG relays a request to a third-party service, IG is acting as a client of the service. IG is *client-side*.

Consider the following comparison of the ClientHandler and ReverseProxyHandler:

|                                                          | ClientHandler                                                                                                                                                                                      | ReverseProxyHandler                                                                                          |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Use this handler to …​                                   | Send requests to third-party services accessed within a route. The service can be AM or an HTTP API. The service can be an HTTP endpoint, such as AM, IDM, Identity Cloud, or any custom HTTP API. | Send requests to the final service accessed by a route. The service can be the final downstream application. |
| If the service does not respond in time, this handler …​ | Propagates the error through the Promise flow\.If the error is not handled within the route, for example, by a FailureHandler, the handler returns a `500 Internal Server Error` response.         | Stops processing the request, and returns a `502 Bad Gateway` response.                                      |

When uploading or downloading large files, prevent timeout issues by increasing the value of `soTimeout`, and using a streaming mode, as follows:

Configure the `streamingEnabled` property of [AdminHttpApplication](RequiredConfiguration.html).

### Usage

```json
{
  "name": string,
  "type": "ClientHandler",
  "config": {
    "vertx": object,
    "connections": configuration expression<number>,
    "waitQueueSize": configuration expression<number>,
    "disableReuseConnection": configuration expression<boolean>, //*
    "stateTrackingEnabled": configuration expression<boolean>, //*
    "soTimeout": configuration expression<duration>,
    "connectionTimeout": configuration expression<duration>,
    "connectionTimeToLive": configuration expression<duration>, //*
    "numberOfWorkers": configuration expression<number>, //*
    "protocolVersion": configuration expression<enumeration>,
    "http2PriorKnowledge": configuration expression<boolean>,
    "proxyOptions": ProxyOptions reference,
    "temporaryStorage": TemporaryStorage reference,
    "tls": ClientTlsOptions reference,
    "asyncBehavior": configuration expression<enumeration>, //*
    "retries": object,
    "circuitBreaker": object,
    "hostnameVerifier": configuration expression<enumeration>, //deprecated
    "proxy": Server reference, //deprecated
    "systemProxy": boolean //deprecated
  }
}
```

\* Legacy; no longer supported

### Properties

* `"vertx"`: *[object](preface.html#definition-object), optional*

  Vert.x-specific configuration for the handler when IG is *client-side*. When IG is acting server-side, configure the `connectors:vertx` property of [admin.json](AdminHttpApplication.html).

  |   |                                                                                                                                                                                                                 |
  | - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | When IG sends requests to a proxied application or requests services from a third-party application, IG is client-side. IG is acting as a client of the application, and the application is acting as a server. |

  Vert.x options are described in [HttpClientOptions](https://vertx.io/docs/4.5.17/apidocs/io/vertx/core/http/HttpClientOptions.html).

  The `vertx` object is read as a map, and values are evaluated as configuration expressions.

  For properties where IG provides its own first-class configuration, Vert.x configuration options are disallowed, and the IG configuration option takes precedence over Vert.x options configured in `vertx`. The following Vert.x configuration options are disallowed client-side:

  * `alpnVersions`

  * `connectTimeout`

  * `enabledCipherSuites`

  * `enabledSecureTransportProtocols`

  * `http2ClearTextUpgrade`

  * `idleTimeout`

  * `idleTimeoutUnit`

  * `keyCertOptions`

  * `keyStoreOptions`

  * `maxWaitQueueSize`

  * `pemKeyCertOptions`

  * `pemTrustOptions`

  * `pfxKeyCertOptions`

  * `pfxTrustOptions`

  * `port`

  * `protocolVersion`

  * `proxyOptions`

  * `ssl`

  * `trustOptions`

  * `trustStoreOptions`

  * `useAlpn`

  * `verifyHost`

  The following example configures the Vert.x configuration when IG is acting client-side. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

  ```json
  {
    "vertx": {
      "maxWebSocketFrameSize": 128000,
      "maxWebSocketMessageSize": 256000,
      "compressionLevel": 4,
      "maxHeaderSize": 16384
    }
  }
  ```

  The following example configures HTTP/2 connections when IG is acting client-side. The configuration allows IG to make HTTP/2 requests with large headers. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

  ```json
  {
    "vertx": {
      "initialSettings": {
        "maxHeaderListSize": 16384
      }
    }
  }
  ```

* `"connections"`: *configuration expression<[number](preface.html#definition-number)>, optional*

  The maximum number of concurrent HTTP connections in the client connection pool.

  For information about the interaction between this property and `waitQueueSize`, see the description of `waitQueueSize`.

  Default: 64

* "waitQueueSize": *configuration expression<[number](preface.html#definition-number)>, optional*

  The maximum number of outbound requests allowed to queue when no downstream connections are available. Outbound requests received when the queue is full are rejected.

  Use this property to limit memory use when there is a backlog of outbound requests, for example, when the protected application or third-party service is slow.

  Configure `waitQueueSize` as follows:

  * Not set (default): The wait queue is calculated as the square of `connections`.

    * If `connections` is not configured, then its default of `64` is used, giving the `waitQueueSize` of `4096`.

    * If the square of `connections` exceeds the maximum integer value for the Java JVM, the maximum integer value for the Java JVM is used.

  * `-1`: The wait queue is unlimited. Requests received when there are no available connections are queued without limit.

  * `0`: There is no wait queue. Requests received when there are no available connections are rejected.

  * A value that is less than the square of `connections`:

    When the configuration is loaded, the configured value is used. IG generates a warning that the `waitQueueSize` is too small for the `connections` size, and recommends a different value.

  * A value where `waitQueueSize` plus `connections` exceeds the maximum integer value for the Java JVM:

    When the configuration is loaded, the `waitQueueSize` is reduced to the maximum integer value for the Java JVM minus the value of `connections`. IG generates a warning.

  Consider the following example configuration of `connections` and `waitQueueSize`:

  ```json
  {
    "handler" : {
      "name" : "proxy-handler",
      "type" : "ReverseProxyHandler",
      "MyCapture" : "all",
      "config": {
        "soTimeout": "10 seconds",
        "connectionTimeout": "10 seconds",
        "connections": 64,
        "waitQueueSize": 100
      }
    },
    "baseURI" : "http://app.example.com:8080",
    "condition" : "${find(request.uri.path, '/')}"
  }
  ```

  IG can propagate the request to the sample application using 64 connections. When the connections are consumed, up to 100 subsequent requests are queued until a connection is freed. Effectively IG can accommodate 164 requests, although user concurrency delay means more may be handled. Requests received when the waitQueue is full are rejected.

  Default: Not set

* `"connectionTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Time to wait to establish a connection, expressed as a duration

  Default: 10 seconds

* `"connectionTimeToLive"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Not supported

* `"disableReuseConnection"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  Not supported

* `"stateTrackingEnabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  Not supported

* `"numberOfWorkers"`: *configuration expression<[number](preface.html#definition-number)>, optional*

  Not supported

* `"protocolVersion"`: *configuration expression<[enumeration](preface.html#definition-enumeration)>, optional*

  The version of HTTP protocol to use when processing requests:

  * `HTTP/2`:

    * For HTTP, process requests using HTTP/1.1.

    * For HTTPS, process requests using HTTP/2.

  * `HTTP/1.1`:

    * For HTTP and HTTPS, process requests using HTTP/1.1.

  * Not set:

    * For HTTP, process requests using HTTP/1.1.

    * For HTTPS with `alpn` enabled in ClientTlsOptions, process requests using HTTP/1.1, with an HTTP/2 upgrade request. If the targeted server can use HTTP/2, the client uses HTTP/2.

      For HTTPS with `alpn` disabled in ClientTlsOptions, process requests using HTTP/1.1, without an HTTP/2 upgrade request.

      Note that `alpn` is enabled by default in ClientTlsOptions.

  Default: Not set

|   |                                                                                                                                                                                                                                                                                                                                      |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | In HTTP/1.1 request messages, a `Host` header is required to specify the host and port number of the requested resource. In HTTP/2 request messages, the `Host` header is not available.In scripts or custom extensions that use HTTP/2, use `UriRouterContext.originalUri.host` or `UriRouterContext.originalUri.port` in requests. |

* `"http2PriorKnowledge"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  A flag for whether the client should have prior knowledge that the server supports HTTP/2. This property is for cleartext (non-TLS requests) only, and is used only when `protocolVersion` is HTTP/2.

  * `false`: The client checks whether the server supports HTTP/2 by sending an HTTP/1.1 request to upgrade the connection to HTTP/2:

    * If the server supports HTTP/2, the server upgrades the connection to HTTP/2, and subsequent requests are processed over HTTP/2.

    * If the server does not support HTTP/2, the connection is not upgraded, and subsequent requests are processed over HTTP/1.

  * `true`: The client does not check that the server supports HTTP/2. The client sends HTTP/2 requests to the server, assuming that the server supports HTTP/2.

  Default: `false`

* `"proxyOptions"`: *ProxyOptions [reference](preface.html#definition-reference), optional*

  A proxy server to which requests can be submitted. Use this property to relay requests to other parts of the network. For example, use it to submit requests from an internal network to the internet.

  Provide the name of a [ProxyOptions](ProxyOptions.html) object defined in the heap or an inline configuration.

  Default: A heap object named `ProxyOptions`.

- `"soTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Socket timeout, after which stalled connections are destroyed, expressed as a duration.

  |   |                                                                                                                                       |
  | - | ------------------------------------------------------------------------------------------------------------------------------------- |
  |   | If `SocketTimeoutException` errors occur in the logs when you try to upload or download large files, consider increasing `soTimeout`. |

  Default: 10 seconds

- `"temporaryStorage"`: *TemporaryStorage [reference](preface.html#definition-reference), optional*

  The [TemporaryStorage](TemporaryStorage.html) object to buffer the request and response, when the `streamingEnabled` property of [admin.json](AdminHttpApplication.html) is `false`.

  Default: A heap object named `TemporaryStorage`.

- `tls`: *ClientTlsOptions [reference](preface.html#definition-reference), optional*

  |   |                                                                                                                                                                                                                                     |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | Use of a TlsOptions reference is deprecated; use ClientTlsOptions instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Configure options for connections to TLS-protected endpoints, based on [ClientTlsOptions](MiscellaneousConfigurationObjects.html#ClientTlsOptions). Define the object inline or in the heap.

  Default: Connections to TLS-protected endpoints are not configured.

- \`"asyncBehavior": *configuration expression<[enumeration](preface.html#definition-enumeration)>, optional*

  Not supported

- `"retries"`: *[object](preface.html#definition-object), optional*

  Enable and configure retry for requests.

  During the execution of a request to a remote server, if a runtime exception occurs, or a condition is met, IG waits for a delay, and then schedules a new execution of the request. IG tries until the allowed number of retries is reached or the execution succeeds.

  A warning-level entry is logged if all retry attempts fail; a debug-level entry is logged if a retry succeeds.

  ```json
  "retries": {
    "enabled": configuration expression<boolean>,
    "condition": runtime expression<boolean>,
    "executor": ScheduledExecutorService reference,
    "count": configuration expression<number>,
    "delay": configuration expression<duration>,
    }
  }
  ```

  * `"enabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

    Enable retries.

    Default: `true`

  * `"condition"`: *runtine expression<[boolean](preface.html#definition-boolean)>, optional*

    An inline IG [expression](Expressions.html#Expressions) to define a condition based on the response, such as an error code.

    The condition is evaluated as follows:

    * If `true`, IG retries the request until the value in `count` is reached.

    * If `false`, IG retries the request only if a runtime exception occurs, until the value in `count` is reached.

      Default: `${false}`

  * `"executor"`: *ScheduledExecutorService [reference](preface.html#definition-reference), optional*

    The ScheduledExecutorService to use for scheduling delayed execution of the request.

    Default: `ScheduledExecutorService`

    See also [ScheduledExecutorService](MiscellaneousConfigurationObjects.html#ScheduledExecutorService).

  * `"count"`: *configuration expression<[number](preface.html#definition-number)>, optional*

    The maximum number of retries to perform. After this threshold is passed and if the request is still not successful, then the ClientHandler propagates the failure.

    Retries caused by any runtime exception or triggered condition are included in the count.

    Default: `5`

  * `"delay"`: *\_configuration expression<[duration](preface.html#definition-duration)>, optional*

    The time to wait before retrying the request.

    After a failure to send the request, if the number of retries is below the threshold, a new attempt is scheduled with the executor service after this delay.

    Default: `10 seconds`

  The following example configures a retry when a downstream component returns a `502 Bad Gateway` response code:

  ```json
  "retries": {
      "enabled": true,
      "condition": "${response.status.code == 502}"
  }
  ```

  The following example configures the handler to retry the request only once, after a 1-minute delay:

  ```json
  {
    "retries": {
      "count": 1,
      "delay": "1 minute"
    }
  }
  ```

  The following example configures the handler to retry the request at most 20 times, every second:

  ```json
  {
    "retries": {
      "count": 20,
      "delay": "1 second"
    }
  }
  ```

  The following example configures the handler to retry the request 5 times, every 10 seconds (default values), with a dedicated executor:

  ```json
  {
    "retries": {
      "executor": {
        "type": "ScheduledExecutorService",
        "config": {
          "corePoolSize": 20
        }
      }
    }
  }
  ```

- `"circuitBreaker"`: *[object](preface.html#definition-object), optional*

  Enable and configure a circuit breaker to trip when the number of failures exceeds a configured threshold. Calls to downstream services are stopped, and a runtime exception is returned. The circuit breaker is reset after the configured delay.

  ```json
  {
    "circuitBreaker": {
      "enabled": configuration expression<boolean>,
      "maxFailures":  configuration expression<integer>,
      "openDuration": configuration expression<duration>,
      "openHandler": Handler reference,
      "slidingCounter":  object,
      "executor":  ScheduledExecutorService reference
    }
  }
  ```

  * `"enabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

    A flag to enable the circuit breaker.

    Default: `true`

  * `"maxFailures"`: *configuration expression<[number](preface.html#definition-number)>, required*

    The maximum number of failed requests allowed in the window given by `size`, before the circuit breaker trips. The value must be greater than zero.

    |   |                                                                                                                                                                                                                                                                                                                                                                                                               |
    | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | When `retries` is set, the circuit breaker does not count retried requests as failures. Bear this in mind when you set `maxFailures`.In the following example, a request can fail and then be retried three times. If it fails the third retry, the request has failed four times, but the circuit breaker counts only one failure.```json
    {
      "retries": {
        "count": 3,
        "delay": "1 second"
      }
    }
    ``` |

  * `"openDuration"`: *configuration expression<[duration](preface.html#definition-duration)>, required*

    The duration for which the circuit stays open after the circuit breaker trips. The `executor` schedules the circuit to be closed after this duration.

  * `"openHandler"`: *Handler [reference](preface.html#definition-reference), optional*

    The [Handler](#) to call when the circuit is open.

    Default: A handler that throws a RuntimeException with a "circuit-breaker open" message.

  * `"slidingCounter"`: *[object](preface.html#definition-object), optional*

    A sliding window error counter. The circuit breaker trips when the number of failed requests in the number of requests given by `size` reaches `maxFailures`.

    The following image illustrates how the sliding window counts failed requests:

    ![Example sliding window error counter.](_images/sliding-window.svg)

    ```json
    {
      "slidingCounter":  {
        "size": configuration expression<number>
      }
    }
    ```

    * `"size"`: *configuration expression<[number](preface.html#definition-number)>, required*

      The size of the sliding window in which to count errors.

      The value of `size` must be greater than zero, and greater than the value of `maxFailures`, otherwise an exception is thrown.

  * `"executor"`: *ScheduledExecutorService [reference](preface.html#definition-reference), optional*

    A [ScheduledExecutorService](MiscellaneousConfigurationObjects.html#ScheduledExecutorService) to schedule closure of the circuit after the duration given by `openDuration`.

    Default: The default ScheduledExecutorService in the heap

- `"hostnameVerifier"`: *configuration expression\<enumeration>, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The way to handle hostname verification for outgoing SSL connections. Use one of the following values:

  * `ALLOW_ALL`: Allow a certificate issued by a trusted CA for any hostname or domain to be accepted for a connection to any domain.

    This setting allows a certificate issued for one company to be accepted as a valid certificate for another company. To prevent the compromise of TLS connections, use this setting in development mode only. In production, use `STRICT`.

  * `STRICT`: Match the hostname either as the value of the the first CN, or any of the subject-alt names.

    A wildcard can occur in the CN, and in any of the subject-alt names. Wildcards match one domain level, so `*.example.com` matches `www.example.com` but not `some.host.example.com`.

  Default: `STRICT`

- `"proxy"`: *Server reference, optional*

  |   |                                                                                                                                                                                                                   |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use `proxyOptions` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  A proxy server to which requests can be submitted. Use this property to relay requests to other parts of the network. For example, use it to submit requests from an internal network to the internet.

  If both `proxy` and `systemProxy` are defined, `proxy` takes precedence.

  ```json
  "proxy" : {
    "uri": configuration expression<uri string>,
    "username": configuration expression<string>,
    "passwordSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "password": configuration expression<string> //deprecated
  }
  ```

  * `"uri"`: *configuration expression\<uri string>, required*

    URI of a server to use as a proxy for outgoing requests.

    The result of the expression must be a string that represents a valid URI, but is not a real java.net.URI object.

  * `"username"`: *configuration expression\<string>, required if the proxy requires authentication*

    Username to access the proxy server.

  * `"passwordSecretId"`: *configuration expression\<secret-id>, required if the proxy requires authentication*

    The secret ID of the password to access the proxy server.

    This secret ID must point to a [GenericSecret](../security-guide/keys.html#secret-types).

  * `"secretsProvider"`: *SecretsProvider reference, optional*

    The SecretsProvider to query for the proxy's password.

  * `"password"`: *configuration expression\<string>, required if the proxy requires authentication*

    |   |                                                                                                                                                                                                                                                    |
    | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | This property is deprecated and is not considered secure. Use `passwordSecretId` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

    Password to access the proxy server.

- `"systemProxy"`: *boolean, optional*

  |   |                                                                                                                                                                                                                   |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use `proxyOptions` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Submit outgoing requests to a system-defined proxy, set by the following system properties or their HTTPS equivalents:

  * `http.proxyHost`, the host name of the proxy server.

  * `http.proxyPort`, the port number of the proxy server. The default is `80`.

  * `http.nonProxyHosts`, a list of hosts that should be reached directly, bypassing the proxy.

  This property can't be used with a proxy that requires a username and password. Use the property `proxy` instead.

  If both `proxy` and `systemProxy` are defined, `proxy` takes precedence.

  For more information, refer to [Java Networking and Proxies](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/doc-files/net-properties.html).

  Default: False.

- `"keyManager"`: *Key manager reference(s), optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The key manager(s) that handle(s) this client's keys and certificates.

  The value of this field can be a single reference, or an array of references.

  Provide either the name(s) of key manager object(s) defined in the heap, or specify the configuration object(s) inline.

  You can specify either a single key manager, as in `"keyManager": "MyKeyManager"`, or an array of key managers, as in `"keyManager": [ "FirstKeyManager", "SecondKeyManager" ]`.

  If you do not configure a key manager, then the client cannot present a certificate, and so cannot play the client role in mutual authentication.

- `"sslCipherSuites"`: *array of strings, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Array of cipher suite names, used to restrict the cipher suites allowed when negotiating transport layer security for an HTTPS connection.

  For information about the available cipher suite names, refer to the documentation for the Java virtual machine (JVM) where you run IG. For Oracle Java, refer to the list of [JSSE Cipher Suite Names](https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#jsse-cipher-suite-names).

  Default: Allow any cipher suite supported by the JVM.

- `"sslContextAlgorithm"`: *string, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The SSLContext algorithm name, as listed in the table of SSLContext Algorithms for the Java Virtual Machine used by IG.

  Default: TLS

- `"sslEnabledProtocols"`: *array of strings, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Array of protocol names, used to restrict the protocols allowed when negotiating transport layer security for an HTTPS connection.

  Default: Allow any protocol supported by the JVM.

- `"trustManager"`: *Trust manager reference(s), optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The trust managers that handle(s) peers' public key certificates.

  The value of this field can be a single reference, or an array of references.

  Provide either the name(s) of trust manager object(s) defined in the heap, or specify the configuration object(s) inline.

  You can specify either a single trust manager, as in `"trustManager": "MyTrustManager"`, or an array of trust managers, as in `"trustManager": [ "FirstTrustManager", "SecondTrustManager" ]`.

  If you do not configure a trust manager, then the client uses only the default Java truststore. The default Java truststore depends on the Java environment. For example, `$JAVA_HOME/lib/security/cacerts`.

### More information

[org.forgerock.openig.handler.ClientHandlerHeaplet](../_attachments/apidocs/org/forgerock/openig/handler/ClientHandlerHeaplet.html)

## DesKeyGenHandler (deprecated)

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | This object is deprecated and not considered secure. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*.Consider using AM's password replay post-authentication plugin class `com.sun.identity.authentication.spi.JwtReplayPassword`. The plugin encrypts the password captured by AM during authentication, and stores it in a session property. IG looks up the property, decrypts it, and replays the password. [Authenticate with credentials from AM](../gateway-guide/sso-cdsso.html#credentials-am). |

Generates a DES key for use with AM.

### Usage

```json
{
    "name": string,
    "type": "DesKeyGenHandler"
}
```

### More information

[org.forgerock.openig.handler.DesKeyGenHandler](../_attachments/apidocs/org/forgerock/openig/handler/DesKeyGenHandler.html)

## DispatchHandler

When a request is handled, the first condition in the list of conditions is evaluated. If the condition expression yields `true`, the request is dispatched to the associated handler with no further processing. Otherwise, the next condition in the list is evaluated.

### Usage

```json
{
  "name": string,
  "type": "DispatchHandler",
  "config": {
    "bindings": [
      {
        "condition": runtime expression<boolean>,
        "handler": Handler reference,
        "baseURI": runtime expression<url>,
      }, ...
    ]
  }
}
```

### Properties

* `"bindings"`: *array of [objects](preface.html#definition-object), required*

  One or more condition and handler bindings.

  * `"condition"`: *runtime expression<[boolean](preface.html#definition-boolean)>, optional*

    A flag to indicate that a condition is met. The condition can be based on the request, context, or IG runtime environment, such as system properties or environment variables.

    Conditions are defined using IG expressions, as described in [Expressions](Expressions.html#Expressions), and are evaluated as follows:

    * `true`: The request is dispatched to the associated handler.

    * `false`: The next condition in the list is evaluated.

    For examples, refer to [Example conditions and requests](Route.html#route-conditions).

    Default: `${true}`

  * `"handler"`: *Handler [reference](preface.html#definition-reference), required*

    The [Handler](#) to which IG dispaches the request if the associated condition yields `true`.

    Provide the name of a Handler object defined in the heap or an inline Handler configuration object.

  * `"baseURI"`: *runtime expression<[url](preface.html#definition-url)>,optional*

    A base URI that overrides the existing request URI. Only scheme, host, and port are used in the supplied URI.

    The result of the expression must be a string that represents a valid URI, but is not a real `java.net.URI` object. For example, it would be incorrect to use `${request.uri}`, which is not a String but a MutableUri.

    In the following example, the binding condition looks up the hostname of the request. If it finds a match, the value is used for the `baseURI`. Otherwise, the default value is used:

    ```json
    {
      "properties": {
        "uris": {
          "app1.example.com": {
            "baseURI": "http://backend1:8080/"
          },
          "app2.example.com": {
            "baseURI": "http://backend2:8080/"
          },
          "default": {
            "baseURI": "http://backend3:8080/"
          }
        }
      },
      "handler": {
        "type": "DispatchHandler",
        "config": {
          "bindings": [
            {
              "condition": "${not empty uris[contexts.router.originalUri.host]}",
              "baseURI": "${uris[contexts.router.originalUri.host].baseURI}",
              "handler": "ReverseProxyHandler"
            },
            {
              "baseURI": "${uris['default'].baseURI}",
              "handler": "ReverseProxyHandler"
            }
          ]
        }
      }
    }
    ```

    Default: No change to the base URI

### Example

For an example that uses a DispatchHandler, refer to [Implement not-enforced URIs with a DispatchHandler](../gateway-guide/not-enforced-uri.html#not-enforced-uri.html#not-enforced-uri-dispatch)

### More information

[org.forgerock.openig.handler.DispatchHandler](../_attachments/apidocs/org/forgerock/openig/handler/DispatchHandler.html)

[Expressions](Expressions.html#Expressions)

## ForgeRockClientHandler

The ForgeRockClientHandler is a Handler available by default on the heap that chains a default [ClientHandler](ClientHandler.html) with a [TransactionIdOutboundFilter](TransactionIdOutboundFilter.html).

This Handler supports ForgeRock audit by supporting the initiation or propagation of audit information from IG to the audit framework. For more information, see [AuditService](AuditService.html).

The following default ForgeRockClientHandler is available as a default object on the heap, and can be referenced by the name ForgeRockClientHandler.

```json
{
     "name": "ForgeRockClientHandler",
     "type": "Chain",
     "config": {
         "filters": [ "TransactionIdOutboundFilter" ],
         "handler": "ClientHandler"
     }
}
```

### Example

For an example that uses ForgeRockClientHandler to log interactions between IG and AM, see [Decorating IG's interactions with AM](../configure/decorators.html#decorators-ig-am).

### More information

[org.forgerock.openig.heap.Keys](../_attachments/apidocs/org/forgerock/openig/heap/Keys.html)

## IdentityAssertionHandlerTechPreview

|   |                                                                                                                                                                                                                                                                                                                                                                       |
| - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The IdentityAssertionHandlerTechPreview, ScriptableIdentityAssertionPluginTechPreview, and IdentityAssertionPluginTechPreview are available in [Technology preview](https://docs.pingidentity.com/pinggateway/release-notes/stability.html#interface-stability). They aren't yet supported, may be functionally incomplete, and are subject to change without notice. |

Use in an Identity Cloud authentication journey with a Gateway Communication node. For more information, refer to Identity Cloud's [Gateway Communication overview](https://docs.pingidentity.com/auth-node-ref/latest/cloud/auth-node-gateway-comm.html).

The IdentityAssertionHandlerTechPreview sets up an IdentityAssertionPluginTechPreview to manage local processing, such as authentication. The Handler then calls the plugin at runtime for each request.

An Identity Cloud authentication journey does the following:

* Redirects users to IG for local authentication.

* After local authentication, provides and identity assertion and redirects users back to the Identity Cloud authentication journey.

The Identity Cloud authentication journey provides:

* A cryptographically-secure random value in a nonce to validate the identity assertion.

* A `returnUri` to redirect the user back to Identity Cloud to continue the authentication journey.

Exceptions during local processing cause a redirect with an assertion JWT containing an `assertionError` claim. Exceptions that prevent the return of a valid assertion, such as an invalid incoming JWT or key error, cause an HTTP 500.

### Usage

```json
{
  "name": string,
  "type": "IdentityAssertionHandlerTechPreview",
  "config": {
    "identityAssertionPlugin": IdentityAssertionPluginTechPreview reference,
    "selfIdentifier": configuration expression<string>,
    "peerIdentifier": configuration expression<string>,
    "expire": configuration expression<duration>,
    "secretsProvider": Secrets Provider reference,
    "verificationSecretId": configuration expression<secret-id>,
    "decryptionSecretId": configuration expression<secret-id>,
    "skewAllowance": configuration expression<duration>,
    "signature": object
  }
}
```

* `"identityAssertionPlugin"`: *configuration expression<[string](preface.html#definition-string)>, required*

  An implementation of [org.forgerock.openig.handler.assertion.IdentityAssertionPluginTechPreview](../_attachments/apidocs/org/forgerock/openig/handler/assertion/IdentityAssertionPluginTechPreview.html).

  An out-of-the box implementation is available in [ScriptableIdentityAssertionPluginTechPreview](MiscellaneousConfigurationObjects.html#ScriptableIdentityAssertionPluginTechPreview).

* `"selfIdentifier"`: *configuration expression<[string](preface.html#definition-string)>, required*

  An identifier to validate that this IG instance is the right audience for the incoming JWT from Identity Cloud. The same identifier is used for the `iss` claim of the outgoing JWT sent to Identity Cloud.

  Can't be null.

* `"peerIdentifier"`: *configuration expression<[string](preface.html#definition-string)>, required*

  An identifier to validate that the incoming JWT is from the expected peer. The same identifier is used for the `aud` claim in the outgoing JWT sent Identity Cloud.

  Can't be null.

* `"expire"`: *[duration](preface.html#definition-duration), optional*

  The expiry time of the outgoing JWT sent to Identity Cloud.

  Default: 30 seconds

* `"secretsProvider"`: *SecretsProvider [reference](preface.html#definition-reference), optional*

  The [SecretsProvider](secrets.html#SecretsProvider) to resolve queried cryptographic keys.

  Default: The route's default secret service. For more information, refer to [Default secrets object](secrets.html#default-secrets-object).

* `"verificationSecretId"`: *configuration expression<[secret-id](preface.html#definition-secretid)>, required*

  The secret ID for the secret to validate the signature of the incoming JWT. The secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

* `"decryptionSecretId"`: *configuration expression<[secret-id](preface.html#definition-secretid)>, optional*

  The secret ID for the secret to decrypt the incoming JWT. The secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

  When this property isn't set, IG treats the incoming JWT as signed but not encrypted.

  Default: Not set.

- `"skewAllowance"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  The duration to add to the validity period of a JWT to allow for clock skew between different servers. To support a zero-trust policy, the skew allowance is by default zero.

  A `skewAllowance` of 2 minutes affects the validity period as follows:

  * A JWT with an `iat` of 12:00 is valid from 11:58 on the IG clock.

  * A JWT with an `exp` 13:00 is expired after 13:02 on the IG clock.

  Default: `zero`

- `"signature"`: *[object](preface.html#definition-object), required*

  A JWT signature to validate the authenticity of claims or data for the outgoing JWT.

  ```json
  {
    "signature": {
      "secretId": configuration expression<secret-id>,
      "algorithm": configuration expression<string>,
      "encryption": object
    }
  }
  ```

  * `"secretId"`: *[secret-id](preface.html#definition-secretid), required*

    The secret ID of the signing key. The secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

  * `"algorithm"`: *configuration expression<[string](preface.html#definition-string)>, optional*

    The signing algorithm.

    Default: `RS256`

  * `"encryption"`: *[object](preface.html#definition-object), required*

    Configuration to encrypt the JWT.

    ```json
    {
      "encryption": {
        "secretId": configuration expression<secret-id>,
        "algorithm": configuration expression<string>,
        "method": configuration expression<string>
      }
    }
    ```

    * `"secretId"`: *[secret-id](preface.html#definition-secretid), required*

      The secret ID of the encryption key. The secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

    * `"algorithm"`: *configuration expression<[string](preface.html#definition-string)>, required*

      The encryption algorithm. Use an algorithm from the [List of JWS Algorithms](https://tools.ietf.org/html/rfc7518#section-3).

    * `"method"`: *configuration expression<[string](preface.html#definition-string)>, required*

      The encryption method. Use a method from the [List of JWE Algorithms](https://tools.ietf.org/html/rfc7518#section-4.1).

### Example

The following example route is for a Identity Cloud authentication journey that uses a [Gateway Communication node](https://docs.pingidentity.com/auth-node-ref/latest/cloud/auth-node-gateway-comm.html).

For information about the `identityAssertionPlugin` object, refer to the example in [ScriptableIdentityAssertionPluginTechPreview](ScriptableIdentityAssertionPluginTechPreview.html).

```json
{
  "type": "IdentityAssertionHandlerTechPreview",
  "config": {
    "identityAssertionPlugin": "BasicAuthScriptablePlugin",
    "selfIdentifier": "identity-gateway",
    "peerIdentifier": "gateway-communication-node",
    "secretsProvider": [
      "IG-Decrypt",
      "Node-Verify",
      "IG-Sign",
      "Node-Encrypt"
    ],
    "verificationSecretId": "id.key.for.verifying.incoming.jwt",
    "decryptionSecretId": "id.key.for.decrypting.incoming.jwt",
    "signature": {
      "secretId": "id.key.for.signing.assertion.jwt",
      "algorithm": "RS256",
      "encryption": {
        "secretId": "id.key.for.encrypting.assertion.jwt",
        "algorithm": "RSA-OAEP-256",
        "method": "A256GCM"
      }
    }
  }
}
```

### More information

[org.forgerock.openig.handler.assertion.IdentityAssertionPluginTechPreview](../_attachments/apidocs/org/forgerock/openig/handler/assertion/IdentityAssertionPluginTechPreview.html).

## JwkSetHandler

Expose cryptographic keys as a JWK set. Use this handler to reuse exposed keys for their assigned purpose in a downstream application.

Consider the following limitations:

* When the public key isn't available, the corresponding private key can't be exposed.

  |   |                                                          |
  | - | -------------------------------------------------------- |
  |   | You are not recommended to expose private keys as a JWK. |

* Keys in secure storage, such as a Hardware Security Module (HSM) or remote server, can't be exposed.

For a description of how secrets are managed, refer to [About secrets](../security-guide/keys.html#about-secrets).

For information about JWKs and JWK Sets, refer to [JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517).

### Usage

```json
{
  "name": string,
  "type": "JwkSetHandler",
  "config": {
    "secretsProvider": SecretsProvider reference,
    "purposes": [ object, ... ],
    "exposePrivateSecrets": configuration expression<boolean>
  }
}
```

* `"secretsProvider"`: *SecretsProvider [reference](preface.html#definition-reference), required*

  The [SecretsProvider](secrets.html#SecretsProvider) to use to resolve the secret. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

* `"purposes"`: *array of [objects](preface.html#definition-object), required*

  One or more purposes for the secret.

```json
{
  "purposes": [
    {
      "secretId": configuration expression<secret-id>,
      "keyUsage": configuration expression<enumeration>
    },
    ...
  ]
}
```

* `"secretId"`: *configuration expression<[secret-id](preface.html#definition-secretid)>, required*

  The secret ID of the key to be exposed in the JwkSet.

  This secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

* `"keyUsage"`: *configuration expression<[enumeration](preface.html#definition-enumeration)>, required*

  The allowed use of the key:

  * `AGREE_KEY`: Export the private key used in the key agreement protocol, for example, Diffie-Hellman.

  * `ENCRYPT`: Export the public key used to encrypt data.

  * `DECRYPT`: Export the private key used to decrypt data.

  * `SIGN`: Export the private key used to sign data.

  * `VERIFY`: Export the public key used to verify signature data.

  * `WRAP_KEY`: Export the public key used to encrypt (wrap) other keys.

  * `UNWRAP_KEY`: Export the private key used to decrypt (unwrap) other keys.

* `exposePrivateSecrets`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  A flag indicating whether to publish private keys in a JWK set. As a security safeguard, this property is `false` by default to prevent the accidental exposure of private keys.

  `true`: Publish both public and private keys in the JWK set `false`: Publish only public keys in the JWK set

  Default: `false`

### Examples

This example uses a JwkSetHandler to expose a signing key used by the JwtBuilderFilter:

1. Set an environment variable for the base64-encoded secret to sign the JWT:

   ```bash
   $ export SIGNING_KEY_SECRET_ID='cGFzc3dvcmQ='
   ```

2. Add the following route to IG:

   * Linux

   * Windows

   ```
   $HOME/.openig/config/routes/jwksethandler.json
   ```

   ```
   %appdata%\OpenIG\config\routes\jwksethandler.json
   ```

   ```json
   {
     "name": "jwksethandler",
     "condition": "${find(request.uri.path, '/jwksethandler')}",
     "heap": [
       {
         "name": "SecretKeyPropertyFormat-1",
         "type": "SecretKeyPropertyFormat",
         "config": {
           "format": "BASE64",
           "algorithm": "AES"
         }
       },
       {
         "name": "SystemAndEnvSecretStore-1",
         "type": "SystemAndEnvSecretStore",
         "config": {
           "mappings": [{
             "secretId": "signing.key.secret.id",
             "format": "SecretKeyPropertyFormat-1"
           }]
         }
       }
     ],
     "handler": {
       "type": "Chain",
       "config": {
         "filters": [
           {
             "name": "JwtBuilderFilter-1",
             "type": "JwtBuilderFilter",
             "config": {
               "template": {
                 "name": "${contexts.userProfile.commonName}",
                 "email": "${contexts.userProfile.rawInfo.mail[0]}"
               },
               "secretsProvider": "SystemAndEnvSecretStore-1",
               "signature": {
                 "secretId": "signing.key.secret.id",
                 "algorithm": "HS256"
               }
             }
           }
         ],
         "handler": {
           "type": "JwkSetHandler",
           "config": {
             "secretsProvider": "SystemAndEnvSecretStore-1",
             "purposes": [{
               "secretId": "signing.key.secret.id",
               "keyUsage": "SIGN"
             }]
           }
         }
       }
     }
   }
   ```

   Notice the following features of the route:

   * The route matches requests to `/jwksethandler`.

   * The JWT signing key is managed by the SysEnvStoreSecretStore in the heap, which refers to the SecretKeyPropertyFormat for the secret's format.

   * The JwtBuilderFilter `signature` property refers to the JWT signing key in the SysEnvStoreSecretStore.

   * The JwkSetHandler refers to the JWT signing key.

3. Go to <http://ig.example.com:8080/jwksethandler>.

   The signing key is displayed as an array, as follows:

   ```json
   {
     "keys": [
       {
         "k": "cGFzc3dvcmQ",
         "kid": "signing.key.secret.id",
         "kty": "oct",
         "use": "sig"
       }
     ]
   }
   ```

   The JWK set secret is ULR base64-encoded. Although the secret is set with the value `cGFzc3dvcmQ=`, the value `cGFzc3dvcmQ` is exposed.

### More information

[org.forgerock.openig.handler.JwkSetHandler](../_attachments/apidocs/org/forgerock/openig/handler/JwkSetHandler.html)

## ResourceHandler

Serves static content from a directory.

### Usage

```json
{
  "name": string,
  "type": "ResourceHandler",
  "config": {
    "directories": [ configuration expression<string>, ... ],
    "basePath": configuration expression<string>,
    "welcomePages": [ configuration expression<string>, ... ],
    "temporaryStorage": TemporaryStorage reference
  }
}
```

### Properties

* `"directories"`: *array of configuration expression<[strings](preface.html#definition-string)>, required*

  A list of one or more directories in which to search for static content.

  When multiple directories are specified in an array, the directories are searched in the listed order.

* `"basePath"`: \_configuration expression<[string](preface.html#definition-string)>, required if the route is not `/`

  The base path of the incoming request for static content.

  To specify no base path, leave this property out of the configuration, or specify it as `"basePath": ""` or `"basePath": "/"`.

  Default: `""`.

* `"welcomePages"`: *array of configuration expression<[strings](preface.html#definition-string)>, optional*

  A set of static content to serve from one of the specified directories when no specific resource is requested.

  When multiple sets of static content are specified in an array, the sets are searched for in the listed order. The first set that is found is used.

  Default: Empty

* `"temporaryStorage"`: *TemporaryStorage [reference](preface.html#definition-reference), optional*

  A [TemporaryStorage](TemporaryStorage.html) object for the static content.

  Default: `TemporaryStorage` heap object

### Example

The following example serves requests to `http://ig.example.com:8080` with the static file `index.html` from `/path/to/static/pages/`:

```json
{
  "name": "StaticWebsite",
  "type": "ResourceHandler",
  "config": {
    "directories": ["/path/to/static/pages"],
    "welcomePages": ["index.html"]
  }
}
```

When the `basePath` is `/website`, the example serves requests to `http://ig.example.com:8080/website`:

```json
{
  "name": "StaticWebsite",
  "type": "ResourceHandler",
  "config": {
    "directories": ["/path/to/static/pages"],
    "basePath": "/website",
    "welcomePages": ["index.html"]
  }
}
```

### More information

[org.forgerock.openig.handler.resources.ResourceHandler](../_attachments/apidocs/org/forgerock/openig/handler/resources/ResourceHandler.html)

[org.forgerock.http.protocol.Entity](../_attachments/apidocs/org/forgerock/http/protocol/Entity.html)

## ReverseProxyHandler

Proxy requests to protected applications. When IG relays the request to the protected application, IG is acting as a client of the application. IG is *client-side*.

Consider the following comparison of the ClientHandler and ReverseProxyHandler:

|                                                          | ClientHandler                                                                                                                                                                                      | ReverseProxyHandler                                                                                          |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Use this handler to …​                                   | Send requests to third-party services accessed within a route. The service can be AM or an HTTP API. The service can be an HTTP endpoint, such as AM, IDM, Identity Cloud, or any custom HTTP API. | Send requests to the final service accessed by a route. The service can be the final downstream application. |
| If the service does not respond in time, this handler …​ | Propagates the error through the Promise flow\.If the error is not handled within the route, for example, by a FailureHandler, the handler returns a `500 Internal Server Error` response.         | Stops processing the request, and returns a `502 Bad Gateway` response.                                      |

When uploading or downloading large files, prevent timeout issues by increasing the value of `soTimeout`, and using a streaming mode, as follows:

Configure the `streamingEnabled` property of [AdminHttpApplication](RequiredConfiguration.html).

### Usage

```json
{
  "name": string,
  "type": "ReverseProxyHandler",
  "config": {
    "vertx": object,
    "connections": configuration expression<number>,
    "waitQueueSize": configuration expression<number>,
    "disableReuseConnection": configuration expression<boolean>, //*
    "stateTrackingEnabled": configuration expression<boolean>, //*
    "soTimeout": configuration expression<duration>,
    "connectionTimeout": configuration expression<duration>,
    "connectionTimeToLive": configuration expression<duration>, //*
    "numberOfWorkers": configuration expression<number>, //*
    "protocolVersion": configuration expression<enumeration>,
    "http2PriorKnowledge": configuration expression<boolean>,
    "proxyOptions": ProxyOptions reference,
    "temporaryStorage": TemporaryStorage reference,
    "tls": ClientTlsOptions reference,
    "asyncBehavior": configuration expression<enumeration>, //*
    "retries": object,
    "circuitBreaker": object,
    "websocket": object,
    "hostnameVerifier": configuration expression<enumeration>, //deprecated
    "proxy": Server reference, //deprecated
    "systemProxy": boolean //deprecated
  }
}
```

\* Legacy; no longer supported

### Properties

* `"vertx"`: *[object](preface.html#definition-object), optional*

  Vert.x-specific configuration for the handler, where IG does not provide its own first-class configuration. Vert.x options are described in [HttpClientOptions](https://vertx.io/docs/4.5.17/apidocs/io/vertx/core/http/HttpClientOptions.html).

  The `vertx` object is read as a map, and values are evaluated as configuration expressions.

  For properties where IG provides its own first-class configuration, Vert.x configuration options are disallowed, and the IG configuration option takes precedence over Vert.x options configured in `vertx`. The following Vert.x configuration options are disallowed client-side:

  * `alpnVersions`

  * `connectTimeout`

  * `enabledCipherSuites`

  * `enabledSecureTransportProtocols`

  * `http2ClearTextUpgrade`

  * `idleTimeout`

  * `idleTimeoutUnit`

  * `keyCertOptions`

  * `keyStoreOptions`

  * `maxWaitQueueSize`

  * `pemKeyCertOptions`

  * `pemTrustOptions`

  * `pfxKeyCertOptions`

  * `pfxTrustOptions`

  * `port`

  * `protocolVersion`

  * `proxyOptions`

  * `ssl`

  * `trustOptions`

  * `trustStoreOptions`

  * `useAlpn`

  * `verifyHost`

  The following example configures the Vert.x configuration when IG is acting client-side. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

  ```json
  {
    "vertx": {
      "maxWebSocketFrameSize": 128000,
      "maxWebSocketMessageSize": 256000,
      "compressionLevel": 4,
      "maxHeaderSize": 16384
    }
  }
  ```

  The following example configures HTTP/2 connections when IG is acting client-side. The configuration allows IG to make HTTP/2 requests with large headers. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

  ```json
  {
    "vertx": {
      "initialSettings": {
        "maxHeaderListSize": 16384
      }
    }
  }
  ```

* `"connections"`: *configuration expression<[number](preface.html#definition-number)>, optional*

  The maximum number of concurrent HTTP connections in the client connection pool.

  For information about the interaction between this property and `waitQueueSize`, see the description of `waitQueueSize`.

  Default: 64

* "waitQueueSize": *configuration expression<[number](preface.html#definition-number)>, optional*

  The maximum number of outbound requests allowed to queue when no downstream connections are available. Outbound requests received when the queue is full are rejected.

  Use this property to limit memory use when there is a backlog of outbound requests, for example, when the protected application or third-party service is slow.

  Configure `waitQueueSize` as follows:

  * Not set (default): The wait queue is calculated as the square of `connections`.

    * If `connections` is not configured, then its default of `64` is used, giving the `waitQueueSize` of `4096`.

    * If the square of `connections` exceeds the maximum integer value for the Java JVM, the maximum integer value for the Java JVM is used.

  * `-1`: The wait queue is unlimited. Requests received when there are no available connections are queued without limit.

  * `0`: There is no wait queue. Requests received when there are no available connections are rejected.

  * A value that is less than the square of `connections`:

    When the configuration is loaded, the configured value is used. IG generates a warning that the `waitQueueSize` is too small for the `connections` size, and recommends a different value.

  * A value where `waitQueueSize` plus `connections` exceeds the maximum integer value for the Java JVM:

    When the configuration is loaded, the `waitQueueSize` is reduced to the maximum integer value for the Java JVM minus the value of `connections`. IG generates a warning.

  Consider the following example configuration of `connections` and `waitQueueSize`:

  ```json
  {
    "handler" : {
      "name" : "proxy-handler",
      "type" : "ReverseProxyHandler",
      "MyCapture" : "all",
      "config": {
        "soTimeout": "10 seconds",
        "connectionTimeout": "10 seconds",
        "connections": 64,
        "waitQueueSize": 100
      }
    },
    "baseURI" : "http://app.example.com:8080",
    "condition" : "${find(request.uri.path, '/')}"
  }
  ```

  IG can propagate the request to the sample application using 64 connections. When the connections are consumed, up to 100 subsequent requests are queued until a connection is freed. Effectively IG can accommodate 164 requests, although user concurrency delay means more may be handled. Requests received when the waitQueue is full are rejected.

  Default: Not set

* `"connectionTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Time to wait to establish a connection, expressed as a duration

  Default: 10 seconds

* `"connectionTimeToLive"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Not supported

* `"disableReuseConnection"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  Not supported

* `"stateTrackingEnabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  Not supported

* `"numberOfWorkers"`: *configuration expression<[number](preface.html#definition-number)>, optional*

  Not supported

* `"protocolVersion"`: *configuration expression<[enumeration](preface.html#definition-enumeration)>, optional*

  The version of HTTP protocol to use when processing requests:

  * `HTTP/2`:

    * For HTTP, process requests using HTTP/1.1.

    * For HTTPS, process requests using HTTP/2.

  * `HTTP/1.1`:

    * For HTTP and HTTPS, process requests using HTTP/1.1.

  * Not set:

    * For HTTP, process requests using HTTP/1.1.

    * For HTTPS with `alpn` enabled in ClientTlsOptions, process requests using HTTP/1.1, with an HTTP/2 upgrade request. If the targeted server can use HTTP/2, the client uses HTTP/2.

      For HTTPS with `alpn` disabled in ClientTlsOptions, process requests using HTTP/1.1, without an HTTP/2 upgrade request.

      Note that `alpn` is enabled by default in ClientTlsOptions.

  Default: Not set

|   |                                                                                                                                                                                                                                                                                                                                      |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | In HTTP/1.1 request messages, a `Host` header is required to specify the host and port number of the requested resource. In HTTP/2 request messages, the `Host` header is not available.In scripts or custom extensions that use HTTP/2, use `UriRouterContext.originalUri.host` or `UriRouterContext.originalUri.port` in requests. |

* `"http2PriorKnowledge"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  A flag for whether the client should have prior knowledge that the server supports HTTP/2. This property is for cleartext (non-TLS requests) only, and is used only when `protocolVersion` is HTTP/2.

  * `false`: The client checks whether the server supports HTTP/2 by sending an HTTP/1.1 request to upgrade the connection to HTTP/2:

    * If the server supports HTTP/2, the server upgrades the connection to HTTP/2, and subsequent requests are processed over HTTP/2.

    * If the server does not support HTTP/2, the connection is not upgraded, and subsequent requests are processed over HTTP/1.

  * `true`: The client does not check that the server supports HTTP/2. The client sends HTTP/2 requests to the server, assuming that the server supports HTTP/2.

  Default: `false`

* `"proxyOptions"`: *ProxyOptions [reference](preface.html#definition-reference), optional*

  A proxy server to which requests can be submitted. Use this property to relay requests to other parts of the network. For example, use it to submit requests from an internal network to the internet.

  Provide the name of a [ProxyOptions](ProxyOptions.html) object defined in the heap or an inline configuration.

  Default: A heap object named `ProxyOptions`.

- `"soTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Socket timeout, after which stalled connections are destroyed, expressed as a duration.

  |   |                                                                                                                                       |
  | - | ------------------------------------------------------------------------------------------------------------------------------------- |
  |   | If `SocketTimeoutException` errors occur in the logs when you try to upload or download large files, consider increasing `soTimeout`. |

  Default: 10 seconds

- `"temporaryStorage"`: *TemporaryStorage [reference](preface.html#definition-reference), optional*

  The [TemporaryStorage](TemporaryStorage.html) object to buffer the request and response, when the `streamingEnabled` property of [admin.json](AdminHttpApplication.html) is `false`.

  Default: A heap object named `TemporaryStorage`.

- `tls`: *ClientTlsOptions [reference](preface.html#definition-reference), optional*

  |   |                                                                                                                                                                                                                                     |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | Use of a TlsOptions reference is deprecated; use ClientTlsOptions instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Configure options for connections to TLS-protected endpoints, based on [ClientTlsOptions](MiscellaneousConfigurationObjects.html#ClientTlsOptions). Define the object inline or in the heap.

  Default: Connections to TLS-protected endpoints are not configured.

- \`"asyncBehavior": *configuration expression<[enumeration](preface.html#definition-enumeration)>, optional*

  Not supported

- `"retries"`: *[object](preface.html#definition-object), optional*

  Enable and configure retry for requests.

  During the execution of a request to a remote server, if a runtime exception occurs, or a condition is met, IG waits for a delay, and then schedules a new execution of the request. IG tries until the allowed number of retries is reached or the execution succeeds.

  A warning-level entry is logged if all retry attempts fail; a debug-level entry is logged if a retry succeeds.

  ```json
  "retries": {
    "enabled": configuration expression<boolean>,
    "condition": runtime expression<boolean>,
    "executor": ScheduledExecutorService reference,
    "count": configuration expression<number>,
    "delay": configuration expression<duration>,
    }
  }
  ```

  * `"enabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

    Enable retries.

    Default: `true`

  * `"condition"`: *runtine expression<[boolean](preface.html#definition-boolean)>, optional*

    An inline IG [expression](Expressions.html#Expressions) to define a condition based on the response, such as an error code.

    The condition is evaluated as follows:

    * If `true`, IG retries the request until the value in `count` is reached.

    * If `false`, IG retries the request only if a runtime exception occurs, until the value in `count` is reached.

      Default: `${false}`

  * `"executor"`: *ScheduledExecutorService [reference](preface.html#definition-reference), optional*

    The ScheduledExecutorService to use for scheduling delayed execution of the request.

    Default: `ScheduledExecutorService`

    See also [ScheduledExecutorService](MiscellaneousConfigurationObjects.html#ScheduledExecutorService).

  * `"count"`: *configuration expression<[number](preface.html#definition-number)>, optional*

    The maximum number of retries to perform. After this threshold is passed and if the request is still not successful, then the ClientHandler propagates the failure.

    Retries caused by any runtime exception or triggered condition are included in the count.

    Default: `5`

  * `"delay"`: *\_configuration expression<[duration](preface.html#definition-duration)>, optional*

    The time to wait before retrying the request.

    After a failure to send the request, if the number of retries is below the threshold, a new attempt is scheduled with the executor service after this delay.

    Default: `10 seconds`

  The following example configures a retry when a downstream component returns a `502 Bad Gateway` response code:

  ```json
  "retries": {
      "enabled": true,
      "condition": "${response.status.code == 502}"
  }
  ```

  The following example configures the handler to retry the request only once, after a 1-minute delay:

  ```json
  {
    "retries": {
      "count": 1,
      "delay": "1 minute"
    }
  }
  ```

  The following example configures the handler to retry the request at most 20 times, every second:

  ```json
  {
    "retries": {
      "count": 20,
      "delay": "1 second"
    }
  }
  ```

  The following example configures the handler to retry the request 5 times, every 10 seconds (default values), with a dedicated executor:

  ```json
  {
    "retries": {
      "executor": {
        "type": "ScheduledExecutorService",
        "config": {
          "corePoolSize": 20
        }
      }
    }
  }
  ```

- `"circuitBreaker"`: *[object](preface.html#definition-object), optional*

  Enable and configure a circuit breaker to trip when the number of failures exceeds a configured threshold. Calls to downstream services are stopped, and a runtime exception is returned. The circuit breaker is reset after the configured delay.

  ```json
  {
    "circuitBreaker": {
      "enabled": configuration expression<boolean>,
      "maxFailures":  configuration expression<integer>,
      "openDuration": configuration expression<duration>,
      "openHandler": Handler reference,
      "slidingCounter":  object,
      "executor":  ScheduledExecutorService reference
    }
  }
  ```

  * `"enabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

    A flag to enable the circuit breaker.

    Default: `true`

  * `"maxFailures"`: *configuration expression<[number](preface.html#definition-number)>, required*

    The maximum number of failed requests allowed in the window given by `size`, before the circuit breaker trips. The value must be greater than zero.

    |   |                                                                                                                                                                                                                                                                                                                                                                                                               |
    | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | When `retries` is set, the circuit breaker does not count retried requests as failures. Bear this in mind when you set `maxFailures`.In the following example, a request can fail and then be retried three times. If it fails the third retry, the request has failed four times, but the circuit breaker counts only one failure.```json
    {
      "retries": {
        "count": 3,
        "delay": "1 second"
      }
    }
    ``` |

  * `"openDuration"`: *configuration expression<[duration](preface.html#definition-duration)>, required*

    The duration for which the circuit stays open after the circuit breaker trips. The `executor` schedules the circuit to be closed after this duration.

  * `"openHandler"`: *Handler [reference](preface.html#definition-reference), optional*

    The [Handler](#) to call when the circuit is open.

    Default: A handler that throws a RuntimeException with a "circuit-breaker open" message.

  * `"slidingCounter"`: *[object](preface.html#definition-object), optional*

    A sliding window error counter. The circuit breaker trips when the number of failed requests in the number of requests given by `size` reaches `maxFailures`.

    The following image illustrates how the sliding window counts failed requests:

    ![Example sliding window error counter.](_images/sliding-window.svg)

    ```json
    {
      "slidingCounter":  {
        "size": configuration expression<number>
      }
    }
    ```

    * `"size"`: *configuration expression<[number](preface.html#definition-number)>, required*

      The size of the sliding window in which to count errors.

      The value of `size` must be greater than zero, and greater than the value of `maxFailures`, otherwise an exception is thrown.

  * `"executor"`: *ScheduledExecutorService [reference](preface.html#definition-reference), optional*

    A [ScheduledExecutorService](MiscellaneousConfigurationObjects.html#ScheduledExecutorService) to schedule closure of the circuit after the duration given by `openDuration`.

    Default: The default ScheduledExecutorService in the heap

- `"websocket"`: *[object](preface.html#definition-object), optional*

  Object to configure upgrade from HTTP or HTTPS protocol to WebSocket protocol.

  Every key/value of the `websocket` object is evaluated as a configuration expression.

  List the subprotocols that are proxied by IG in the `vertx` property of [AdminHttpApplication (`admin.json`)](AdminHttpApplication.html). For more information and an example of proxying WebSocket traffic, refer to [WebSocket traffic](../gateway-guide/websocket.html)

  ```json
  {
    "websocket": {
      "enabled": configuration expression<boolean>,
      "connectionTimeout": configuration expression<duration>,
      "soTimeout": configuration expression<duration>,
      "numberOfSelectors": configuration expression<number>,
      "tls": ClientTlsOptions reference,
      "proxyOptions": ProxyOptions reference,
      "vertx": object
    }
  }
  ```

  For more information, refer to [The WebSocket Protocol](https://www.rfc-editor.org/rfc/rfc6455).

  * `"enabled"`: *configuration expression<[boolean](preface.html#definition-boolean)>,optional*

    Enable upgrade from HTTP protocol and HTTPS protocol to WebSocket protocol.

    Default: `false`

  * `"connectionTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

    The maximum time allowed to establish a WebSocket connection.

    Default: The value of handler's main `connectionTimeout`.

  * `"soTimeout"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

    The time after which stalled connections are destroyed.

    |   |                                                                                                                                                                               |
    | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | If there can be long delays between messages, consider increasing this value. Alternatively, keep the connection active by using WebSocket ping messages in your application. |

    Default: The value of handler's main `soTimeout`.

  * `"numberOfSelectors"`: *configuration expression<[number](preface.html#definition-number)>, optional*

    The maximum number of worker threads.

    In deployments with a high number of simultaneous connections, consider increasing the value of this property.

    Default: `2`

  * `"tls"`: *ClientTlsOptions [reference](preface.html#definition-reference), optional*

    Configure options for connections to TLS-protected endpoints, based on a [ClientTlsOptions](MiscellaneousConfigurationObjects.html#ClientTlsOptions) configuration. Define a ClientTlsOptions object inline or in the heap.

    Default: Use ClientTlsOptions defined for the handler

  * `"proxyOptions"`: *ProxyOptions [reference](preface.html#definition-reference), optional*

    A proxy server to which requests can be submitted. Use this property to relay requests to other parts of the network. For example, use it to submit requests from an internal network to the internet.

    Provide the name of a [ProxyOptions](ProxyOptions.html) object defined in the heap or an inline configuration.

    Default: A heap object named `ProxyOptions`.

  * `"vertx"`: *[object](preface.html#definition-object), optional*

    Vert.x-specific configuration for the WebSocket connection, where IG does not provide its own first-class configuration. Vert.x options are described in [HttpClientOptions](https://vertx.io/docs/4.5.17/apidocs/io/vertx/core/http/HttpClientOptions.html).

    For properties where IG provides its own first-class configuration, Vert.x configuration options are disallowed, and the IG configuration option takes precedence over Vert.x options configured in `vertx`. The following Vert.x configuration options are disallowed client-side:

    * `alpnVersions`

    * `connectTimeout`

    * `enabledCipherSuites`

    * `enabledSecureTransportProtocols`

    * `http2ClearTextUpgrade`

    * `idleTimeout`

    * `idleTimeoutUnit`

    * `keyCertOptions`

    * `keyStoreOptions`

    * `maxWaitQueueSize`

    * `pemKeyCertOptions`

    * `pemTrustOptions`

    * `pfxKeyCertOptions`

    * `pfxTrustOptions`

    * `port`

    * `protocolVersion`

    * `proxyOptions`

    * `ssl`

    * `trustOptions`

    * `trustStoreOptions`

    * `useAlpn`

    * `verifyHost`

    The following example configures the Vert.x configuration when IG is acting client-side. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

    ```json
    {
      "vertx": {
        "maxWebSocketFrameSize": 128000,
        "maxWebSocketMessageSize": 256000,
        "compressionLevel": 4,
        "maxHeaderSize": 16384
      }
    }
    ```

    The following example configures HTTP/2 connections when IG is acting client-side. The configuration allows IG to make HTTP/2 requests with large headers. When IG is acting server-side, configure the `connectors:vertx` property of `admin.json`:

    ```json
    {
      "vertx": {
        "initialSettings": {
          "maxHeaderListSize": 16384
        }
      }
    }
    ```

  The following default `vertx` configuration provided by this handler overrides the Vert.x defaults:

  * `tryUsePerFrameWebSocketCompression` = `true`

  * `tryUsePerMessageWebSocketCompression` = `true`

- "hostnameVerifier": configuration expression\<enumeration>, optional

  |   |                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the [ClientTlsOptions](ClientTlsOptions.html) property `hostnameVerifier` instead.If a ReverseProxyHandler includes the deprecated `"hostnameVerifier": "ALLOW_ALL"` configuration, it takes precedence, and deprecation warnings are written to the logs.For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The way to handle hostname verification for outgoing SSL connections. Use one of the following values:

  * `ALLOW_ALL`: Allow a certificate issued by a trusted CA for any hostname or domain to be accepted for a connection to any domain.

    This setting allows a certificate issued for one company to be accepted as a valid certificate for another company. To prevent the compromise of TLS connections, use this setting in development mode only. In production, use `STRICT`.

  * `STRICT`: Match the hostname either as the value of the the first CN, or any of the subject-alt names.

    A wildcard can occur in the CN, and in any of the subject-alt names. Wildcards match one domain level, so `*.example.com` matches `www.example.com` but not `some.host.example.com`.

  Default: `STRICT`

- `"proxy"`: *Server reference, optional*

  |   |                                                                                                                                                                                                                   |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use `proxyOptions` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  A proxy server to which requests can be submitted. Use this property to relay requests to other parts of the network. For example, use it to submit requests from an internal network to the internet.

  If both `proxy` and `systemProxy` are defined, `proxy` takes precedence.

  ```json
  "proxy" : {
    "uri": configuration expression<uri string>,
    "username": configuration expression<string>,
    "passwordSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "password": configuration expression<string> //deprecated
  }
  ```

  * `"uri"`: *configuration expression\<uri string>, required*

    URI of a server to use as a proxy for outgoing requests.

    The result of the expression must be a string that represents a valid URI, but is not a real java.net.URI object.

  * username: configuration expression\<string>, required if the proxy requires authentication

    Username to access the proxy server.

  * `"passwordSecretId"`: *configuration expression\<secret-id>*, required if the proxy requires authentication

    The secret ID of the password to access the proxy server.

    This secret ID must point to a [GenericSecret](../security-guide/keys.html#secret-types).

  * `"secretsProvider"`: *SecretsProvider reference, optional*

    The SecretsProvider to query for the proxy's password.

  * `"password"`: *configuration expression\<string>, required if the proxy requires authentication*

    |   |                                                                                                                                                                                                                                                    |
    | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    |   | This property is deprecated and is not considered secure. Use `passwordSecretId` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

    Password to access the proxy server.

- `"systemProxy"`: *boolean, optional*

  |   |                                                                                                                                                                                                                   |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use `proxyOptions` instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Submit outgoing requests to a system-defined proxy, set by the following system properties or their HTTPS equivalents:

  * `http.proxyHost`, the host name of the proxy server.

  * `http.proxyPort`, the port number of the proxy server. The default is `80`.

  * `http.nonProxyHosts`, a list of hosts that should be reached directly, bypassing the proxy.

  This property can't be used with a proxy that requires a username and password. Use the property `proxy` instead.

  If both `proxy` and `systemProxy` are defined, `proxy` takes precedence.

  For more information, refer to [Java Networking and Proxies](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/doc-files/net-properties.html).

  Default: False.

- `"keyManager"`: *Key manager reference(s), optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The key manager(s) that handle(s) this client's keys and certificates.

  The value of this field can be a single reference, or an array of references.

  Provide either the name(s) of key manager object(s) defined in the heap, or specify the configuration object(s) inline.

  You can specify either a single key manager, as in `"keyManager": "MyKeyManager"`, or an array of key managers, as in `"keyManager": [ "FirstKeyManager", "SecondKeyManager" ]`.

  If you do not configure a key manager, then the client cannot present a certificate, and so cannot play the client role in mutual authentication.

- `"sslCipherSuites"`: *array of strings, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Array of cipher suite names, used to restrict the cipher suites allowed when negotiating transport layer security for an HTTPS connection.

  For information about the available cipher suite names, refer to the documentation for the Java virtual machine (JVM) where you run IG. For Oracle Java, refer to the list of [JSSE Cipher Suite Names](https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#jsse-cipher-suite-names).

  Default: Allow any cipher suite supported by the JVM.

- `"sslContextAlgorithm"`: *string, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Default: TLS

- `"sslEnabledProtocols"`: *array of strings, optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  Array of protocol names, used to restrict the protocols allowed when negotiating transport layer security for an HTTPS connection.

  Default: Allow any protocol supported by the JVM.

- `"trustManager"`: *Trust manager reference(s), optional*

  |   |                                                                                                                                                                                                                                                                              |
  | - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | This property is deprecated; use the `tls` property instead to configure [ClientTlsOptions](ClientTlsOptions.html). For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  The trust managers that handle(s) peers' public key certificates.

  The value of this field can be a single reference, or an array of references.

  Provide either the name(s) of TrustManager object(s) defined in the heap, or specify the configuration object(s) inline.

  You can specify either a single trust manager, as in `"trustManager": "MyTrustManager"`, or an array of trust managers, as in `"trustManager": [ "FirstTrustManager", "SecondTrustManager" ]`.

  If you do not configure a trust manager, then the client uses only the default Java truststore. The default Java truststore depends on the Java environment. For example, `$JAVA_HOME/lib/security/cacerts`.

### More information

[org.forgerock.openig.handler.ReverseProxyHandlerHeaplet](../_attachments/apidocs/org/forgerock/openig/handler/ReverseProxyHandlerHeaplet.html)

## Route

Routes are JSON-encoded configuration files that you add to IG to manage requests. You can add routes in the following ways:

* Manually into the filesystem.

* Through Common REST commands. For information, refer to [Routes and Common REST](../configure/crest.html).

* Through Studio. For information, refer to the [Studio guide](../studio-guide/preface.html#preface).

Routes handle requests and their context, and then hand off any request they accept to a [Handler](#).

When a route has a condition, it handles only requests that meet the condition. When a route has no condition, it handles any request.

Routes inherit settings from their parent configuration. This means that you can configure global objects in the `config.json` heap, for example, and then reference the objects by name in any other IG configuration.

### Usage

```json
{
  "handler": Handler reference,
  "heap": [ object, ... ],
  "condition": runtime expression<boolean>,
  "name": string,
  "secrets": {
    "stores": [ SecretStore reference, ... ]
  }, //deprecated
  "session": AsyncSessionManager reference,
  "auditService": AuditService reference,
  "globalDecorators": map,
  "decorator name": Decorator object
}
```

(\*)Deprecated

### Properties

* `"handler"`: *Handler [reference](preface.html#definition-reference), required*

  The [Handler](#) to which IG dispaches requests.

  Provide the name of a Handler object defined in the heap or an inline Handler configuration object.

* `"heap"`: *array of [objects](preface.html#definition-object), optional*

  Heap object configuration for objects local to this route.

  Objects referenced but not defined here are inherited from the parent.

  You can omit an empty array. If you only have one object in the heap, you can inline it as the handler value.

  See also [Heap objects](RequiredConfiguration.html#heap-objects).

* `"condition"`: *runtime expression<[boolean](preface.html#definition-boolean)>, optional*

  A condition based on the request, context, or IG runtime environment, such as system properties or environment variables.

  * `true`: The request is dispatched to the route.

  * `false`: The condition for the next route in the configuration is evaluated.

  * No condition: the request is dispatched unconditionally to the route.

  |   |                                                                                                                                                                                                                                                                                                                                                                         |
  | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | For debugging, log the routes for which IG evaluates a condition, and the route that matches a condition. Add the following line to a custom `$HOME/.openig/config/logback.xml`, and restart IG:```xml
  <logger name="org.forgerock.openig.handler.router.RouterHandler" level="trace" />
  ```For information, refer to [Manage logs](../maintenance-guide/logging.html). |

  An external request can never match a condition that uses the reserved administrative route. Therefore, routes that use these conditions are effectively ignored. For example, if `/openig` is the administrative route, a route with the following condition is ignored: `${find(request.uri.path, '^/openig/my/path')}`.

  Default: `${true}`

  For example conditions and requests that match them, refer to [Example conditions and requests](#route-conditions).

* `"name"`: *[string](preface.html#definition-string), optional*

  Route name.

  The Router uses the `name` property to order the routes in the configuration. If the route does not have a `name` property, the Router uses the route ID.

  The route ID is managed as follows:

  * When you add a route manually to the routes folder, the route ID is the value of the `_id` field. If there is no `_id` field, the route ID is the filename of the added route.

  * When you add a route through the Common REST endpoint, the route ID is the value of the mandatory `_id` field.

  * When you add a route through Studio, you can edit the default route ID.

    CAUTION: The filename of a route cannot be `default.json`. The route `name` property or route ID cannot be `default`.

  Default: route ID

- `"secrets"`: *SecretStore [reference](preface.html#definition-reference), optional*

  |   |                                                                                                                                                                                                                                            |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  |   | This property is deprecated; use [SecretsProvider](SecretsProvider.html) instead. For more information, refer to the [Deprecated](https://docs.pingidentity.com/pinggateway/release-notes/deprecated.html) section of the *Release Notes*. |

  One or more secret stores, as defined in [Secrets](secrets.html).

* `"session"`: *AsyncSessionManager reference. [reference](preface.html#definition-reference), optional*

  Stateless session implementation for this route. Define an AuthenticatedEncryptedJwtSessionManager object inline or in the heap.

  When a request enters the route, IG builds a new session object for the route. The session content is available to the route's downstream handlers and filters. Session content available in the ascending configuration (a parent route or `config.json`) is not available in the new session.

  When the response exits the route, the session content is serialized as a secure JWT that is encrypted and signed, and the resulting JWT string is placed in a cookie. Session information set inside the route is no longer available. The `session` references the previous session object.

  Default: Do not change the session storage implementation.

  For more information, refer to [AsyncSessionManager](../_attachments/apidocs/org/forgerock/http/session/AsyncSessionManager.html), and [Sessions](../about/about-sessions.html).

* `"auditService"`: *AuditService [reference](preface.html#definition-reference), optional*

  An audit service for the route. Provide either the name of an AuditService object defined in the heap or an inline AuditService configuration object.

  Default: No auditing of a configuration. The NoOpAuditService provides an empty audit service to the top-level heap and its child routes.

* `"globalDecorators"`: *[map](preface.html#map), optional*

  A map of one or more data pairs with the format `Map<String, JsonValue>`, where:

  * The key is a decorator name

  * The value is a decorator configuration, passed *as is* to the decorator

  The following format is required:

  ```json
  {
    "globalDecorators": {
      "decorator name": "decoration configuration",
      ...
    }
  }
  ```

  All compatible objects in a route are decorated with the mapped decorator value. For more information, refer to [Decorators](Decorators.html).

  In the following example, the property decorates all compatible objects in the route with a capture and timer decorator:

  ```json
  "globalDecorators": {
    "capture": "all",
    "timer": true
  }
  ```

  Default: Empty

* `"decorator name"`: *Decorator [object](preface.html#definition-object), optional*

  Decorate the main handler of this route with a decorator referred to by the decorator name, and provide the configuration as described in [Decorators](Decorators.html).

  Default: No decoration.

### Route metrics at the Prometheus Scrape Endpoint

Route metrics at the Prometheus Scrape Endpoint have the following labels:

* `name`: Route name, for example, `My Route`.

  If the router was declared with a default handler, then its metrics are published through the route named `default`.

* `route`: Route identifier, for example, `my-route`.

* `router`: Fully qualified name of the router, for example, `gateway.main-router`.

The following table summarizes the recorded metrics:

| Name(1)                          | [Monitoring type](MonitoringTypes.html) | Description                                                                                                                                                                                                                                   |
| -------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ig_route_request_active`        | Gauge                                   | Number of requests being processed.                                                                                                                                                                                                           |
| `ig_route_request_total`         | Counter                                 | Number of requests processed by the router or route since it was deployed.                                                                                                                                                                    |
| `ig_route_response_error_total`  | Counter                                 | Number of responses that threw an exception.                                                                                                                                                                                                  |
| `ig_route_response_null_total`   | Counter                                 | Number of responses that were not handled by IG.                                                                                                                                                                                              |
| `ig_route_response_status_total` | Counter                                 | Number of responses by HTTP status code family. The `family` label depends on the HTTP status code:- Informational (1xx)

- Successful (2xx)

- Redirection (3xx)

- Client_error (4xx)

- Server_error (5xx)

- Unknown (status code >= 600) |
| `ig_route_response_time`         | Summary                                 | A summary of response time observations.                                                                                                                                                                                                      |

(1)Metric names are deprecated and expected to be replaced with names ending in \_total. The information provided by the metric is not deprecated. Other Prometheus metrics are not affected.

For more information about the the Prometheus Scrape Endpoint, see [Prometheus Scrape Endpoint](Monitoring.html#monitoring-prom).

### Route Metrics at the Common REST Monitoring Endpoint

Route metrics at the Common REST Monitoring Endpoint are published with an `_id` in the following pattern:

* `heap.router-name.route.route-name.metric`

The following table summarizes the recorded metrics:

| Name                            | [Monitoring type](MonitoringTypes.html) | Description                                                                                                      |
| ------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `request`                       | Counter                                 | Number of requests processed by the router or route since it was deployed.                                       |
| `request.active`                | Gauge                                   | Number of requests being processed by the router or route at this moment.                                        |
| `response.error`                | Counter                                 | Number of responses that threw an exception.                                                                     |
| `response.null`                 | Counter                                 | Number of responses that were not handled by IG.                                                                 |
| `response.status.client_error`  | Counter                                 | Number of responses with an HTTP status code `400`-`499`, indicating client error.                               |
| `response.status.informational` | Counter                                 | Number of responses with an HTTP status code `100`-`199`, indicating that they are provisional responses.        |
| `response.status.redirection`   | Counter                                 | Number of responses with an HTTP status code `300`-`399`, indicating a redirect.                                 |
| `response.status.server_error`  | Counter                                 | Number of responses with an HTTP status code `500`-`599`, indicating server error.                               |
| `response.status.successful`    | Counter                                 | Number of responses with an HTTP status code `200`-`299`, indicating success.                                    |
| `response.status.unknown`       | Counter                                 | Number of responses with an HTTP status code `600`-`699`, indicating that a request failed and was not executed. |
| `response.time`                 | Timer                                   | Time-series summary statistics.                                                                                  |

For more information about the the Common REST Monitoring Endpoint, see [Common REST Monitoring Endpoint](Monitoring.html#monitoring-crest).

#### Example conditions and requests

| Condition                                                                                                                                            | Requests that meet the condition                                                                                                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ```json
"${true}"
```                                                                                                                                | All requests, because this expression always evaluates to `true`.                                                                                                                                                                                        |
| ```json
"${find(request.uri.path, '^/login')}"
```                                                                                                   | `http://app.example.com/login`, . . .                                                                                                                                                                                                                    |
| ```json
"${request.uri.host == 'api.example.com'}"
```                                                                                               | `http://api.example.com/`, `https://api.example.com/home`, `http://api.example.com:8080/home`, . . .                                                                                                                                                     |
| ```json
"${find(contexts.client.remoteAddress, '127.0.0.1')}"
```                                                                                    | `http://localhost:8080/keygen`, `http://127.0.0.1:8080/keygen`, . . .Where `/keygen` is not mandatory and could be anything else.                                                                                                                        |
| ```json
"${find(request.uri.query, 'demo=simple')}"
```                                                                                              | `http://ig.example.com:8080/login?demo=simple`, . . .For information about URI query, refer to `query` in [URI](RequestsResponses.html#URI).                                                                                                             |
| ```json
"${request.uri.scheme == 'http'}"
```                                                                                                        | `http://ig.example.com:8080`, . . .                                                                                                                                                                                                                      |
| ```json
"${find(request.uri.path, '^/dispatch') or find(request.uri.path, '^/mylogin')}"
```                                                         | `http://ig.example.com:8080/dispatch`, `http://ig.example.com:8080/mylogin`, . . .                                                                                                                                                                       |
| ```json
"${request.uri.host == 'sp1.example.com' and not find(request.uri.path, '^/saml')}"
```                                                      | `http://sp1.example.com:8080/`, `http://sp1.example.com/mypath`, . . .Not `http://sp1.example.com:8080/saml`, `http://sp1.example.com/saml`, . . .                                                                                                       |
| ```json
"condition": "${find (request.uri.path, '&{uriPath}')}"
```                                                                                  | `http://ig.example.com:8080/hello`, when the following property is configured:```json
{
  "properties": {
    "uriPath": "hello"
  }
}
```For information about including properties in the configuration, refer to [Route properties](Properties.html). |
| ```json
"condition": "${request.headers['X-Forwarded-Host'][0] == 'service.example.com'}"
```                                                        | Requests with the header `X-Forwarded-Host`, whose first value is `service.example.com`.                                                                                                                                                                 |
| ```json
"condition": "#{find(request.uri.path, '^/openam/oauth2/access_token') && request.entity.form['client_id'][0] == 'client-service'}"
```      | Requests where an OAuth 2.0 client named `client-service` issues the original access token request.                                                                                                                                                      |
| ```json
"condition": "#{find(request.uri.path, '^/openam/oauth2/access_token') && request.entity.form['grant_type'][0] == 'client_credentials'}"
``` | Requests using the client credentials grant-type.                                                                                                                                                                                                        |

## Router

A [Handler](#) that performs the following tasks:

* Defines the routes directory and loads routes into the configuration.

* Depending on the scanning interval, periodically scans the routes directory and updates the IG configuration when routes are added, removed, or changed. The router updates the IG configuration without needing to restart IG or access the route.

* Manages an internal list of routes, where routes are ordered lexicographically by route name. If a route is not named, then the route ID is used instead. For more information, refer to [Route](#Route).

* Routes requests to the first route in the internal list of routes, whose condition is satisfied.

  Because the list of routes is ordered lexicographically by route name, name your routes with this in mind:

  * If a request satisfies the condition of more than one route, it is routed to the first route in the list whose condition is met.

  * Even if the request matches a later route in the list, it might never reach that route.

  If a request does not satisfy the condition of any route, it is routed to the default handler if one is configured.

The router does not have to know about specific routes in advance - you can configure the router first and then add routes while IG is running.

|   |                                                                                                                                                                                                                                       |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Studio deploys and undeploys routes through a main router named `_router`, which is the name of the main router in the default configuration. If you use a custom `config.json`, make sure it contains a main router named `_router`. |

### Usage

```json
{
    "name": string,
    "type": "Router",
    "config": {
        "defaultHandler": Handler reference,
        "directory": configuration expression<string>,
        "scanInterval": configuration expression<duration>
    }
}
```

An alternative value for type is RouterHandler.

### Properties

* `"defaultHandler"`: *Handler [reference](preface.html#definition-reference), optional*

  Handler to use when a request does not satisfy the condition of any route.

  Provide either the name of a handler object defined in the heap or an inline handler configuration object.

  Default: If no default route is set either here or in the route configurations, IG aborts the request with an internal error.

  See also [Handlers](#).

* `"directory"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Directory from which to load route configuration files.

  Default: The default directory for route configuration files, at `$HOME/.openig`(on Windows, `%appdata%\OpenIG`).

  With the following example, route configuration files are loaded from `/path/to/safe/routes` instead of from the default directory:

  ```json
  {
    "type": "Router",
    "config": {
      "directory": "/path/to/safe/routes"
    }
  }
  ```

  |   |                                                                                                                                      |
  | - | ------------------------------------------------------------------------------------------------------------------------------------ |
  |   | If you define multiple routers, configure `directory` so that the routers load route configuration files from different directories. |

  An infinite route-loading sequence is triggered when a router starts a route that, directly or indirectly, starts another router, which then loads route configuration files from the same directory.

  See also [Expressions](Expressions.html#Expressions).

* `"scanInterval"`: *configuration expression<[duration](preface.html#definition-duration)>, optional*

  Time interval at which IG scans the specified directory for changes to routes. When a route is added, removed, or changed, the router updates the IG configuration without needing to restart IG or access the route.

  When an integer is used for the `scanInterval`, the time unit is seconds.

  To load routes at startup only, and prevent changes to the configuration if the routes are changed, set the scan interval to `disabled`.

  Default: 10 seconds

### Router metrics at the Prometheus Scrape Endpoint

Router metrics at the Prometheus Scrape Endpoint have the following labels:

* `fully_qualified_name`: Fully qualified name of the router, for example, `gateway.main-router`.

* `heap`: Name of the heap in which this router is declared, for example, `gateway`.

* `name`: Simple name declared in router configuration, for example, `main-router`.

The following table summarizes the recorded metrics:

| Name                        | [Monitoring type](MonitoringTypes.html) | Description                                     |
| --------------------------- | --------------------------------------- | ----------------------------------------------- |
| `ig_router_deployed_routes` | `Gauge`                                 | Number of routes deployed in the configuration. |

For more information about the the Prometheus Scrape Endpoint, refer to [Prometheus Scrape Endpoint](Monitoring.html#monitoring-prom).

### Router metrics at the Common REST Monitoring Endpoint

Router metrics at the Common REST Monitoring Endpoint are JSON objects, with the following form:

* `[heap name].[router name].deployed-routes`

The following table summarizes the recorded metrics:

| Name              | [Monitoring type](MonitoringTypes.html) | Description                                     |
| ----------------- | --------------------------------------- | ----------------------------------------------- |
| `deployed-routes` | `Gauge`                                 | Number of routes deployed in the configuration. |

For more information about the the Common REST Monitoring Endpoint, refer to [Common REST Monitoring Endpoint](Monitoring.html#monitoring-crest).

### Example

The following `config.json` file configures a Router:

```json
{
  "handler": {
    "type": "Router",
    "name": "_router",
    "baseURI": "http://app.example.com:8081",
    "capture": "all"
  },
  "heap": [
    {
      "name": "JwtSession",
      "type": "JwtSession"
    },
    {
      "name": "capture",
      "type": "CaptureDecorator",
      "config": {
        "captureEntity": true,
        "_captureContext": true
      }
    }
  ]
}
```

All requests pass with the default settings to the Router. The Router scans `$HOME/.openig/config/routes` at startup, and rescans the directory every 10 seconds. If routes have been added, deleted, or changed, the router applies the changes.

The main router and any subrouters build the monitoring endpoints. For information about monitoring endpoints, refer to [Monitoring endpoints](Monitoring.html#monitoring-metrics).

### More information

[org.forgerock.openig.handler.router.RouterHandler](../_attachments/apidocs/org/forgerock/openig/handler/router/RouterHandler.html)

## SamlFederationHandler (deprecated)

|   |                                                                                                |
| - | ---------------------------------------------------------------------------------------------- |
|   | This handler is deprecated; use the [SamlFederationFilter](SamlFederationFilter.html) instead. |

A handler to play the role of SAML 2.0 Service Provider (SP).

Consider the following requirements for SamlFederationHandler:

* This handler does not support filtering; do not use it as the handler for a chain, which can include filters.

* Do not use this handler when its use depends on something in the response. The response can be handled independently of IG, and can be `null` when control returns to IG. For example, do not use this handler in a `SequenceHandler` where the `postcondition` depends on the response.

* Requests to the SamlFederationHandler must not be rebased, because the request URI must match the endpoint in the SAML metadata.

**SAML in deployments with multiple instances of IG**

IG uses the federation libraries from AM (also referred to as the Fedlet) to implement SAML. When IG acts as a SAML service provider, the session information is stored in the fedlet, not the session cookie. In deployments that use multiple instances of IG as a SAML service provider, it is therefore necessary to set up sticky sessions so that requests always hit the instance where the SAML interaction was started.

For information, refer to [Session state considerations](https://docs.pingidentity.com/pingam/7.4/am-saml2/saml2-configuration.html#saml2-and-session-state) in AM's *SAML v2.0 guide*.

For more information, refer to [About session stickiness and session replication for Tomcat](../installation-guide/install-tomcat.html#stickiness-tomcat) and [About session stickiness and session replication for Jetty](../installation-guide/install-jetty.html#stickiness-jetty)

### Usage

```json
{
    "name": string,
    "type": "SamlFederationHandler",
    "config": {
        "assertionMapping": map or configuration expression<map>,
        "redirectURI": configuration expression<url>,
        "secretsProvider": SecretsProvider reference,
        "assertionConsumerEndpoint": configuration expression<url>,
        "authnContext": configuration expression<string>,
        "authnContextDelimiter": configuration expression<string>,
        "logoutURI": configuration expression<url>,
        "sessionIndexMapping": configuration expression<string>,
        "singleLogoutEndpoint": configuration expression<url>,
        "singleLogoutEndpointSoap": configuration expression<url>,
        "SPinitiatedSLOEndpoint": configuration expression<url>,
        "SPinitiatedSSOEndpoint": configuration expression<url>,
        "useOriginalUri": configuration expression<boolean>,
        "subjectMapping": configuration expression<string>
    }
}
```

### Properties

* `"assertionMapping"`: *[map](preface.html#definition-map) or configuration expression\<map>, required*

  A map with the format `Map<String, String>`, where:

  * Key: Session name, `localName`

  * Value: SAML assertion name, `incomingName`, or a configuration expression that evaluates to the name

  The following formats are allowed:

  ```json
  {
    "assertionMapping": {
      "string": "configuration expression<string>",
      ...
    }
  }
  ```

  ```json
  {
    "assertionMapping": "configuration expression<map>"
  }
  ```

  In the following example, the session names `username` and `password` are mapped to SAML assertion names `mail` and `mailPassword` :

  ```json
  {
    "assertionMapping": {
      "username": "mail",
      "password": "mailPassword"
    }
  }
  ```

  If an incoming SAML assertion contains the following statement:

  ```
  mail = demo@example.com
  mailPassword = demopassword
  ```

  Then the following values are set in the session:

  ```
  username[0] = demo@example.com
  password[0] = demopassword
  ```

  For this to work, edit the `<Attribute name="attributeMap">` element in the SP extended metadata file, `$HOME/.openig/SAML/sp-extended.xml`, so that it matches the assertion mapping configured in the SAML 2.0 Identity Provider (IDP) metadata.

  Because the dot character (`.`) serves as a query separator in expressions, do not use dot characters in the localName.

  To prevent different handlers from overwriting each others' data, use unique localName settings when protecting multiple service providers.

* `"redirectURI"`: *configuration expression<[url](preface.html#definition-url)>, required*

  The page that the filter used to HTTP POST a login form recognizes as the login page for the protected application.

  This is how IG and the Federation component work together to provide SSO. When IG detects the login page of the protected application, it redirects to the Federation component. Once the Federation handler validates the SAML exchanges with the IDP, and sets the required session attributes, it redirects back to the login page of the protected application. This allows the filter used to HTTP POST a login form to finish the job by creating a login form to post to the application based on the credentials retrieved from the session attributes.

* `"secretsProvider"`: *SecretsProvider [reference](preface.html#definition-reference), optional*

  The SecretsProvider object to query for keys when AM provides signed or encrypted SAML assertions.

  When this property is not set, the keys are provided by direct keystore look-ups based on entries in the SP extended metadata file, `sp-extended.xml`.

  For more information, refer to [SecretsProvider](secrets.html#SecretsProvider).

  Default: Empty.

* `"assertionConsumerEndpoint"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Default: `fedletapplication` (same as the Fedlet)

  If you modify this attribute, change the metadata to match.

* `"authnContext"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Name of the session field to hold the value of the authentication context. Because the dot character (`.`) serves as a query separator in expressions, do not use dot characters in the field name.

  Use this setting when protecting multiple service providers, as the different configurations must not map their data into the same fields of `session`. Otherwise different handlers can overwrite each others' data.

  As an example, if you set `"authnContext": "myAuthnContext"`, then IG sets `session.myAuthnContext` to the authentication context specified in the assertion. When the authentication context is password over protected transport, then this results in the session containing `"myAuthnContext": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"`.

  Default: map to `session.authnContext`

* `"authnContextDelimiter"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  The authentication context delimiter used when there are multiple authentication contexts in the assertion.

  Default: `|`

* `"logoutURI"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Set this to the URI to visit after the user is logged out of the protected application.

  You only need to set this if the application uses the single logout feature of the Identity Provider.

* `"sessionIndexMapping"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Name of the session field to hold the value of the session index. Because the dot character (`.`) serves as a query separator in expressions, do not use dot characters in the field name.

  Use this setting when protecting multiple service providers, as the different configurations must not map their data into the same fields of `session`. Otherwise different handlers can overwrite each others' data.

  As an example, if you set `"sessionIndexMapping": "mySessionIndex"`, then IG sets `session.mySessionIndex` to the session index specified in the assertion. This results in the session containing something like `"mySessionIndex": "s24ccbbffe2bfd761c32d42e1b7a9f60ea618f9801"`.

  Default: map to `session.sessionIndex`

* `"singleLogoutEndpoint"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Default: `fedletSLORedirect` (same as the Fedlet)

  If you modify this attribute, change the metadata to match.

* `"singleLogoutEndpointSoap"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Default: `fedletSloSoap` (same as the Fedlet)

  If you modify this attribute, change the metadata to match.

* `"SPinitiatedSLOEndpoint"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Default: `SPInitiatedSLO`

  If you modify this attribute, change the metadata to match.

* `"SPinitiatedSSOEndpoint"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Default: `SPInitiatedSSO`

  If you modify this attribute, change the metadata to match.

* `"useOriginalUri"`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  When `true`, use the original URI instead of a rebased URI when validating RelayState and Assertion Consumer Location URLs. Use this property if a `baseUri` decorator is used in the route or in `config.json`.

  Default: `false`

* `"subjectMapping"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Name of the session field to hold the value of the subject name. Because the dot character (`.`) serves as a query separator in expressions, do not use dot characters in the field name.

  Use this setting when protecting multiple service providers, as the different configurations must not map their data into the same fields of `session`. Otherwise different handlers can overwrite each others' data.

  As an example, if you set `"subjectMapping": "mySubjectName"`, then IG sets `session.mySubjectName` to the subject name specified in the assertion. If the subject name is an opaque identifier, then this results in the session containing something like `"mySubjectName": "vtOk+APj1s9Rr4yCka6V9pGUuzuL"`.

  Default: map to `session.subjectName`

### Example

For an example of how to set up IG as a SAML service provider, refer to [SAML](../gateway-guide/saml.html).

In the following example, IG receives a SAML 2.0 assertion from the IDP, and then logs the user in to the protected application using the username and password from the assertion:

```json
{
    "name": "SamlFederationHandler",
    "type": "SamlFederationHandler",
    "config": {
        "assertionMapping": {
            "username": "mail",
            "password": "mailPassword"
        },
        "redirectURI": "/login",
        "logoutURI": "/logout"
    }
}
```

## ScriptableHandler

Creates a response to a request by executing a script.

Scripts must return either a [Promise\<Response, NeverThrowsException>](../_attachments/apidocs/org/forgerock/util/promise/Promise.html) or a [Response](../_attachments/apidocs/org/forgerock/http/protocol/Response.html).

This section describes the usage of ScriptableHandler. For information about script properties, available global objects, and automatically imported classes, see [Scripts](Scripts.html).

### Usage

```json
{
    "name": string,
    "type": "ScriptableHandler",
    "config": {
        "type": configuration expression<string>,
        "file": configuration expression<string>, // Use either "file"
        "source": [ string, ... ],                // or "source", but not both
        "args": map,
        "clientHandler": Handler reference
    }
}
```

### Properties

For information about properties for ScriptableHandler, refer to [Scripts](Scripts.html).

### More information

[org.forgerock.openig.handler.ScriptableHandler](../_attachments/apidocs/org/forgerock/openig/handler/ScriptableHandler.html)

## SequenceHandler

Processes a request through a sequence of handlers and post conditions, as follows:

* A request is treated by `handler1`, and then `postcondition1` is evaluated.

* If `postcondition1` is true, the request is then treated by `handler2`, and so on.

```json
{
  "handler": handler1,
  "postcondition": expression1
},
{
  "handler": handler2,
  "postcondition": expression2
},
...
```

Use this handler for multi-request processing, such as retrieving a form, extracting form content (for example, a nonce), and then submitting it in a subsequent request.

### Usage

```json
{
    "name": string,
    "type": "SequenceHandler",
    "config": {
        "bindings": [
            {
                "handler": Handler reference,
                "postcondition": runtime expression<boolean>
            }
        ]
    }
}
```

### Properties

* `"bindings"`: *array of [objects](preface.html#definition-object), required*

  A list of handler and postcondition bindings.

* `"handler"`: *Handler [reference](preface.html#definition-reference), required*

  The [handler](#) to dispatch the request to when it is the first handler in the bindings, or for subsequent handlers when their previous `postcondition` yields `true`.

  Provide the name of a Handler object defined in the heap or an inline Handler configuration object.

* `"postcondition"`: *runtime expression<[boolean](preface.html#definition-boolean)>, optional*

  A flag to indicate that a post condition is met:

  * `true`: The request is dispatched to the next handler in `bindings`.

  * `false`: The sequence stops.

  Postconditions are defined using IG expressions, as described in [Expressions](Expressions.html#Expressions).

  Default: `${true}`

### More information

[org.forgerock.openig.handler.SequenceHandler](../_attachments/apidocs/org/forgerock/openig/handler/SequenceHandler.html)

## StaticResponseHandler

Creates a response to a request statically, or based on something in the context.

### Usage

```json
{
  "name": string,
  "type": "StaticResponseHandler",
  "config": {
    "status": configuration expression<number>,
    "reason": configuration expression<string>,
    "headers": {
       configuration expression<string>: [ runtime expression<string>, ... ], ...
    },
    "trailers": {
       configuration expression<string>: [ runtime expression<string>, ... ], ...
    },
    "entity": runtime expression<string> or [ runtime expression<string>, ... ]
  }
}
```

### Properties

* `"status"`: *Status object*

  The response status. For more information, refer to [Status](Contexts.html#Status).

* `"reason"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  Used only for custom HTTP status codes. For more information, refer to [Response Status Codes](https://datatracker.ietf.org/doc/html/rfc7231#section-6) and [Status Code Registry](https://datatracker.ietf.org/doc/html/rfc7231#section-8.2).

* `"headers"`: *[map](preface.html#definition-map), optional*

  One or more headers to set for a response, with the format `name: [ value, …​ ]`, where:

  * *name* is a configuration expression<[string](preface.html#definition-string)> for a header name. If multiple expressions resolve to the same final string, *name* has multiple values.

  * *value* one or more a runtime expression<[strings](preface.html#definition-string)> for header values.

  When the property `entity` is used, set a `Content-Type` header with the correct content type value. The following example sets the content type of a message entity in the response:

  ```json
  "headers": {
    "Content-Type": [ "text/html; charset=UTF-8" ]
  }
  ```

  The following example is used in `federate-handler.json` to redirect the original URI from the request:

  ```json
  "headers": {
    "Location": [
       "http://sp.example.com:8080/saml/SPInitiatedSSO"
    ]
  }
  ```

Default: Empty

* `"trailers"`: *[map](preface.html#definition-map), optional*

  One or more trailers to set for a response, with the format `name: [ value, …​ ]`, where:

  * *name* is a configuration expression<[string](preface.html#definition-string)> for a trailer name. If multiple expressions resolve to the same string, *name* has multiple values.

    The following trailer names are not allowed:

    * Message framing headers (for example, `Transfer-Encoding` and `Content-Length`)

    * Routing headers (for example, `Host`)

    * Request modifiers (for example, controls and conditionals such as `Cache-Control`, `Max-Forwards`, and `TE`)

    * Authentication headers (for example, `Authorization` and `Set-Cookie`)

    * `Content-Encoding`

    * `Content-Type`

    * `Content-Range`

    * `Trailer`

  * *value* is one or more runtime expression<[strings](preface.html#definition-string)> for trailer values.

  Default: Empty

* `"entity"`: *runtime expression<[string](preface.html#definition-string)>* or *array of runtime expression<[string](preface.html#definition-string)>, optional*

  The message entity body to include in a response.

  If a `Content-Type` header is present, the entity must conform to the header and set the content length header automatically.

  Methods are provided for accessing the entity as byte, string, or JSON content. For information, refer to [Entity](../_attachments/apidocs/org/forgerock/http/protocol/Entity.html).

  |   |                                                                                                                                                                                                               |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  |   | Attackers during reconnaissance can use response messages to identify information about a deployment. For security, limit the amount of information in messages, and avoid using words that help identify IG. |

  Default: Empty

### Example

```json
{
  "name": "ErrorHandler",
  "type":"StaticResponseHandler",
  "config": {
    "status": 500,
    "headers": {
      "Content-Type": [ "text/html; charset=UTF-8" ]
    },
    "entity": "<html><h2>Epic #FAIL</h2></html>"
  }
}
```

```json
{
  "handler": {
    "type": "StaticResponseHandler",
    "config": {
      "status": 200,
      "headers": {
        "content-type": [ "text/html" ]
      },
      "entity": [
        "<html>",
        "  <body>",
        "    <h1>Request Details</h1>",
        "    <p>The path was: ${request.uri.path}<p>",
        "    <p>The query params were: ${toString(request.queryParams)}</p>",
        "    <p>The headers were: ${toString(request.headers.entrySet())}<p>",
        "  </body>",
        "</html>"
      ]
    }
  }
}
```

### More information

[org.forgerock.openig.handler.StaticResponseHandler](../_attachments/apidocs/org/forgerock/openig/handler/StaticResponseHandler.html)
