Identity Gateway 2023.11

Reference

This guide describes configuration options for IG. It is for IG designers, developers, and administrators.

For API specifications, refer to the appropriate Javadoc.

The examples in this guide use some of the following third-party tools:

Reserved routes

By default, IG reserves all paths starting with /openig for administrative use, and only local client applications can access resources exposed under /openig.

IG uses an ApiProtectionFilter to protect reserved routes. By default, the ApiProtectionFilter allows access to reserved routes only from the loopback address. To override this behavior, declare a custom ApiProtectionFilter in the top-level heap. For an example, refer to the CORS filter described in Set up the UMA example.

For information about how to change the base for administrative routes, refer to Change the base location.

Reserved field names

IG reserves all configuration field names that contain only alphanumeric characters.

If you must define your own field names, for example, in custom decorators, use names with dots, ., or dashes, -. Examples include my-decorator and com.example.myDecorator.

Field value conventions

IG configuration uses JSON notation.

This reference uses the following terms when referring to values of configuration object fields:

array

JSON array.

boolean

Either true or false.

certificate

java.security.cert.Certificate instance.

configuration token

Configuration tokens introduce variables into the server configuration. They can take values from Java system properties, environment variables, JSON and Java properties files held in specified directories, and from properties configured in routes. For more information, refer to JSON Evaluation.

duration

A duration is a lapse of time expressed in English, such as 23 hours 59 minutes and 59 seconds. Durations are not case sensitive, and negative durations are not supported. The following units can be used in durations:

  • indefinite, infinity, undefined, unlimited: unlimited duration

  • zero, disabled: zero-length duration

  • days, day, d: days

  • hours, hour, h: hours

  • minutes, minute, min, m: minutes

  • seconds, second, sec, s: seconds

  • milliseconds, millisecond, millisec, millis, milli, ms: milliseconds

  • microseconds, microsecond, microsec, micros, micro, us, µs: microseconds

  • nanoseconds, nanosecond, nanosec, nanos, nano, ns: nanoseconds

enumeration

A collections of constants.

expression

See Expressions.

configuration expression

Expression evaluated at configuration time, when routes are loaded. See Configuration Expressions.

runtime expression

Expression evaluated at runtime, for each request and response. See Runtime Expressions.

instant

An instantaneous point on the timeline, as a Java type. For more information, see Class Instant.

JsonValue

An object (JsonObject), an array (JsonArray), a number (JsonNumber), a string (JsonString), true (JsonValue.TRUE), false (JsonValue.FALSE), or null (JsonValue.NULL).

lvalue-expression

Expression yielding an object whose value is to be set.

Properties whose format is lvalue-expression cannot consume streamed content. They must be written with $ instead of #.

map

An object that maps keys to values. Keys must be unique, and can map to at most one value.

number

JSON number.

object

JSON object where the content depends on the object’s type.

pattern

A regular expression according to the rules for the Java Pattern class.

pattern-template

Template for referencing capturing groups in a pattern by using $n, where n is the index number of the capturing group starting from zero.

For example, if the pattern is \w+\s*=\s*(\w)+, the pattern-template is $1, and the text to match is key = value, the pattern-template yields value.

reference

References an object in the following ways:

  • An inline configuration object, where the name is optional.

  • A configuration expression that is a string or contains variable elements that evaluate to a string, where the string is the name of an object declared in the heap.

    For example, the following temporaryStorage object takes the value of the system property storage.ref, which must a be string equivalent to the name of an object defined in the heap:

    {
      "temporaryStorage": "${system['storage.ref']}"
    }
secret-id

String that references a secret managed by the Commons Secrets API, as described in Secrets.

The secret ID must conform to the following regex pattern: Pattern.compile("(\\.[a-zA-Z0-9])*");

string

JSON string.

url

String representation for a resource available via the Internet. For more information, refer to Uniform Resource Locators (URL).

About Common REST

Common REST is a common REST API framework. It provides ForgeRock Identity Platform software common ways to access web resources and collections of resources. Adapt the examples in this section to your resources and deployment.

This page describes the full Common REST framework. Some platform component products do not implement all Common REST behaviors exactly as described. For details, refer to the product-specific examples and reference information.

Common REST resources

Servers generally return JSON-format resources, though resource formats can depend on the implementation.

Resources in collections can be found by their unique identifiers (IDs). IDs are exposed in the resource URIs. For example, if a server has a user collection under /users, then you can access a user at /users/user-id. The ID is also the value of the _id field of the resource.

Resources are versioned using revision numbers. A revision is specified in the resource’s _rev field. Revisions make it possible to figure out whether to apply changes without resource locking and without distributed transactions.

Common REST verbs

The Common REST APIs use the following verbs, sometimes referred to collectively as CRUDPAQ. For details and HTTP-based examples of each, follow the links to the sections for each verb.

Create

Add a new resource.

This verb maps to HTTP PUT or HTTP POST.

For details, see Create.

Read

Retrieve a single resource.

This verb maps to HTTP GET.

For details, see Read.

Update

Replace an existing resource.

This verb maps to HTTP PUT.

For details, see Update.

Delete

Remove an existing resource.

This verb maps to HTTP DELETE.

For details, see Delete.

Patch

Modify part of an existing resource.

This verb maps to HTTP PATCH.

For details, see Patch.

Action

Perform a predefined action.

This verb maps to HTTP POST.

For details, see Action.

Query

Search a collection of resources.

This verb maps to HTTP GET.

For details, see Query.

Common REST parameters

Common REST reserved query string parameter names start with an underscore, _. Reserved query string parameters include, but are not limited to, the following names:

  • _action

  • _api

  • _crestapi

  • _fields

  • _mimeType

  • _pageSize

  • _pagedResultsCookie

  • _pagedResultsOffset

  • _prettyPrint

  • _queryExpression

  • _queryFilter

  • _queryId

  • _sortKeys

  • _totalPagedResultsPolicy

Some parameter values are not safe for URLs, so URL-encode parameter values as necessary.

Continue reading for details about how to use each parameter.

Common REST extension points

The action verb is the main vehicle for extensions. For example, to create a new user with HTTP POST rather than HTTP PUT, you might use /users?_action=create. A server can define additional actions. For example, /tasks/1?_action=cancel.

A server can define stored queries to call by ID. For example, /groups?_queryId=hasDeletedMembers. Stored queries can call for additional parameters. The parameters are also passed in the query string. Which parameters are valid depends on the stored query.

Common REST headers

Accept-API-Version

Common REST APIs use the Accept-API-Version header to specify protocol and resource versions:

Accept-API-Version: protocol=version,resource=version
protocol

The version reflects changes in the Common REST protocol, such as common method parameters and headers specified by the protocol itself, or the input or response conventions it prescribes.

For example, protocol version 2.2 introduced the _countOnly parameter.

resource

The version reflects changes in the resource implementation, including JSON representation of resources, input parameters required, and incompatible behavior changes.

For example, the version changes when errorMessage changes to message in a JSON response.

Whether this header is required depends on the product and API you make the request to.

X-ForgeRock-TransactionId

Common REST APIs use the X-ForgeRock-TransactionId header to track related requests through ForgeRock Identity Platform.

X-ForgeRock-TransactionId: transactionID

The transactionID consists of a unique identifier for the transaction optionally followed by a sequence number for the individual request.

This header is optional. In self-managed deployments, you configure products to trust transaction IDs and let them propagate for audit purposes.

Common REST API documentation

Common REST APIs often depend at least in part on runtime configuration. Many Common REST endpoints therefore serve API descriptors at runtime. An API descriptor documents the actual API as it is configured.

Use the following query string parameters to retrieve API descriptors:

_api

Serves an API descriptor that complies with the OpenAPI specification.

This API descriptor represents the API accessible over HTTP. It is suitable for use with popular tools such as Swagger UI.

_crestapi

Serves a native Common REST API descriptor.

This API descriptor provides a compact representation that is not dependent on the transport protocol. It requires a client that understands Common REST, as it omits many Common REST defaults.

Consider limiting access to API descriptors in production environments in order to avoid unnecessary traffic.

To provide documentation in production environments, see To publish OpenAPI documentation instead.

To publish OpenAPI documentation

In production systems, developers expect stable, well-documented APIs. Rather than retrieving API descriptors at runtime through Common REST, prepare final versions, and publish them alongside the software in production.

Use the OpenAPI-compliant descriptors to provide API reference documentation for your developers:

  1. Configure the software to produce production-ready APIs.

    In other words, configure the software as for production so that the APIs match exactly.

  2. Retrieve the OpenAPI-compliant descriptor.

    The following command saves the descriptor to a file. :

    $ curl -o <filename>.json <endpoint>?_api

    The endpoint must be a valid endpoint. For example:

    $ curl -o myapi.json https://am.example.com:8443/am/json/realms/root/authenticate?_api
  3. If necessary, edit the descriptor.

    For example, add security definitions to describe the API protection.

  4. Publish the descriptor using a tool such as Swagger UI.

Create

There are two ways to create a resource, HTTP POST or HTTP PUT.

To create a resource using POST, perform an HTTP POST with the query string parameter _action=create, and the JSON resource as a payload. Accept a JSON response. The server creates the identifier if not specified:

POST /users?_action=create HTTP/1.1
Host: example.com
Accept: application/json
Content-Length: ...
Content-Type: application/json
{ JSON resource }

To create a resource using PUT, perform an HTTP PUT including the case-sensitive identifier for the resource in the URL path, and the JSON resource as a payload. Use the If-None-Match: * header. Accept a JSON response:

PUT /users/some-id HTTP/1.1
Host: example.com
Accept: application/json
Content-Length: ...
Content-Type: application/json
If-None-Match: *
{ JSON resource }

The _id and content of the resource depend on the server implementation. The server is not required to use the _id that the client provides. The server response to the request indicates the resource location as the value of the Location header.

If you include the If-None-Match header, you must use If-None-Match: *. In this case, the request creates the object if it does not exist, and fails if the object does exist. If you include any value other If-None-Match: *, the server returns an HTTP 400 Bad Request error. For example, creating an object with If-None-Match: revision returns a bad request error.

If you do not include If-None-Match: *, the request creates the object if it does not exist, and updates the object if it does exist.

Parameters
_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_prettyPrint=true

Format the body of the response.

Read

To retrieve a single resource, perform an HTTP GET on the resource by its case-sensitive identifier (_id), and accept a JSON response:

GET /users/some-id HTTP/1.1
Host: example.com
Accept: application/json
Parameters
_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_mimeType=mime-type

Some resources have fields whose values are multi-media resources, such as a profile photo.

If the feature is enabled for the endpoint, you can read a single field that is a multi-media resource by specifying the field and mime-type.

In this case, the content type of the field value returned matches the mime-type that you specify, and the body of the response is the multi-media resource.

Do not use the Accept header in this case. For example, Accept: image/png does not work. Use the _mimeType query string parameter instead.

_prettyPrint=true

Format the body of the response.

Update

To update a resource, perform an HTTP PUT including the case-sensitive identifier (_id) as the final element of the path to the resource, and the JSON resource as the payload. Use the If-Match: _rev header to check that you are actually updating the version you modified. Use If-Match: * if the version does not matter. Accept a JSON response:

PUT /users/some-id HTTP/1.1
Host: example.com
Accept: application/json
Content-Length: ...
Content-Type: application/json
If-Match: _rev
{ JSON resource }

When updating a resource, include all the attributes to retain. Omitting an attribute in the resource amounts to deleting the attribute unless it is not under the control of your application. Attributes not under the control of your application include private and read-only attributes. In addition, virtual attributes and relationship references might not be under the control of your application.

Product-specific implementations may differ. Not all products use the payload to replace the state of the resource in its entirety. For example, attributes that are omitted from the request payload to AM will not be deleted. Instead, you need to specify the attribute and set the value to an empty array to delete the attribute from the resource.

For more information, see the product-specific examples and reference information.

Parameters
_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_prettyPrint=true

Format the body of the response.

Delete

To delete a single resource, perform an HTTP DELETE by its case-sensitive identifier (\_id) and accept a JSON response:

DELETE /users/some-id HTTP/1.1
Host: example.com
Accept: application/json
Parameters
_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_prettyPrint=true

Format the body of the response.

Patch

To patch a resource, send an HTTP PATCH request with the following parameters:

  • operation

  • field

  • value

  • from (optional with copy and move operations)

You can include these parameters in the payload for a PATCH request, or in a JSON PATCH file. If successful, you’ll see a JSON response similar to the following:

PATCH /users/some-id HTTP/1.1
Host: example.com
Accept: application/json
Content-Length: ...
Content-Type: application/json
If-Match: _rev
{ JSON array of patch operations }

PATCH operations apply to three types of targets:

  • single-valued, such as an object, string, boolean, or number.

  • list semantics array, where the elements are ordered, and duplicates are allowed.

  • set semantics array, where the elements are not ordered, and duplicates are not allowed.

Common REST PATCH supports multiple operations:

Patch operation: add

The add operation ensures that the target field contains the value provided, creating parent fields as necessary.

If the target field is single-valued, then the value you include in the PATCH replaces the value of the target. A single-valued field is an object, string, boolean, or number.

An add operation has different results on two standard types of arrays:

  • List semantic arrays: you can run any of these add operations on that type of array:

    • If you add an array of values, the PATCH operation appends it to the existing list of values.

    • If you add a single value, specify an ordinal element in the target array, or use the {-} special index to add that value to the end of the list.

  • Set semantic arrays: The value included in the patch is merged with the existing set of values. Any duplicates within the array are removed.

As an example, start with the following list semantic array resource:

{
    "fruits" : [ "orange", "apple" ]
}

The following add operation includes the pineapple to the end of the list of fruits, as indicated by the - at the end of the fruits array.

{
    "operation" : "add",
    "field" : "/fruits/-",
    "value" : "pineapple"
}

The following is the resulting resource:

{
    "fruits" : [ "orange", "apple", "pineapple" ]
}

You can add only one array element one at a time, as per the corresponding JSON Patch specification. If you add an array of elements, for example:

{
    "operation" : "add",
    "field" : "/fruits/-",
    "value" : ["pineapple", "mango"]
}

The resulting resource would have the following invalid JSON structure:

{
    "fruits" : [ "orange", "apple", ["pineapple", "mango"]]
}
Patch operation: copy

The copy operation takes one or more existing values from the source field. It then adds those same values on the target field. Once the values are known, it is equivalent to performing an add operation on the target field.

The following copy operation takes the value from a field named mail, and then runs a replace operation on the target field, another_mail.

[
  {
     "operation":"copy",
     "from":"mail",
     "field":"another_mail"
  }
]

If the source and target field values are arrays, the result depends on whether the array has list semantics or set semantics, as described in Patch operation: add.

Patch operation: increment

The increment operation changes the value or values of the target field by the amount you specify. The value that you include must be one number, and may be positive or negative. The value of the target field must accept numbers. The following increment operation adds 1000 to the target value of /user/payment.

[
  {
    "operation" : "increment",
    "field" : "/user/payment",
    "value" : "1000"
  }
]

Since the value of the increment is a single number, arrays do not apply.

Patch operation: move

The move operation removes existing values on the source field. It then adds those same values on the target field. This is equivalent to a remove operation on the source, followed by an add operation with the same values, on the target.

The following move operation is equivalent to a remove operation on the source field, surname, followed by a replace operation on the target field value, lastName. If the target field does not exist, it is created:

[
  {
     "operation":"move",
     "from":"surname",
     "field":"lastName"
  }
]

To apply a move operation on an array, you need a compatible single-value, list semantic array, or set semantic array on both the source and the target. For details, see the criteria described in Patch operation: add.

Patch operation: remove

The remove operation ensures that the target field no longer contains the value provided. If the remove operation does not include a value, the operation removes the field. The following remove deletes the value of the phoneNumber, along with the field.

[
  {
    "operation" : "remove",
    "field" : "phoneNumber"
  }
]

If the object has more than one phoneNumber, those values are stored as an array.

A remove operation has different results on two standard types of arrays:

  • List semantic arrays: A remove operation deletes the specified element in the array. For example, the following operation removes the first phone number, based on its array index (zero-based):

    [
       {
          "operation" : "remove",
          "field" : "/phoneNumber/0"
       }
    ]
  • Set semantic arrays: The list of values included in a patch are removed from the existing array.

Patch operation: replace

The replace operation removes any existing value(s) of the targeted field, and replaces them with the provided value(s). It is essentially equivalent to a remove followed by a add operation. If the arrays are used, the criteria is based on Patch operation: add. However, indexed updates are not allowed, even when the target is an array.

The following replace operation removes the existing telephoneNumber value for the user, and then adds the new value of +1 408 555 9999.

[
  {
    "operation" : "replace",
    "field" : "/telephoneNumber",
    "value" : "+1 408 555 9999"
  }
]

A PATCH replace operation on a list semantic array works as a PATCH remove operation. The following example demonstrates how the effect of both operations. Start with the following resource:

{
    "fruits" : [ "apple", "orange", "kiwi", "lime" ],
}

Apply the following operations on that resource:

[
  {
    "operation" : "remove",
    "field" : "/fruits/0",
    "value" : ""
  },
  {
    "operation" : "replace",
    "field" : "/fruits/1",
    "value" : "pineapple"
  }
]

The PATCH operations are applied sequentially. The remove operation removes the first member of that resource, based on its array index, (fruits/0), with the following result:

[
  {
    "fruits" : [ "orange", "kiwi", "lime" ],
  }
]

The second PATCH operation, a replace, is applied on the second member (fruits/1) of the intermediate resource, with the following result:

[
  {
    "fruits" : [ "orange", "pineapple", "lime" ],
  }
]
Patch operation: transform

The transform operation changes the value of a field based on a script, or some other data transformation command. The following transform operation takes the value from the field named /objects, and applies the something.js script as shown:

[
  {
    "operation" : "transform",
    "field" : "/objects",
    "value" : {
      "script" : {
        "type" : "text/javascript",
        "file" : "something.js"
      }
    }
  }
]
Patch operation limitations

Some HTTP client libraries do not support the HTTP PATCH operation. Make sure that the library you use supports HTTP PATCH before using this REST operation.

For example, the Java Development Kit HTTP client does not support PATCH as a valid HTTP method. Instead, the method HttpURLConnection.setRequestMethod("PATCH") throws ProtocolException.

Parameters
_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_prettyPrint=true

Format the body of the response.

Action

Actions are a means of extending Common REST APIs and are defined by the resource provider, so the actions you can use depend on the implementation.

The standard action indicated by _action=create is described in Create.

Parameters

In addition to these parameters, specific action implementations have their own parameters:

_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_prettyPrint=true

Format the body of the response.

Query

To query a resource collection (or resource container), perform an HTTP GET, and accept a JSON response, including either a _queryExpression, _queryFilter, or _queryId parameter. The parameters cannot be used together:

GET /users?_queryFilter=true HTTP/1.1
Host: example.com
Accept: application/json

The server returns the result as a JSON object including a "results" array, and other fields that depend on the parameters.

Parameters
_countOnly=true

Return a count of query results without returning the resources.

This parameter requires protocol version 2.2 or later.

_fields=field[,field…​]

Return only the specified fields in the body of the response.

The field values are JSON pointers. For example if the resource is {"parent":{"child":"value"}}, parent/child refers to the "child":"value".

If the field is left blank, the server returns all default values.

_queryFilter=filter-expression

Query filters request that the server return entries that match the filter expression. You must URL-escape the filter expression.

The string representation is summarized as follows. Continue reading for additional explanation:

Expr           = OrExpr
OrExpr         = AndExpr ( 'or' AndExpr ) *
AndExpr        = NotExpr ( 'and' NotExpr ) *
NotExpr        = '!' PrimaryExpr | PrimaryExpr
PrimaryExpr    = '(' Expr ')' | ComparisonExpr | PresenceExpr | LiteralExpr
ComparisonExpr = Pointer OpName JsonValue
PresenceExpr   = Pointer 'pr'
LiteralExpr    = 'true' | 'false'
Pointer        = JSON pointer
OpName         = 'eq' |  # equal to
                 'co' |  # contains
                 'sw' |  # starts with
                 'lt' |  # less than
                 'le' |  # less than or equal to
                 'gt' |  # greater than
                 'ge' |  # greater than or equal to
                 STRING  # extended operator
JsonValue      = NUMBER | BOOLEAN | '"' UTF8STRING '"'
STRING         = ASCII string not containing white-space
UTF8STRING     = UTF-8 string possibly containing white-space

JsonValue components of filter expressions follow RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format. In particular, as described in section 7 of the RFC, the escape character in strings is the backslash character. For example, to match the identifier test\, use _id eq 'test\\'. In the JSON resource, the \ is escaped the same way: "_id":"test\\".

When using a query filter in a URL, the filter expression is part of a query string parameter. A query string parameter must be URL encoded, as described in RFC 3986: Uniform Resource Identifier (URI): Generic Syntax. For example, white space, double quotes ("), parentheses, and exclamation characters must be URL encoded in HTTP query strings. The following rules apply to URL query components:

query       = *( pchar / "/" / "?" )
pchar       = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims  = "!" / "$" / "&amp;" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="

ALPHA, DIGIT, and HEXDIG are core rules of RFC 5234: Augmented BNF for Syntax Specifications:

ALPHA       =  %x41-5A / %x61-7A   ; A-Z / a-z
DIGIT       =  %x30-39             ; 0-9
HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"

As a result, a backslash escape character in a JsonValue component is percent-encoded in the URL query string parameter as %5C. To encode the query filter expression _id eq 'test\\', use _id+eq+'test%5C%5C', for example.

A simple filter expression can represent a comparison, presence, or a literal value.

For comparison expressions, use json-pointer comparator json-value, where the comparator is one of the following:

eq (equals)
co (contains)
sw (starts with)
lt (less than)
le (less than or equal to)
gt (greater than)
ge (greater than or equal to)

For presence, use json-pointer pr to match resources where the JSON pointer is present, and the value it points to is not null.

Literal values include true (match anything) and false (match nothing).

Complex expressions employ and, or, and ! (not), with parentheses, (expression), to group expressions.

_queryId=identifier

Specify a query by its identifier.

Specific queries can take their own query string parameter arguments, which depend on the implementation.

_pagedResultsCookie=string

The string is an opaque cookie used by the server to keep track of the position in the search results. The server returns the cookie in the JSON response as the value of pagedResultsCookie.

In the request _pageSize must also be set and non-zero. You receive the cookie value from the provider on the first request, and then supply the cookie value in subsequent requests until the server returns a null cookie, meaning the final page of results has been returned.

The _pagedResultsCookie parameter is supported when used with the _queryFilter parameter. The _pagedResultsCookie parameter is not guaranteed to work with the _queryExpression or _queryId parameters.

The _pagedResultsCookie and _pagedResultsOffset parameters are mutually exclusive, and not to be used together.

_pagedResultsOffset=integer

When _pageSize is non-zero, use this as an index in the result set indicating the first page to return.

The _pagedResultsCookie and _pagedResultsOffset parameters are mutually exclusive, and not to be used together.

_pageSize=integer

Return query results in pages of this size. After the initial request, use _pagedResultsCookie or _pageResultsOffset to page through the results.

_prettyPrint=true

Format the body of the response.

_totalPagedResultsPolicy=string

When a _pageSize is specified, and non-zero, the server calculates the "totalPagedResults", in accordance with the totalPagedResultsPolicy, and provides the value as part of the response.

The "totalPagedResults" is either an estimate of the total number of paged results (_totalPagedResultsPolicy=ESTIMATE), or the exact total result count (_totalPagedResultsPolicy=EXACT). If no count policy is specified in the query, or if _totalPagedResultsPolicy=NONE, result counting is disabled, and the server returns value of -1 for "totalPagedResults".

_sortKeys=(|-)__field__[,(|-)field…​]

Sort the resources returned based on the specified field(s), either in + (ascending, default) order, or in - (descending) order.

Because ascending order is the default, including the `` character in the query is unnecessary. If you do include the `` character, it must be URL-encoded as %2B, for example:

http://localhost:8080/api/users?_queryFilter=true&_sortKeys=%2Bname/givenName

The _sortKeys parameter is not supported for predefined queries (_queryId).

HTTP status codes

When working with a Common REST API over HTTP, client applications should expect at least these HTTP status codes. Not all servers necessarily return all status codes identified here:

200 OK

The request was successful and a resource returned, depending on the request.

201 Created

The request succeeded and the resource was created.

204 No Content

The action request succeeded, and there was no content to return.

304 Not Modified

The read request included an If-None-Match header, and the value of the header matched the revision value of the resource.

400 Bad Request

The request was malformed.

401 Unauthorized

The request requires user authentication.

403 Forbidden

Access was forbidden during an operation on a resource.

404 Not Found

The specified resource could not be found, perhaps because it does not exist.

405 Method Not Allowed

The HTTP method is not allowed for the requested resource.

406 Not Acceptable

The request contains parameters that are not acceptable, such as a resource or protocol version that is not available.

409 Conflict

The request would have resulted in a conflict with the current state of the resource.

410 Gone

The requested resource is no longer available, and will not become available again. This can happen when resources expire for example.

412 Precondition Failed

The resource’s current version does not match the version provided.

415 Unsupported Media Type

The request is in a format not supported by the requested resource for the requested method.

428 Precondition Required

The resource requires a version, but no version was supplied in the request.

500 Internal Server Error

The server encountered an unexpected condition that prevented it from fulfilling the request.

501 Not Implemented

The resource does not support the functionality required to fulfill the request.

503 Service Unavailable

The requested resource was temporarily unavailable. The service may have been disabled, for example.

Required configuration

AdminHttpApplication (admin.json)

The AdminHttpApplication serves requests on the administrative route, such as the creation of routes and the collection of monitoring information. The administrative route and its subroutes are reserved for administration endpoints.

The configuration is loaded from a JSON-encoded file, expected at $HOME/.openig/config/admin.json. Objects configured in admin.json cannot be used by config.json or any IG routes.

Default objects

IG provides default objects in admin.json. To override a default object, configure an object with the same name in admin.json.

Configure default objects in admin.json and config.json separately. An object configured in admin.json with the same name as an object configured in config.json is not the same object.

AuditService

Records no audit events. The default AuditService is NoOpAuditService. For more information, refer to NoOpAuditService.

CaptureDecorator

Captures requests and response messages. The default CaptureDecorator is named capture, and uses the default settings given in CaptureDecorator.

When a capture point for the default CaptureDecorator is defined in a route, for example, when "capture: "all" is set as a top-level attribute of the JSON, log messages for requests and responses passing through the route are written to a log file in $HOME/.openig/logs.

When no capture point is defined in a route, only exceptions thrown during request or response processing are logged.

By default, request and response contexts and entities are not captured. Do one of the following to capture information:

  • Override the default capture decorator declaration, and set captureEntity to true.

  • Declare another CaptureDecorator object with an appropriate configuration and use it at your capture points.

The capture decorator logs information about the HTTP request and response messages, along with their respective headers.

ClientHandler

Communicates with third-party services. For more information, refer to ClientHandler.

ForgeRockClientHandler

Sends ForgeRock Common Audit transaction IDs when communicating with protected applications. The default ForgeRockClientHandler is a Chain, composed of a TransactionIdOutboundFilter and a ClientHandler.

ProxyOptions

A proxy to which a ClientHandler or ReverseProxyHandler can submit requests, and an AmService can submit Websocket notifications. For more information, refer to ProxyOptions.

ReverseProxyHandler

Communicates with third-party services. For more information, refer to ReverseProxyHandler.

ScheduledExecutorService

Specifies the number of threads in a pool.

SecretsService (deprecated)

Manages a store of secrets from files, system properties, and environment variables, by using Commons Secrets API. The default SecretsService is a SystemAndEnvSecretStore with the default configuration. For more information, refer to Secrets.

TemporaryStorage

Manages temporary buffers. For more information, refer to TemporaryStorage.

TimerDecorator

Records time spent within filters and handlers. The default TimerDecorator is named timer. For more information, refer to TimerDecorator.

TransactionIdOutboundFilter

Inserts the ID of a transaction into the header of a request.

Provided objects

IG creates the following objects when a filter with the name of the object is declared in admin.json:

"ApiProtectionFilter"

A filter to protect administrative APIs on reserved routes. By default, only the loopback address can access reserved routes.

For an example that uses an ApiProtectionFilter, refer to Set up the UMA example. For information about reserved routes, refer to Reserved routes.

"MetricsProtectionFilter"

A filter to protect the monitoring endpoints.

By default, the Prometheus Scrape Endpoint and Common REST Monitoring Endpoint are open and accessible; no special credentials or privileges are required to access the monitoring endpoints.

For an example that uses a MetricsProtectionFilter, refer to Protect monitoring endpoints.

"StudioProtectionFilter"

A filter to protect the Studio endpoint when IG is running in development mode.

When IG is running in development mode, by default the Studio endpoint is open and accessible.

For an example that uses a StudioProtectionFilter, refer to Restrict access to Studio.

Usage

{
  "heap": [ object, ... ],
  "connectors": [ object, ... ],
  "vertx": object,
  "gatewayUnits": configuration expression<number>,
  "mode": configuration expression<enumeration>,
  "prefix": configuration expression<string>,
  "properties": object,
  "secrets"(*): {
    "stores": [ SecretStore reference, ... ]
  },
  "temporaryDirectory": configuration expression<string>,
  "temporaryStorage": TemporaryStorage reference,
  "pidFileMode": configuration expression<enumeration>,
  "preserveOriginalQueryString": configuration expression<boolean>,
  "session": object,
  "streamingEnabled": configuration expression<boolean>
}

(*)Deprecated

Properties

"heap": array of objects, optional

The heap object configuration, described in Heap objects.

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

"connectors": array of objects, required

Server port configuration, when IG is acting server-side.

When an application sends requests to IG or requests services from IG, IG is server-side. IG is acting as a server of the application, and the application is acting as a client.
{
  "connectors" : [
    {
      "port": [ configuration expression<number>, ... ],
      "tls": ServerTlsOptions reference,
      "vertx": object,
      "maxTotalHeadersSize": configuration expression<integer>
    },
    {
      ...
    }
  ]
}
port: array of configuration expression<numbers>, required

One or more ports on which IG is connected. When more than one port is defined, IG is connected to each port.

tls: ServerTlsOptions reference, optional

Configure options for connections to TLS-protected endpoints, based on ServerTlsOptions. Define the object inline or in the heap.

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

vertx: object, optional

Vert.x-specific configuration for this connector when IG is acting server-side. When IG is acting client-side, configure the vertx property of ClientHandler or ReverseProxyHandler.

Vert.x options are described in HttpServerOptions.

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. Vert.x values are evaluated as configuration expressions.

The following Vert.x configuration options are disallowed server-side:

  • port

  • useAlpn

  • ssl

  • enabledCipherSuites

  • enabledSecureTransportProtocols

  • jdkSslEngineOptions

  • keyStoreOptions

  • openSslEngineOptions

  • pemKeyCertOptions

  • pemTrustOptions

  • pfxKeyCertOptions

  • pfxTrustOptions

  • trustStoreOptions

  • clientAuth

The following Vert.x configuration options are deprecated server-side:

  • maxHeaderSize

  • initialSettings:maxHeaderListSize

Use connectors:maxTotalHeadersSize instead of vertx.maxHeaderSize or vertx.initialSettings.maxHeaderListSize.

The following example configures connectors on ports 8080 and 8443 when IG is acting server-side. When IG is acting client-side, configure the vertx property of ClientHandler or ReverseProxyHandler:

{
  "connectors": [{
    "port": 8080,
    "vertx": {
      "maxWebSocketFrameSize": 128000,
      "maxWebSocketMessageSize": 256000,
      "compressionLevel": 4
    }
  },
  {
    "port": 8443,
    "tls": "ServerTlsOptions-1"
  }]
}
maxTotalHeadersSize: integer, optional

The maximum size in bytes of the sum of all request headers. When the request headers exceed this limit, IG returns an HTTP 431 error.

Default: 8 192 bytes

The following example configures HTTP/2 connections on port 7070 when IG is acting server-side. The configuration allows IG to accept HTTP/2 requests with large headers. When IG is acting client-side, configure the vertx property of ClientHandler or ReverseProxyHandler:

{
  "connectors": [
    {
      "port": 7070,
      "maxTotalHeadersSize": 16384
    }
  ]
}
vertx: object, optional

Vert.x-specific configuration used to more finely-tune Vert.x instances.

Vert.x values are evaluated as configuration expressions.

Use the Vert.x options described in VertxOptions, with the following exceptions:

  • metricsOptions: Not used

  • metricsEnabled: Enable Vertx metrics. Default: true.

For an example, refer to Monitoring Services.

IG proxies all WebSocket subprotocols by default. To proxy specific WebSocket subprotocols only, list them as follows:

"vertx": {
  "webSocketSubProtocols": ["v1.notifications.forgerock.org", ... ]
}
"gatewayUnits": configuration expression<number>, optional

The number of parallel instances of IG to bind to an event loop. All instances listen on the same ports.

Default: The number of cores available to the JVM.

mode: configuration expression<enumeration>, optional

Set the IG mode to development or production. The value is not case-sensitive.

If mode is not set, the provided configuration token ig.run.mode can be resolved at startup to define the run mode.

For more information, refer to Operating modes.

Default: production

"prefix": configuration expression<string>, optional

The base of the route for administration requests. This route and its subroutes are reserved for administration endpoints.

Default: openig

"properties": object, optional

Configuration parameters declared as property variables for use in the configuration. See also Route properties.

Default: Null

"secrets": SecretStore reference, optional
This property is deprecated; use SecretsProvider instead. For more information, refer to the Deprecated section of the Release Notes.

One or more secret stores, as defined in Secrets.

"temporaryDirectory": configuration expression<string>, optional

Directory containing temporary storage files.

Set this property to store temporary files in a different directory, for example:

{
   "temporaryDirectory": "/path/to/my-temporary-directory"
}

Default: $HOME/.openig/tmp (on Windows,%appdata%\OpenIG\OpenIG\tmp)

"temporaryStorage": TemporaryStorage reference, optional

The TemporaryStorage object to buffer content during processing.

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

Incoming requests use the temporary storage buffer as follows:

  • Used only when streamingEnabled is false.

  • The request is loaded into the IG storage defined in temporaryStorage, before it enters the chain.

  • If the content length of the request is more than the buffer limit, IG returns an HTTP 413 Payload Too Large.

Default: Use the heap object named TemporaryStorage. Otherwise use an internally-created TemporaryStorage object that is named TemporaryStorage, and that uses default settings for a TemporaryStorage object.

"pidFileMode": configuration expression<enumeration>, optional

Mode to allow or disallow startup if there is an existing PID file. Use one of the following values:

  • fail: Startup fails if there is an existing PID file.

  • override: Startup is allowed if there is an existing PID file. IG removes the existing PID file and creates a new one during startup.

Default: fail

"preserveOriginalQueryString": configuration expression<boolean>, optional

Process query strings in URLs, by applying or not applying a decode/encode process to the whole query string.

The following characters are disallowed in query string URL components: ", {, }, <, >, (space), and |. For more information about which query strings characters require encoding, refer to Uniform Resource Identifier (URI): Generic Syntax.

  • true: Preserve query strings as they are presented.

    Select this option if the query string must not change during processing, for example, in signature verification.

    If a query string contains a disallowed character, the request produces a 400 Bad Request.

  • false: Tolerate disallowed characters in query string URL components, by applying a decode/encode process to the whole query string.

    Select this option when a user agent or client produces query searches with disallowed characters. IG transparently encodes the disallowed characters before forwarding requests to the protected application.

    Characters in query strings are transformed as follows:

    • Allowed characters are not changed. For example, sep=a is not changed.

    • Percent-encoded values are re-encoded when the decoded value is an allowed character. For example, sep=%27 is changed to sep=', because ' is an allowed character.

    • Percent-encoded values are not changed when the decoded value is a disallowed character. For example, sep=%22 is not changed, because " is a disallowed character.

    • Disallowed characters are encoded. For example, sep=", is changed to sep=%22, because " is a disallowed character.

Default: false

"session": object, optional

Configures stateful sessions for IG. For information about IG sessions, refer to Sessions.

{
  "session": {
    "cookie": {
      "name": configuration expression<string>,
      "httpOnly": configuration expression<boolean>,
      "path": configuration expression<string>,
      "sameSite": configuration expression<enumeration>,
      "secure": configuration expression<boolean>,
    },
    "timeout": configuration expression<duration>
  }
}
"cookie": object, optional

The configuration of the cookie used to store the stateful session.

Default: The session cookie is treated as a host-based cookie.

"name": configuration expression<string>, optional

The session cookie name.

Default: IG_SESSIONID

"httpOnly": configuration expression<boolean>, optional

Flag to mitigate the risk of client-side scripts accessing protected session cookies.

Default: true

"path": configuration expression<string>, optional

The path protected by the session.

Set a path only if the user agent is able to re-emit session cookies on the path. For example, to re-emit a session cookie on the path /home/cdsso, the user agent must be able to access that path on its next hop.

Default: /.

"sameSite": configuration expression<enumeration>, optional

Options to manage the circumstance in which the session cookie is sent to the server. The following values are listed in order of strictness, with most strict first:

  • STRICT: Send the session cookie only if the request was initiated from the session cookie domain. Not case-sensitive. Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • LAX: Send the session cookie only with GET requests in a first-party context, where the URL in the address bar matches the session cookie domain. Not case-sensitive. Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • NONE: Send the session cookie whenever a request is made to the session cookie domain. With this setting, consider setting secure to true to prevent browsers from rejecting the session cookie. For more information, refer to SameSite cookies

Default: LAX

For CDSSO, set "sameSite":"none" and "secure":"true". For security reasons, many browsers require the connection used by the browser to be secure (HTTPS) for "sameSite":"none". Therefore, if the connection used by the browser is not secure (HTTP), the browser might not supply cookies with "sameSite":"none". For more information, refer to Authenticate with CDSSO.
"secure": configuration expression<boolean>, optional

Flag to limit the scope of the session cookie to secure channels.

Set this flag only if the user agent is able to re-emit session cookies over HTTPS on its next hop. For example, to re-emit a session cookie with the secure flag, the user agent must be connected to its next hop by HTTPS.

Default: false

For CDSSO, set "sameSite":"none" and "secure":"true". For security reasons, many browsers require the connection used by the browser to be secure (HTTPS) for "sameSite":"none". Therefore, if the connection used by the browser is not secure (HTTP), the browser might not supply cookies with "sameSite":"none". For more information, refer to Authenticate with CDSSO.
"timeout": configuration expression<duration>, optional

The duration after which idle sessions are automatically timed out.

The value must be above zero, and no greater than 3650 days (approximately 10 years). IG truncates the duration of longer values to 3650 days.

Default: 30 minutes

"streamingEnabled": configuration expression<boolean>, optional

A flag to manage content:

  • true: IG streams the content of HTTP requests and responses. The content is available for processing bit-by-bit, as soon as it is received.

  • false: IG buffers the content of HTTP requests and responses into the storage defined in temporaryStorage. The content is available for processing only after it has all been received.

When this property is true, consider the following requirements to prevent IG from blocking an executing thread to wait for streamed content:

  • Write runtime expressions that consume streamed content with # instead of $. For more information, refer to runtime expression.

  • In scripts and Java extensions, never use a Promise blocking method, such as get(), getOrThrow(), or getOrThrowUninterruptibly() to obtain the response. For more information, refer to Scripts.

When streamingEnabled=true and a CaptureDecorator with captureEntity=true decorates a component, the decorator interrupts streaming for the captured request or response until the whole entity is captured.

Default: false

Example configuration files

Default configuration

When your configuration does not include an admin.json file, the following admin.json is provided by default:

{
  "prefix": "openig",
  "connectors": [
    { "port" : 8080 }
  ]
}
Overriding the default ApiProtectionFilter

The following example shows an admin.json file configured to override the default ApiProtectionFilter that protects the reserved administrative route. This example is used in Set up the UMA example.

{
  "prefix": "openig",
  "connectors": [
    { "port" : 8080 }
  ],
  "heap": [
    {
      "name": "ClientHandler",
      "type": "ClientHandler"
    },
    {
      "name": "ApiProtectionFilter",
      "type": "CorsFilter",
      "config": {
        "policies": [
          {
            "acceptedOrigins": [ "http://app.example.com:8081" ],
            "acceptedMethods": [ "GET", "POST", "DELETE" ],
            "acceptedHeaders": [ "Content-Type" ]
          }
        ]
      }
    }
  ]
}

GatewayHttpApplication (config.json )

The GatewayHttpApplication is the entry point for all incoming gateway requests. It is responsible for initializing a heap of objects, described in Heap objects, and providing the main Handler that receives all the incoming requests.

The configuration is loaded from a JSON-encoded file, expected by default at $HOME/.openig/config/config.json. Objects configured in config.json can be used by config.json and any IG route. They cannot be used by admin.json.

If you provide a config.json, the IG configuration is loaded from that file. If there is no file, the default configuration is loaded. For the default configuration, and the example config.json used in many of the examples in the documentation, refer to the Examples section of this page.

Routes endpoint

The endpoint is defined by the presence and content of config.json, as follows:

  • When config.json is not provided, the routes endpoint includes the name of the main router in the default configuration, _router.

  • When config.json is provided with an unnamed main router, the routes endpoint includes the main router name router-handler.

  • When config.json is provided with a named main router, the routes endpoint includes the provided name or the transformed, URL-friendly name.

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.

Default objects

IG creates objects by default in config.json. To override a default object, configure an object with the same name in config.json.

Configure default objects in config.json and admin.json separately. An object configured in config.json with the same name as an object configured in admin.json is not the same object.

BaseUriDecorator

A decorator to override the scheme, host, and port of the existing request URI. The default BaseUriDecorator is named baseURI. For more information, refer to BaseUriDecorator.

AuditService

Records no audit events. The default AuditService is NoOpAuditService. For more information, refer to NoOpAuditService.

CaptureDecorator

Captures requests and response messages. The default CaptureDecorator is named capture, and uses the default settings given in CaptureDecorator.

When a capture point for the default CaptureDecorator is defined in a route, for example, when "capture: "all" is set as a top-level attribute of the JSON, log messages for requests and responses passing through the route are written to a log file in $HOME/.openig/logs.

When no capture point is defined in a route, only exceptions thrown during request or response processing are logged.

By default, request and response contexts and entities are not captured. Do one of the following to capture information:

  • Override the default capture decorator declaration, and set captureEntity to true.

  • Declare another CaptureDecorator object with an appropriate configuration and use it at your capture points.

The capture decorator logs information about the HTTP request and response messages, along with their respective headers.

ClientHandler

Communicates with third-party services. For more information, refer to ClientHandler.

ForgeRockClientHandler

Sends ForgeRock Common Audit transaction IDs when communicating with protected applications. The default ForgeRockClientHandler is a Chain, composed of a TransactionIdOutboundFilter and a ClientHandler.

ProxyOptions

A proxy to which a ClientHandler or ReverseProxyHandler can submit requests, and an AmService can submit Websocket notifications. For more information, refer to ProxyOptions.

ReverseProxyHandler

Communicates with third-party services. For more information, refer to ReverseProxyHandler.

ScheduledExecutorService

Specifies the number of threads in a pool.

SecretsService (deprecated)

Manages a store of secrets from files, system properties, and environment variables, by using Commons Secrets API. The default SecretsService is a SystemAndEnvSecretStore with the default configuration. For more information, refer to Secrets.

TemporaryStorage

Manages temporary buffers. For more information, refer to TemporaryStorage.

TimerDecorator

Records time spent within filters and handlers. The default TimerDecorator is named timer. For more information, refer to TimerDecorator.

TransactionIdOutboundFilter

Inserts the ID of a transaction into the header of a request.

Sessions

When the heap is configured with a JwtSession object named Session, the object is used as the default session producer. Stateless sessions are created for all requests.

When a JwtSession is not configured for a request, session information is stored in the IG cookie, called by default IG_SESSIONID.

For more information, refer to Sessions and JwtSession.

Usage

{
  "handler": Handler reference,
  "heap": [ object, ... ],
  "properties": object,
  "secrets"(*): {
    "stores": [ SecretStore reference, ... ]
  },
  "temporaryStorage": TemporaryStorage reference
}

(*)Deprecated

Properties

"handler": Handler 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, optional

The heap object configuration, described in Heap objects.

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

"properties": object, optional

Configuration parameters declared as property variables for use in the configuration. See also Route properties.

Default: Null

"secrets": SecretStore reference, optional
This property is deprecated; use SecretsProvider instead. For more information, refer to the Deprecated section of the Release Notes.

One or more secret stores, as defined in Secrets.

"temporaryStorage": TemporaryStorage reference, optional

The TemporaryStorage object to buffer content during processing.

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

Incoming requests use the temporary storage buffer as follows:

  • Used only when streamingEnabled is false.

  • The request is loaded into the IG storage defined in temporaryStorage, before it enters the chain.

  • If the content length of the request is more than the buffer limit, IG returns an HTTP 413 Payload Too Large.

Default: Use the heap object named TemporaryStorage. Otherwise use an internally-created TemporaryStorage object that is named TemporaryStorage, and that uses default settings for a TemporaryStorage object.

Example configuration files

Default configuration

When your configuration does not include a config.json file, the following configuration is provided by default.

{
    "heap": [
        {
            "name": "_router",
            "type": "Router",
            "config": {
                "scanInterval": "&{ig.router.scan.interval|10 seconds}",
                "defaultHandler": {
                    "type": "DispatchHandler",
                    "config": {
                        "bindings": [
                            {
                                "condition": "${request.method == 'GET' and request.uri.path == '/'}",
                                "handler": {
                                    "type": "WelcomeHandler"
                                }
                            },
                            {
                                "condition": "${request.uri.path == '/'}",
                                "handler": {
                                    "type": "StaticResponseHandler",
                                    "config": {
                                        "status": 405,
                                        "reason": "Method Not Allowed"
                                    }
                                }
                            },
                            {
                                "handler": {
                                    "type": "StaticResponseHandler",
                                    "config": {
                                        "status": 404,
                                        "reason": "Not Found"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    ],
    "handler": "_router"
}

Notice the following features of the default configuration:

  • The handler contains a main router named _router. When IG receives an incoming request, _router routes the request to the first route in the configuration whose condition is satisfied.

  • If the request doesn’t satisfy the condition of any route, it is routed to the defaultHandler. If the request is to access the IG welcome page, IG dispatches the request. Otherwise, IG returns an HTTP status 404 (Resource not found), because the requested resource does not exist.

Example config.json used in the doc

The following example of config.json is used in many of the examples in the documentation:

{
  "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
      }
    }
  ]
}

Notice the following features of the file:

  • The handler contains a main router named _router. When IG receives an incoming request, _router routes the request to the first route in the configuration whose condition is satisfied.

  • The baseURI changes the request URI to point the request to the sample application.

  • The capture captures the body of the HTTP request and response.

  • The JwtSession object in the heap can be used in routes to store the session information as JSON Web Tokens (JWT) in a cookie. For more information, refer to JwtSession.

Heap objects

A heaplet creates and initializes an object that is stored in a heap. A heaplet can retrieve objects it depends on from the heap.

A heap is a collection of associated objects created and initialized by heaplet objects. All configurable objects in IG are heap objects.

The heap configuration is included as an object in admin.json and config.json.

Usage

[
    {
        "name": string,
        "type": string,
        "config": {
            object-specific configuration
        }
    },
    ...
]

Properties

"name": string, required except for inline objects

The unique name to give the heap object in the heap. This name is used to resolve the heap object, for example, when another heap object names a heap object dependency.

"type": string, required

The class name of the object to be created. To determine the type name, see the object’s documentation in this reference.

"config": object, required

The configuration that is specific to the heap object being created.

If all the fields are optional and the configuration uses only default settings, you can omit the config field instead of including an empty config object as the field value.

Configuration settings

Filters, handlers, and other objects whose configuration settings are defined by strings, integers, or booleans, can alternatively be defined by expressions that match the expected type.

For information about expressions, refer to Expressions.

Supported system properties

The following properties are supported in IG. Their names have a special meaning in IG, and they should be used only for their stated purpose:

ig.instance.dir, IG_INSTANCE_DIR

The full path to the directory containing configuration and data for the IG instance.

Default: Linux, $HOME/.openig; Windows, %appdata%\OpenIG

For information about how to use a different location, refer to Configuration location.

org.forgerock.json.jose.jwe.compression.max.decompressed.size.bytes

The maximum size in bytes to which a compressed JWT can be decompressed.

Default: 32 KBytes

org.forgerock.secrets.preferDeterministicEcdsa

When this property is true, and the following conditions are met, JWTs are signed with a deterministic Elliptic Curve Digital Signature Algorithm (ECDSA):

  • ECDSA is used for signing

  • Bouncy Castle is installed

Default: true

org.forgerock.http.TrustTransactionHeader

When this property is true, all incoming X-ForgeRock-TransactionId headers are trusted. Monitoring or reporting systems that consume the logs can allow requests to be correlated as they traverse multiple servers.

Default: false

org.forgerock.http.util.ignoreFormParamDecodingError

When this property is true, form encoding errors caused by invalid characters are ignored, and encoded values are used instead.

Default: false

org.forgerock.json.jose.jwe.compression.max.decompressed.size.bytes

The maximum size in bytes to which a compressed JWT can be decompressed.

Default: 32 KBytes

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.

Usage

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

Properties

"filters": array of Filter references, 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.

"handler": Handler 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

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

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.

Usage

{
  "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, 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.

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.

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:

{
  "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:

{
  "vertx": {
    "initialSettings": {
      "maxHeaderListSize": 16384
    }
  }
}
"connections": configuration expression<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>, 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:

{
  "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>, optional

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

Default: 10 seconds

"connectionTimeToLive": configuration expression<duration>, optional

Not supported

"disableReuseConnection": configuration expression<boolean>, optional

Not supported

"stateTrackingEnabled": configuration expression<boolean>, optional

Not supported

"numberOfWorkers": configuration expression<number>, optional

Not supported

"protocolVersion": configuration expression<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>, 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, 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 object defined in the heap or an inline configuration.

Default: A heap object named ProxyOptions.

"soTimeout": configuration expression<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, optional

The TemporaryStorage object to buffer the request and response, when the streamingEnabled property of admin.json is false.

Default: A heap object named TemporaryStorage.

tls: ClientTlsOptions reference, optional

Use of a TlsOptions reference is deprecated; use ClientTlsOptions instead. For more information, refer to the Deprecated section of the Release Notes.

Configure options for connections to TLS-protected endpoints, based on ClientTlsOptions. Define the object inline or in the heap.

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

`"asyncBehavior": configuration expression<enumeration>, optional

Not supported

"retries": 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.

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

Enable retries.

Default: true

"condition": runtine expression<boolean>, optional

An inline IG expression 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, optional

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

Default: ScheduledExecutorService

"count": configuration expression<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>, 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:

"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:

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

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

{
  "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:

{
  "retries": {
    "executor": {
      "type": "ScheduledExecutorService",
      "config": {
        "corePoolSize": 20
      }
    }
  }
}
"circuitBreaker": 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.

{
  "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>, optional

A flag to enable the circuit breaker.

Default: true

"maxFailures": configuration expression<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.

{
  "retries": {
    "count": 3,
    "delay": "1 second"
  }
}
"openDuration": configuration expression<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, 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, 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.
{
  "slidingCounter":  {
    "size": configuration expression<number>
  }
}
"size": configuration expression<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, optional

A 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. For more information, refer to the Deprecated 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 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.

"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.

"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 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 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.

Default: False.

"keyManager": Key manager reference(s), optional
This property is deprecated; use the tls property instead to configure ClientTlsOptions. For more information, refer to the Deprecated 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. For more information, refer to the Deprecated 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.

Default: Allow any cipher suite supported by the JVM.

"sslContextAlgorithm": string, optional
This property is deprecated; use the tls property instead to configure ClientTlsOptions. For more information, refer to the Deprecated 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. For more information, refer to the Deprecated 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. For more information, refer to the Deprecated 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.

DesKeyGenHandler (deprecated)

This object is deprecated and not considered secure. For more information, refer to the Deprecated 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.

Generates a DES key for use with AM.

Usage

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

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

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

Properties

"bindings": array of objects, required

One or more condition and handler bindings.

"condition": runtime expression<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, 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.

Default: ${true}

"handler": Handler 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>,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:

{
  "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

ForgeRockClientHandler

The ForgeRockClientHandler is a Handler available by default on the heap that chains a default ClientHandler with a TransactionIdOutboundFilter.

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.

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

{
     "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.

IdentityAssertionHandlerTechPreview

The IdentityAssertionHandlerTechPreview, ScriptableIdentityAssertionPluginTechPreview, and IdentityAssertionPluginTechPreview are available in Technology preview. 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.

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

{
  "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>, required
"selfIdentifier": configuration expression<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>, 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, optional

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

Default: 30 seconds

"secretsProvider": SecretsProvider reference, optional

The SecretsProvider to resolve queried cryptographic keys.

Default: The route’s default secret service. For more information, refer to Default secrets object.

"verificationSecretId": configuration expression<secret-id>, required

The secret ID for the secret to validate the signature of the incoming JWT. The secret ID must point to a CryptoKey.

"decryptionSecretId": configuration expression<secret-id>, optional

The secret ID for the secret to decrypt the incoming JWT. The secret ID must point to a CryptoKey.

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

Default: Not set.

"skewAllowance": configuration expression<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, required

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

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

The secret ID of the signing key. The secret ID must point to a CryptoKey.

"algorithm": configuration expression<string>, optional

The signing algorithm.

Default: RS256

"encryption": object, required

Configuration to encrypt the JWT.

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

The secret ID of the encryption key. The secret ID must point to a CryptoKey.

"algorithm": configuration expression<string>, required

The encryption algorithm. Use an algorithm from the List of JWS Algorithms.

"method": configuration expression<string>, required

The encryption method. Use a method from the List of JWE Algorithms.

Example

The following example route is for a Identity Cloud authentication journey that uses a Gateway Communication node.

For information about the identityAssertionPlugin object, refer to the example in ScriptableIdentityAssertionPluginTechPreview.

{
  "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"
      }
    }
  }
}

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.

For information about JWKs and JWK Sets, refer to JSON Web Key (JWK).

Usage

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

The 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, required

One or more purposes for the secret.

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

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

This secret ID must point to a CryptoKey.

"keyUsage": configuration expression<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>, 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:

    $ 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
    {
      "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:

    {
      "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.

ResourceHandler

Serves static content from a directory.

Usage

{
  "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>, 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>, 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>, 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, optional

A TemporaryStorage 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/:

{
  "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:

{
  "name": "StaticWebsite",
  "type": "ResourceHandler",
  "config": {
    "directories": ["/path/to/static/pages"],
    "basePath": "/website",
    "welcomePages": ["index.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.

Usage

{
  "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, 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.

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:

{
  "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:

{
  "vertx": {
    "initialSettings": {
      "maxHeaderListSize": 16384
    }
  }
}
"connections": configuration expression<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>, 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:

{
  "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>, optional

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

Default: 10 seconds

"connectionTimeToLive": configuration expression<duration>, optional

Not supported

"disableReuseConnection": configuration expression<boolean>, optional

Not supported

"stateTrackingEnabled": configuration expression<boolean>, optional

Not supported

"numberOfWorkers": configuration expression<number>, optional

Not supported

"protocolVersion": configuration expression<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>, 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, 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 object defined in the heap or an inline configuration.

Default: A heap object named ProxyOptions.

"soTimeout": configuration expression<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, optional

The TemporaryStorage object to buffer the request and response, when the streamingEnabled property of admin.json is false.

Default: A heap object named TemporaryStorage.

tls: ClientTlsOptions reference, optional

Use of a TlsOptions reference is deprecated; use ClientTlsOptions instead. For more information, refer to the Deprecated section of the Release Notes.

Configure options for connections to TLS-protected endpoints, based on ClientTlsOptions. Define the object inline or in the heap.

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

`"asyncBehavior": configuration expression<enumeration>, optional

Not supported

"retries": 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.

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

Enable retries.

Default: true

"condition": runtine expression<boolean>, optional

An inline IG expression 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, optional

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

Default: ScheduledExecutorService

"count": configuration expression<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>, 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:

"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:

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

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

{
  "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:

{
  "retries": {
    "executor": {
      "type": "ScheduledExecutorService",
      "config": {
        "corePoolSize": 20
      }
    }
  }
}
"circuitBreaker": 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.

{
  "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>, optional

A flag to enable the circuit breaker.

Default: true

"maxFailures": configuration expression<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.

{
  "retries": {
    "count": 3,
    "delay": "1 second"
  }
}
"openDuration": configuration expression<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, 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, 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.
{
  "slidingCounter":  {
    "size": configuration expression<number>
  }
}
"size": configuration expression<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, optional

A ScheduledExecutorService to schedule closure of the circuit after the duration given by openDuration.

Default: The default ScheduledExecutorService in the heap

"websocket": 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). For more information and an example of proxying WebSocket traffic, refer to WebSocket traffic

{
  "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.

"enabled": configuration expression<boolean>,optional

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

Default: false

"connectionTimeout": configuration expression<duration>, optional

The maximum time allowed to establish a WebSocket connection.

Default: The value of handler’s main connectionTimeout.

"soTimeout": configuration expression<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>, 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, optional

Configure options for connections to TLS-protected endpoints, based on a ClientTlsOptions configuration. Define a ClientTlsOptions object inline or in the heap.

Default: Use ClientTlsOptions defined for the handler

"proxyOptions": ProxyOptions 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 object defined in the heap or an inline configuration.

Default: A heap object named ProxyOptions.

"vertx": 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.

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:

{
  "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:

{
  "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 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 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 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.

"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.

"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 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 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.

Default: False.

"keyManager": Key manager reference(s), optional
This property is deprecated; use the tls property instead to configure ClientTlsOptions. For more information, refer to the Deprecated 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. For more information, refer to the Deprecated 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.

Default: Allow any cipher suite supported by the JVM.

"sslContextAlgorithm": string, optional
This property is deprecated; use the tls property instead to configure ClientTlsOptions. For more information, refer to the Deprecated section of the Release Notes.

Default: TLS

"sslEnabledProtocols": array of strings, optional
This property is deprecated; use the tls property instead to configure ClientTlsOptions. For more information, refer to the Deprecated 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. For more information, refer to the Deprecated 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.

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.

  • Through Studio. For information, refer to the Studio guide.

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

{
  "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, 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, 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.

"condition": runtime expression<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:

<logger name="org.forgerock.openig.handler.router.RouterHandler" level="trace" />

For information, refer to Manage logs.

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.

"name": 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, optional
This property is deprecated; use SecretsProvider instead. For more information, refer to the Deprecated section of the Release Notes.

One or more secret stores, as defined in Secrets.

"session": AsyncSessionManager reference. 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, and Sessions.

"auditService": AuditService 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, 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:

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

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

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

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

Default: Empty

"decorator name": Decorator 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.

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 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.

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 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.

Example conditions and requests
Condition Requests that meet the condition
"${true}"

All requests, because this expression always evaluates to true.

"${find(request.uri.path, '^/login')}"

http://app.example.com/login, . . .

"${request.uri.host == 'api.example.com'}"

http://api.example.com/, https://api.example.com/home, http://api.example.com:8080/home, . . .

"${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.

"${find(request.uri.query, 'demo=simple')}"

http://ig.example.com:8080/login?demo=simple, . . .

For information about URI query, refer to query in URI.

"${request.uri.scheme == 'http'}"

http://ig.example.com:8080, . . .

"${find(request.uri.path, '^/dispatch') or find(request.uri.path, '^/mylogin')}"

http://ig.example.com:8080/dispatch, http://ig.example.com:8080/mylogin, . . .

"${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, . . .

"condition": "${find (request.uri.path, '&{uriPath}')}"

http://ig.example.com:8080/hello, when the following property is configured:

{
  "properties": {
    "uriPath": "hello"
  }
}

For information about including properties in the configuration, refer to Route properties.

"condition": "${request.headers['X-Forwarded-Host'][0] == 'service.example.com'}"

Requests with the header X-Forwarded-Host, whose first value is service.example.com.

"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.

"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.

  • 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

{
    "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, 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>, 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:

{
  "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.

"scanInterval": configuration expression<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 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.

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 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.

Example

The following config.json file configures a Router:

{
  "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.

SamlFederationHandler (deprecated)

This handler is deprecated; use the SamlFederationFilter 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 in AM’s SAML v2.0 guide.

Usage

{
    "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 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:

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

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

{
  "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>, 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, 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.

Default: Empty.

"assertionConsumerEndpoint": configuration expression<string>, optional

Default: fedletapplication (same as the Fedlet)

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

"authnContext": configuration expression<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>, optional

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

Default: |

"logoutURI": configuration expression<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>, 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>, optional

Default: fedletSLORedirect (same as the Fedlet)

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

"singleLogoutEndpointSoap": configuration expression<string>, optional

Default: fedletSloSoap (same as the Fedlet)

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

"SPinitiatedSLOEndpoint": configuration expression<string>, optional

Default: SPInitiatedSLO

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

"SPinitiatedSSOEndpoint": configuration expression<string>, optional

Default: SPInitiatedSSO

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

"useOriginalUri": configuration expression<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>, 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.

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:

{
    "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> or a Response.

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

Usage

{
    "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.

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.

{
  "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

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

Properties

"bindings": array of objects, required

A list of handler and postcondition bindings.

"handler": Handler 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>, 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.

Default: ${true}

StaticResponseHandler

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

Usage

{
  "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.

"reason": configuration expression<string>, optional

Used only for custom HTTP status codes. For more information, refer to Response Status Codes and Status Code Registry.

"headers": map, optional

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

  • name is a configuration expression<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> 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:

"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:

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

Default: Empty

"trailers": map, optional

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

  • name is a configuration expression<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> for trailer values.

Default: Empty

"entity": runtime expression<string> or array of runtime expression<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.

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

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

Filters

Filter objects intercept requests and responses during processing, and change them as follows:

  • Leave the request, response, and contexts unchanged. For example, the filter can simply can log the context as it passes through the filter.

  • In the request flow, change any aspect of the request (such as the URL, headers, or entity), or replace the request with a new Request object.

  • In the response flow, change any aspect of the response (such as the status, headers, or entity), or return a new Response instance

AllowOnlyFilter

Authorizes a request to continue processing if it satisfies at least one of the configured rules. Otherwise, passes the request to the FailureHandler or returns an HTTP 401 Unauthorized, with an empty response body.

This filter manages requests from the last request sender, otherwise called the request from the last hop, or the request from a direct client.

For debugging, configure the AllowOnlyFilter name, and add the following logger to logback.xml, replacing filter_name with the name:

org.forgerock.openig.filter.allow.AllowOnlyFilter.filter_name

For more information, see Manage logs.

Usage

{
  "name": string,
  "type": "AllowOnlyFilter",
  "config": {
    "rules": [ object, ... ],
    "failureHandler": Handler reference
  }
}

Properties

"rules": array of objects, required

An array of one or more rules configuration objects to specify criteria for the request.

When more than one rules configuration object is included in the array, the request must match at least one of the configuration objects.

When more than one property is specified in the rules configuration (for example, from and destination) the request must match criteria for each property.

{
  "rules": [
    {
      "name": configuration expression<string>,
      "from": [ object, ... ],
      "destination": [ object, ... ],
      "when": configuration expression<boolean>
    },
    ...
  ]
}
"name": configuration expression<string>, optional

A name for the rules configuration. When logging is configured for the AllowOnlyFilter, the rule name appears in the logs.

"from": array of objects, required

An array of one or more from configuration objects to specify criteria about the last request sender (the direct client).

When more than one from configuration object is included in the array, the last request sender must match at least one of the configuration objects.

When both ip and certificate properties are included in the configuration, the last request sender must match criteria for both properties.

"from": [
  {
    "ip": {
      "list": [configuration expression<string>, ...],
      "resolver": runtime expression<string>
    },
    "certificate" : {
      "subjectDNs" : Pattern[]
    }
  },
  ...
]
"ip": object, optional

Criteria about the IP address of the last request sender.

"list": array of configuration expression<strings>, required:

An array of IP addresses or IP address ranges, using IPv4 or IPv6, and CIDR notation. The following example includes different formats:

"list": ["127.0.0.1", "::1", "192.168.0.0/16", "1234::/16"]

The IP address of the last request sender must match at least one of the specified IP addresses or IP address ranges.

"resolver": runtime expression<string>, optional:

An expression that returns an IP address as a string. The following example returns an IP address from the first item in X-Forwarded-For:

"resolver": "${request.headers['X-Forwarded-For'][0]}"

Default: Resolve the IP address from the following items, in the following order:

  1. If there is a Forwarded header, use the IP address of the last hop.

  2. Otherwise, if there is an X-Forwarded-For header, use the IP address of the last hop.

  3. Otherwise, use the IP address of the connection.

"certificate": array of objects, optional

An array of certificate configuration objects that specify criteria about the certificate of the last request sender.

"subjectDNs": array of patterns, required:

An array of patterns to represent the expected distinguished name of the certificate subject, the subjectDN. The subjectDN of the last request sender must match at least one of the patterns.

"destination": array of objects, optional

An array of destination configuration objects to specify criteria about the request destination.

When more than one destination configuration object is included in the array, the request destination must match at least one of the configuration objects.

When more than one property is specified in the destination configuration, for example hosts and ports, the request destination must match criteria for each property.

"destination": [
  {
    "hosts": [pattern, ... ],
    "ports": [configuration expression<string>, ... ],
    "methods": [configuration expression<string>, ... ],
    "paths": [pattern, ... ]
  },
  ...
]
"hosts": array of patterns, optional

An array of case-insensitive patterns to match the request.host attribute. Patterns are matched with the Java Pattern class.

When this property is configured, the request destination must match at least one host pattern in the array.

Default: Any host is allowed.

"ports": array of configuration expression<strings>, optional

An array of strings to match the request.port attribute. Specify values in the array as follows:

  • Array of single ports, for example ["80", "90"].

  • Array of port ranges, for example ["100:200"].

  • Array of single ports and port ranges, for example ["80", "90", "100:200"].

When this property is configured, the destination port must match at least one entry in the array.

Default: Any port is allowed.

"methods": array of configuration expression<strings>, optional

An array of HTTP methods to match the request.method attribute.

When this property is configured, the request method must match at least one method in the array.

Default: Any method is allowed.

"paths": array of patterns, optional

An array of case-sensitive patterns to match the request.url_path attribute. Patterns are matched with the Java Pattern class.

When this property is configured, the destination path must match at least one path in the array.

Default: Any path is allowed.

"when": runtime expression<boolean>, optional

A flag to indicate that the request meets a condition. When true, the request is allowed.

The following condition is met when the first value of h1 is 1:

"when": "${request.headers['h1'][0] == '1'}"

Default: ${true}

"failureHandler": Handler reference, optional

Handler to treat the request if none of the declared rules are satisfied.

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

Default: HTTP 401 Unauthorized, with an empty response body.

See also Handlers.

Examples

In the following example, a request is authorized if the last request sender satisfies either of the following conditions:

  • Certificate subjectDN matches .*CN=test$ or CN=me, and the IP address is in the range 1.2.3.0/24.

  • IP address is 123.43.56.8.

"from": [
   {
     "certificate": {
          "subjectDNs": [".*CN=test$", "CN=me"]
     },
     "ip": {
       "list": ["1.2.3.0/24"]
     }
   },
   {
     "ip": {
       "list": ["123.43.56.8"]
     }
   },
]

In the following example, a request is authorized if the request destination satisfies all of the following conditions:

  • The host is myhost1.com or www.myhost1.com

  • The port is 80.

  • The method is POST or GET

  • The path matches /user/*.

"destination": [
  {
    "hosts": ["myhost1.com", "www.myhost1.com"],
    "ports": ["80"],
    "methods": ["POST", "GET"],
    "paths": ["/user/*"]
  }
]

The following example authorizes a request to continue processing if the requests meets the conditions set by either rule1 or rule2:

{
  "type": "AllowOnlyFilter",
  "config": {
    "rules": [
      {
        "name": "rule1",
        "from": [
          {
            "certificate": {
              "subjectDNs": [".*CN=test$", "CN=me"]
            },
            "ip": {
              "list": ["1.2.3.0/24"]
            }
          }
        ],
        "destination": [
          {
            "hosts": ["myhost1.com", "www.myhost1.com"],
            "ports": ["80"],
            "methods": ["POST", "GET"],
            "paths": ["/user/*"]
          }
        ],
        "when": "${request.headers['h1'][0] == '1'}"
      },
      {
        "name":"rule2",
        "when": "${request.headers['h1'][0] == '2'}"
      }
    ]
  }
}

AmSessionIdleTimeoutFilter

Forces the revocation of AM sessions that have been idle for a specified duration. The AmSessionIdleTimeoutFilter issues an authenticated and encrypted JWT to track activity on the AM session, and conveys it within a persistent cookie. The tracking token contains the following parts:

  • The time when the user was last active

  • A hash of the AM session cookie, to bind the tracking token to the AM session cookie

  • The idle timeout

Multiple filter instances can share the same tracking token, for example, in a clustered IG configuration, or when a federation of applications protected by authentication filters need to have a flexible idle timeout strategy.

AmSessionIdleTimeoutFilter requires the following configuration:

  • In AM, client-side sessions must be enabled for the realm in which the tracking token operates. See Configure client-side sessions in AM’s Sessions Guide.

  • In AM, client-side session denylisting must be enabled. See Configure client-side session denylisting in AM’s Sessions Guide.

  • The AmSessionIdleTimeoutFilter must be placed in a route before a filter that uses the AM session token, such as a SingleSignOnFilter or PolicyEnforcementFilter.

  • In production environments, and when multiple AmSessionIdleTimeoutFilters use the same tracking token, the encryption must not rely on the default configuration. It must be configured identically on each filter that uses the tracking token.

The following image shows the flow of information when an AmSessionIdleTimeoutFilter sits in front of a CrossDomainSingleSignOnFilter, to manage AM session timeout.

idletime

[1-5] When the AmSessionIdleTimeoutFilter receives an unauthenticated request, it passes the request along the chain, and the CrossDomainSingleSignOnFilter manages authentication.

[6-8] When the AmSessionIdleTimeoutFilter receives an authenticated request, it checks that the AM session token is valid, and then passes the request along the chain.

[9-10] If the AM session was valid, the AmSessionIdleTimeoutFilter issues a tracking token on the response flow, containing the following information:

  • Hash of the AM session token

  • Current timestamp

  • Idle timeout of the current filter

If the AM session was not valid, the AmSessionIdleTimeoutFilter does nothing on the response flow.

[11-12] The AmSessionIdleTimeoutFilter places the tracking token in persistent tracking cookie, and sends it with the response, to be used in the next request.

[13-15] When the same or another AmSessionIdleTimeoutFilter receives an authenticated request with a tracking token, it checks that the AM session token is valid, and checks that tracking token hash is bound to the AM session.

[16] Depending on the strategy set by idleTimeoutUpdate, the AmSessionIdleTimeoutFilter selects the value for idleTimeout from the tracking token (set by the AmSessionIdleTimeoutFilter in a previous request) or from its own value of idleTimeout (if this is a different instance of AmSessionIdleTimeoutFilter).

The AmSessionIdleTimeoutFilter checks for AM session timeout. If the last activity time plus the idle timeout is before the current time, the session has timed out. For example, a session with the following values has timed out:

  • last activity time: 15h30 today

  • idle timeout: 5 mins

  • current time: 15h40

[17-21] The AM session has timed out, so the AmSessionIdleTimeoutFilter does the following:

  • Forces AM to revoke the session.

  • Passes the request along the chain.

  • Expires the tracking cookie on the response flow, and sends it with the response.

[22-26] The session has not timed out, so the AmSessionIdleTimeoutFilter does the following:

  • Passes the request along the chain.

  • Updates the tracking token on the response flow, with the current timestamp and the value for idleTimeOut, using the same value for that was selected in step 16.

  • Places the tracking token in a persistent tracking cookie, and sends it with the response, to be used in the next request.

Usage

{
  "name": string,
   "type": "AmSessionIdleTimeoutFilter",
   "config": {
     "amService": AmService reference,
     "idleTimeout": configuration expression<duration>,
     "sessionToken": runtime expression<string>,
     "idleTimeoutUpdate": configuration expression<enumeration>,
     "secretsProvider": SecretsProvider reference,
     "encryptionSecretId": configuration expression<secret-id>,
     "encryptionMethod": configuration expression<string>,
     "cookie": object
   }
}

Properties

"amService": AmService reference, required

The AmService that refers to the AM instance that issue tracked session token.

"idleTimeout": configuration expression<duration>, required

The time a session can be inactive before it is considered as idle.

When an AmSessionIdleTimeoutFilter creates the tracking token, the token’s value for idleTimeout is set by this property. When a different AmSessionIdleTimeoutFilter accesses the same tracking token, depending on the strategy set by idleTimeoutUpdate, the token’s value for idleTimeout can be updated by the second AmSessionIdleTimeoutFilter.

"sessionToken": runtime expression<string>, optional

The location of the AM session token in the request. The following example accesses the first value of the request cookie iPlanetDirectoryPro:

"sessionToken": "${request.cookies['iPlanetDirectoryPro'][0].value}"

For more information, refer to Find the AM session cookie name.

Default: ${request.cookies['<cookie name defined in the referenced AmService>'][0].value}

idleTimeoutUpdate: configuration expression<enumeration>, required

When multiple AmSessionIdleTimeoutFilters use the same tracking token, this property selects whether to use the idleTimeout from this filter or from the tracking token.

Use one of the following values:

  • NEVER: Use the idle timeout from the tracking token, and ignore the idle timeout from this filter.

  • ALWAYS: Use the idle timeout from this filter, and ignore the idle timeout from the tracking token.

  • INCREASE_ONLY: Compare the idle timeout from this filter and the tracking token, and use the longest value.

  • DECREASE_ONLY: Compare the idle timeout from this filter and the tracking token, and use the shortest value.

Default: ALWAYS

"secretsProvider": SecretsProvider reference, optional

The SecretsProvider to query for secrets to encrypt the tracking token.

"encryptionSecretId": configuration expression<secret-id>, optional

The secret ID of the encryption key used to encrypt the tracking cookie.

This secret ID must point to a CryptoKey`.

In production environments, and when multiple AmSessionIdleTimeoutFilters use the same tracking cookie, the encryption must not rely on the default configuration. It must be configured identically on each filter that uses the cookie.

Authenticated encryption is achieved with a symmetric encryption key. Therefore, the secret must refer to a symmetric key.

For more information, refer to RFC 5116.

Default: When no secretsProvider is provides, IG generates a random symmetric key for authenticated encryption.

"encryptionMethod": configuration expression<string>, optional

The algorithm to use for authenticated encryption. For information about allowed encryption algorithms, refer to RFC 7518: "enc" (Encryption Algorithm) Header Parameter Values for JWE.

Default: A256GCM

"cookie": object, optional

Configuration of the activity tracking cookie.

{
  "name": configuration expression<string>,
  "domain": configuration expression<string>,
  "httpOnly": configuration expression<boolean>,
  "path": configuration expression<string>,
  "sameSite": configuration expression<enumeration>,
  "secure": configuration expression<boolean>
}
"name": configuration expression<string>, optional

The cookie name.

Default: x-ig-activity-tracker

"domain": configuration expression<string>, optional

Domain to which the cookie applies.

Default: The fully qualified hostname of the IG host.

"httpOnly": configuration expression<boolean>, optional

Flag to mitigate the risk of client-side scripts accessing protected cookies.

Default: true

"path": configuration expression<string>, optional

Path to apply to the cookie.

Default: /

"sameSite": configuration expression<enumeration>, optional

Options to manage the circumstances in which a cookie is sent to the server. Use one of the following values to reduce the risk of CSRF attacks:

  • STRICT: Send the cookie only if the request was initiated from the cookie domain. Not case-sensitive. Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • LAX: Send the cookie only with GET requests in a first-party context, where the URL in the address bar matches the cookie domain. Not case-sensitive. Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • NONE: Send the cookie whenever a request is made to the cookie domain. With this setting, consider setting secure to true to prevent browsers from rejecting the cookie. For more information, refer to SameSite cookies.

Default: Null

"secure": configuration expression<boolean>, optional

Flag to limit the scope of the cookie to secure channels.

Default: false

Example

{
  "type": "AmSessionIdleTimeoutFilter",
  "config": {
    "sessionToken": "${request.cookies['iPlanetDirectoryPro'][0].value}",
    "amService": "AmService",
    "idleTimeout": "1 minute",
    "idleTimeoutUpdate": "ALWAYS",
    "cookie": {
      "name": "x-ig-activity-tracker",
      "domain": null,
      "path": "/",
      "secure": false,
      "httpOnly": true,
      "sameSite": null
    },
   "secretsProvider": "secrets-provider-ref",
   "encryptionMethod": "A256GCM",
   "encryptionSecretId": "crypto.key.secret.id"
  }
}

AssignmentFilter

Verifies that a specified condition is met. If the condition is met or if no condition is specified, the value is assigned to the target. Values can be assigned before the request is handled and after the response is handled.

Usage

{
  "name": string,
  "type": "AssignmentFilter",
  "config": {
    "onRequest": [
      {
        "condition": runtime expression<boolean>,
        "target": lvalue-expression,
        "value": runtime expression
      }, ...
    ],
    "onResponse": [
      {
        "condition": runtime expression<boolean>,
        "target": lvalue-expression,
        "value": runtime expression
      }, ...
    ]
  }
}

Properties

"onRequest": array of objects, optional

Defines a list of assignment bindings to evaluate before the request is handled.

"onResponse": array of objects, optional

Defines a list of assignment bindings to evaluate after the response is handled.

"condition": runtime expression<boolean>, optional

If the expression evaluates true, the value is assigned to the target.

Default: ${true}

"target": <lvalue-expression>, required

Expression that yields the target object whose value is to be set.

"value": runtime expression<object> , optional

The value to be set in the target. The value can be a string, information from the context, or even a whole map of information.

Examples

Add info to a session

The following example assigns a value to a session. Add the filter to a route to prevent IG from clearing up empty JWTSession cookies:

{
  "type": "AssignmentFilter",
  "config": {
    "onRequest": [{
      "target": "${session.authUsername}",
      "value": "I am root"
    }]
  }
}
Capture and store login credentials

The following example captures credentials and stores them in the IG session during a login request. Notice that the credentials are captured on the request but are not marked as valid until the response returns a positive 302. The credentials could then be used to log a user in to a different application:

{
  "name": "PortalLoginCaptureFilter",
  "type": "AssignmentFilter",
  "config": {
    "onRequest": [
      {
        "target": "${session.authUsername}",
        "value": "${request.queryParams['username'][0]}"
      },
      {
        "target": "${session.authPassword}",
        "value": "${request.queryParams['password'][0]}"
      },
      {
        "comment": "Authentication has not yet been confirmed.",
        "target": "${session.authConfirmed}",
        "value": "${false}"
      }
    ],
    "onResponse": [
      {
        "condition": "${response.status.code == 302}",
        "target": "${session.authConfirmed}",
        "value": "${true}"
      }
    ]
  }
}

AuthorizationCodeOAuth2ClientFilter

Uses OAuth 2.0 delegated authorization to authenticate end users. The filter can act as an OpenID Connect relying party or as an OAuth 2.0 client.

AuthorizationCodeOAuth2ClientFilter performs the following tasks:

  • Allows the user to select an Authorization Server from one or more static client registrations or by discovery and dynamic registration.

    In static client registration, Authorization Servers are provided by Issuer, and registrations are provided by ClientRegistration.

  • Redirects the user through the authentication and authorization steps of an OAuth 2.0 authorization code grant, which results in the Authorization Server returning an access token to the filter.

  • When an authorization grant succeeds, injects the access token data into a configurable target in the context so that subsequent filters and handlers can access the access token. Subsequent requests can use the access token without authenticating again.

  • When an authorization grant fails, the filter injects information about the failure into the OAuth2FailureContext, which is provided to the failureHandler object.

Service URIs

Service URIs are constructed from the clientEndpoint, as follows:

clientEndpoint/login/?discovery=user-input&goto=url

Discover and register dynamically with the end user’s OpenID Provider or with the client registration endpoint as described in RFC 7591, using the value of user-input.

After successful registration, redirect the end user to the provider for authentication and authorization consent. Then redirect the user agent back to the callback client endpoint, and then the goto URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error.

To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

clientEndpoint/login?registration=clientId&issuer=issuerName&goto=url

Redirect the end user for authorization with the specified registration, defined by the ClientRegistration’s clientId and issuerName. For information, refer to ClientRegistration.

The provider corresponding to the registration then authenticates the end user and obtains authorization consent before redirecting the user agent back to the callback client endpoint.

If successful, the filter saves the authorization state in the session and redirects the user agent to the goto URL.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error.

To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

clientEndpoint/logout?goto=url

Remove the authorization state for the end user, and redirect the request to the goto URL.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error.

To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

If no goto URL is specified in the request, use defaultLogoutGoto.

clientEndpoint/callback

Handle the callback from the OAuth 2.0 Authorization Server occuring as part of the authorization process.

If the callback is handled successfully, the filter saves the authorization state in the context at the specified target location and redirects to the URL provided to the login endpoint during login.

Other request URIs

Restore the authorization state in the specified target location, and call the next filter or handler in the chain.

Usage

{
  "name": string,
  "type": "AuthorizationCodeOAuth2ClientFilter",
  "config": {
    "clientEndpoint": runtime expression<uri string>,
    "failureHandler": Handler reference,
    "loginHandler": Handler reference,
    "registrations": [ ClientRegistration reference, ... ],
    "metadata": object,
    "cacheExpiration": configuration expression<duration>,
    "executor": ScheduledExecutorService reference,
    "target": lvalue-expression,
    "defaultLoginGoto": runtime expression<url>,
    "defaultLogoutGoto": runtime expression<url>,
    "requireHttps": configuration expression<boolean>,
    "requireLogin": configuration expression<boolean>,
    "revokeOauth2TokenOnLogout": configuration expression<boolean>,
    "openIdEndSessionOnLogout": configuration expression<boolean>,
    "prompt": configuration expression<string>,
    "issuerRepository": Issuer repository reference,
    "discoveryHandler": Handler reference,
    "discoverySecretId": configuration expression<secret-id>,
    "tokenEndpointAuthMethod": configuration expression<enumeration>,
    "tokenEndpointAuthSigningAlg": configuration expression<string>,
    "oAuth2SessionKey": configuration expression<string>,
    "secretsProvider": SecretsProvider reference
  }
}

Properties

"clientEndpoint": runtime expression<url>, required

The URI to the client endpoint.

So that routes can accept redirects from the Authorization Server to the callback endpoint, the clientEndpoint must be the same as the route condition or a sub path of the route condition. For example:

  • The same as the route condition:

    "condition": "${find(request.uri.path, '^/discovery')}"
    "clientEndpoint": "/discovery"
  • As a sub path of the route condition:

    "condition": "${find(request.uri.path, '^/home/id_token')}"
    "clientEndpoint": "/home/id_token/sub-path"

    Service URIs are constructed from the clientEndpoint. For example, when clientEndpoint is openid, the service URIs are /openid/login, /openid/logout, and /openid/callback. These endpoints are implicitly reserved, and attempts to access them directly can cause undefined errors.

    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.

    See also Expressions.

"failureHandler": Handler reference, required

An inline handler configuration object, or the name of a handler object defined in the heap.

When the OAuth 2.0 Resource Server denies access to a resource, the failure handler can be invoked only if the error response contains a WWW-Authenticate header (meaning that there was a problem with the OAuth 2.0 exchange). All other responses are forwarded to the user agent without invoking the failure handler.

If the value of the WWW-Authenticate header is invalid_token, the AuthorizationCodeOAuth2ClientFilter tries to refresh the access token:

  • If the token is refreshed, the AuthorizationCodeOAuth2ClientFilter tries again to access the protected resource.

  • If the token is not refreshed, or if the second attempt to access the protected resource fails, the AuthorizationCodeOAuth2ClientFilter invokes the failure handler.

Consider configuring the handler to access information in OAuth2FailureContext.

"loginHandler": Handler reference, required if there are zero or multiple client registrations, optional if there is one client registration

The handler to invoke when the user must select a registered identity provider for login. When registrations contains only one client registration, this handler is optional but is displayed if specified.

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

When you use loginHandler in AuthorizationCodeOAuth2ClientFilter, retrieve the original target URI for the request from one of the following contexts:

"registrations": array of ClientRegistration references optional

List of client registrations that authenticate IG to the Authorization Server. The list must contain all client registrations that are to be used by the client filter.

The value represents a static client registration with an Authorization Server, as described in ClientRegistration.

"metadata": <object>, required for dynamic client registration and ignored otherwise

The values of the object are evaluated as configuration expression<strings>.

This object holds client metadata as described in OpenID Connect Dynamic Client Registration 1.0, and optionally a list of scopes. See that document for additional details and a full list of fields.

This object can also hold client metadata as described in RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol. See that RFC for additional details.

The following partial list of metadata fields is not exhaustive, but includes metadata that is useful with AM as OpenID Provider:

"redirect_uris": array of configuration expression<url>, required

The array of redirection URIs to use when dynamically registering this client.

One of the registered values must match the clientEndpoint.

"client_name": configuration expression<string>, optional

Name of the client to present to the end user.

"scope": _configuration expression<string>, optional

Space-separated string of scopes to request of the OpenID Provider, for example:

"scope": "openid profile"

This property is available for dynamic client registration with AM, or with Authorization Servers that support RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol

"cacheExpiration": configuration expression<duration>, optional

Duration for which to cache user-info resources.

IG lazily fetches user info from the OpenID provider. In other words, IG only fetches the information when a downstream Filter or Handler uses the user info. Caching allows IG to avoid repeated calls to OpenID providers when reusing the information over a short period.

Default: 10 minutes

Set this to disabled or zero to disable caching. When caching is disabled, user info is still lazily fetched.

"executor": ScheduledExecutorService reference, optional

A ScheduledExecutorService to schedule the execution of tasks, such as the eviction of entries in the OpenID Connect user information cache.

Default: ScheduledExecutorService

"target": lvalue-expression, optional

An expression that yields the target object. Downstream filters and handlers can use data in the target to enrich the existing request or create a new request.

When the target is openid, the following information can be provided in ${attributes.openid}:

  • access_token: Value of the OAuth 2.0 access token

  • scope: Scopes associated with the OAuth 2.0 access token

  • token_type: Authentication token type; for example, Bearer

  • expires_in: Number of milliseconds until the OAuth 2.0 access token expires

  • id_token: Value of the OpenID Connect token

  • id_token_claims: Claims used in the OpenID Connect token

  • client_endpoint: URL to the client endpoint

  • client_registration: Client ID of the OAuth 2.0 client that enables IG to communicate as an OAuth 2.0 client with an authorization server

  • user_info: Profile attributes of an authenticated user; for example, sub, name, family_name

Data is provided to the target as follows:

  • If the authorization process completes successfully, the AuthorizationCodeOAuth2ClientFilter injects the authorization state data into the target. In the following example, a downstream StaticRequestFilter retrieves the username and password from the target to log the user in to the sample application.

    {
      "type": "StaticRequestFilter",
      "config": {
        "method": "POST",
        "uri": "http://app.example.com:8081/login",
        "form": {
          "username": [
            "${attributes.openid.user_info.sub}"
          ],
           "password": [
            "${attributes.openid.user_info.family_name}"
          ]
        }
      }
    }

    For information about setting up this example, refer to Authenticate Automatically to the Sample Application.

  • If the failure handler is invoked, the target can be populated with information such as the exception, client registration, and error, as described in "failureHandler" in this reference page.

    Default: ${attributes.openid}

    See also Expressions.

"defaultLoginGoto": runtime expression<url>,optional

After successful authentication and authorization, if the user accesses the clientEndpoint/login endpoint without providing a landing page URL in the goto parameter, the request is redirected to this URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error.

To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

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.

Default: return an empty page.

"defaultLogoutGoto": runtime expression<url>,optional

If the user accesses the clientEndpoint/logout endpoint without providing a goto URL, the request is redirected to this URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error.

To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

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.

Default: return an empty page.

"requireHttps": configuration expression<boolean>, optional

Whether to require that original target URI of the request uses the HTTPS scheme.

If the received request doesn’t use HTTPS, it is rejected.

Default: true.

"requireLogin": configuration expression<boolean>, optional

Whether to require authentication for all incoming requests.

Default: true.

"revokeOauth2TokenOnLogout": configuration expression<boolean>, optional

When true, call the revocationEndpoint defined in Issuer to revoke the access token or refresh token issued by the Authorization Server during login.

If this property is false or if revocationEndpoint in Issuer isn’t defined, IG doesn’t revoke the tokens.

Processing errors generate warnings in the logs but don’t break the logout flow.

Default: false.

"openIdEndSessionOnLogout": configuration expression<boolean>, optional

When true, redirect the user to the endSessionEndpoint defined in Issuer to log the user out of the Authorization Server. Use this properties to initiate logout from an OpenID Connect resource provider.

If this property is false or if endSessionEndpoint in Issuer isn’t defined, IG doesn’t redirect the user to log the user out of the authorization server.

If the user accesses the endSessionEndpoint endpoint without providing a goto URL, IG redirects the request to the defaultLogoutGoto.

For more information, refer to OpenID Connect Session Management.

Default: false

"prompt": configuration expression<string>, optional

A space-separated, case-sensitive list of strings that indicate whether to prompt the end user for authentication and consent. Use in OIDC flows only.

Refer to the Authorization Server documentation for information about supported prompt values. For example, refer to prompt in Identity Cloud’s OAuth 2.0 guide or prompt in AM’s OAuth 2.0 guide.

IG provides the following values:

  • none: Don’t display authentication or consent pages. Don’t use this value in the same list as login, consent, or select_account.

  • login: Prompt the end user to reauthenticate even if they have a valid session on the Authorization Server.

  • consent: Prompt the end user to consent before returning information to the Client, even if they have already consented in the session.

  • select_account: Prompt the end user to select a user account.

Example: Prompt the end user to reauthenticate
"prompt": "login"
Example: Prompt the end user to reauthenticate and consent
"prompt": "login consent"
"issuerRepository": Issuer repository reference, optional

A repository of OAuth 2.0 issuers, built from discovered issuers and the IG configuration.

Provide the name of an IssuerRepository object defined in the heap.

Default: Look up an issuer repository named IssuerRepository in the heap. If none is explicitly defined, then a default one named IssuerRepository is created in the current route.

See also IssuerRepository.

"discoveryHandler": Handler reference, optional

Use this property for discovery and dynamic registration of OpenID Connect clients.

Provide either the name of a Handler object defined in the heap or an inline Handler configuration object. Usually, set this to the name of a ClientHandler configured in the heap or a chain that ends in a ClientHandler.

Default: The default ClientHandler.

See also Handlers, ClientHandler.

"discoverySecretId": configuration expression<secret-id>, required for discovery and dynamic registration

Use this property for discovery and dynamic registration of OAuth 2.0 clients.

This secret ID must point to a CryptoKey.

Specifies the secret ID of the secret that is used to sign a JWT before the JWT is sent to the Authorization Server.

If discoverySecretId is used, then the tokenEndpointAuthMethod is always private_key_jwt.

"tokenEndpointAuthMethod": configuration expression<enumeration>, optional

Use this property for discovery and dynamic registration of OAuth 2.0 clients.

The authentication method with which a client authenticates to the authorization server or OpenID provider at the token endpoint. For information about client authentication methods, refer to OpenID Client Authentication. The following client authentication methods are allowed:

  • client_secret_basic: Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization Server by using HTTP basic access authentication, as in the following example:

    POST /oauth2/token HTTP/1.1
    Host: as.example.com
    Authorization: Basic ....
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&
    code=...
  • client_secret_post: Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization Server by including the client credentials in the request body, as in the following example:

    POST /oauth2/token HTTP/1.1
    Host: as.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&;
    client_id=...&
    client_secret=...&
    code=...
  • private_key_jwt: Clients send a signed JSON Web Token (JWT) to the Authorization Server. IG builds and signs the JWT, and prepares the request as in the following example:

    POST /token HTTP/1.1
    Host: as.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&
    code=...&
    client_id=<clientregistration_id>&
    client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
    client_assertion=PHNhbWxwOl ... ZT

    If the Authorization Server doesn’t support private_key_jwt, a dynamic registration falls back on the method returned by the Authorization Server, for example, client_secret_basic or client_secret_post.

    If tokenEndpointAuthSigningAlg is not configured, the RS256 signing algorithm is used for private_key_jwt.

    Consider these points for identity providers:

    • Some providers accept more than one authentication method.

    • If a provider strictly enforces how the client must authenticate, align the authentication method with the provider.

    • If a provider doesn’t support the authentication method, the provider sends an HTTP 400 Bad Request response with an invalid_client error message, according to RFC 6749: Error Response.

    • If the authentication method is invalid, the provider sends an IllegalArgumentException.

Default: If discoverySecretId is used, then the tokenEndpointAuthMethod is always private_key_jwt. Otherwise, it is client_secret_basic.

"tokenEndpointAuthSigningAlg": configuration expression<string>, optional

The JSON Web Algorithm (JWA) used to sign the JWT that is used to authenticate the client at the token endpoint. The property is used when private_key_jwt is used for authentication.

If the Authorization Server sends a notification to use a different algorithm to sign the JWT, that algorithm is used.

Default: If discoverySecretId is used, then the tokenEndpointAuthSigningAlg is RS256. Otherwise, it is not used.

"oAuth2SessionKey": configuration expression<string>, optional

A key to identify an OAuth 2.0 session. The key can be any character string.

To share the same OAuth 2.O session when a user accesses different applications protected by IG, use the same key in each filter.

Default: The complete client endpoint URI. AuthorizationCodeOAuth2ClientFilters do not share OAuth 2.O sessions.

"secretsProvider": SecretsProvider reference, required if discoverySecretId is used

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

CapturedUserPasswordFilter

Makes an AM password available to IG in the following steps:

  • Checks for the presence of the SessionInfoContext context, at ${contexts.amSession}.

    • If the context is not present, or if sunIdentityUserPassword is null, the CapturedUserPasswordFilter collects session info and properties from AM.

    • If the context is present and sunIdentityUserPassword is not null, the CapturedUserPasswordFilter uses that value for the password.

  • The CapturedUserPasswordFilter decrypts the password and stores it in the CapturedUserPasswordContext, at ${contexts.capturedPassword}.

Usage

{
  "name": string,
   "type": "CapturedUserPasswordFilter",
   "config": {
     "amService": AmService reference,
     "keySecretId": configuration expression<secret-id>,
     "keyType": configuration expression<string>,
     "secretsProvider": SecretsProvider reference,
     "ssoToken": runtime expression<string>,
     "key": configuration expression<string> //deprecated
   }
}

Properties

"amService": AmService reference, required

The AmService heap object to use for the password. See also, AmService.

"keySecretId": configuration expression<secret-id>, required

The secret ID for the key required decrypt the AM password.

This secret ID must point to a CryptoKey` that matches the algorithm in "keyType".

Although secrets of type GenericSecret are accepted, their usage is deprecated in this filter. For more information, refer to the Deprecated section of the Release Notes.
"keyType": configuration expression<enumeration>, required

Algorithm to decrypt the AM password. Use one of the following values:

  • AES AES for JWT-based AES_128_CBC_HMAC_SHA_256 encryption. For more information, refer to AES_128_CBC_HMAC_SHA_256 in the IETF JSON Web Algorithms.

  • DES for DES/ECB/NoPadding

    This value is deprecated, and considered unsecure. For more information, refer to the Deprecated section of the Release Notes.
"secretsProvider": SecretsProvider reference, optional

The SecretsProvider object to query for the shared secret that is used to decrypt the user password.

For more information, refer to SecretsProvider.

"ssoToken": runtime expression<string>, required

Location of the AM SSO token.

Default: ${request.cookiesAmService-ssoTokenHeader'][0].value}, where AmService-ssoTokenHeader is the name of the header or cookie where the AmService expects to find SSO tokens.

"key": configuration expression<string>, required
This property is deprecated and is not considered secure. Use keySecretId instead. For more information, refer to the Deprecated section of the Release Notes.

Base64 encoded key value to decrypt the AM password.

Examples

The following example route is used to get login credentials from AM in Authenticate with credentials from AM.

{
  "name": "04-replay",
  "condition": "${find(request.uri.path, '^/replay')}",
  "heap": [
    {
      "name": "SystemAndEnvSecretStore-1",
      "type": "SystemAndEnvSecretStore",
      "config": {
        "mappings": [
          {
            "secretId": "aes.key",
            "format": {
              "type": "SecretKeyPropertyFormat",
              "config": {
                "format": "BASE64",
                "algorithm": "AES"
              }
            }
          }
        ]
      }
    },
    {
      "name": "AmService-1",
      "type": "AmService",
      "config": {
        "agent": {
          "username": "ig_agent",
          "passwordSecretId": "agent.secret.id"
        },
        "secretsProvider": "SystemAndEnvSecretStore-1",
        "url": "http://am.example.com:8088/openam/"
      }
    },
    {
      "name": "CapturedUserPasswordFilter",
      "type": "CapturedUserPasswordFilter",
      "config": {
        "ssoToken": "${contexts.ssoToken.value}",
        "keySecretId": "aes.key",
        "keyType": "AES",
        "secretsProvider": "SystemAndEnvSecretStore-1",
        "amService": "AmService-1"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "SingleSignOnFilter",
          "config": {
            "amService": "AmService-1"
          }
        },
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${true}",
            "credentials": "CapturedUserPasswordFilter",
            "request": {
              "method": "POST",
              "uri": "http://app.example.com:8081/login",
              "form": {
                "username": [
                  "${contexts.ssoToken.info.uid}"
                ],
                "password": [
                  "${contexts.capturedPassword.value}"
                ]
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

CertificateThumbprintFilter

Extracts a Java certificate from a trusted header or from a TLS connection, computes the SHA-256 thumbprint of that certificate, and makes the thumbprint available for the ConfirmationKeyVerifierAccessTokenResolver. Use this filter to enable verification of certificate-bound access tokens.

CertificateThumbprintFilter computes and makes available the SHA-256 thumbprint of a client certificate as follows:

  • Evaluates a runtime expression and yields a java.security.cert.Certificate

  • Hashes the certificate using SHA-256

  • Base64url-encodes the result

  • Stores the result in the contexts chain

The runtime expression can access or build a client certificate from any information present at runtime, such as a PEM in a header, or a pre-built certificate.

Use CertificateThumbprintFilter with ConfirmationKeyVerifierAccessTokenResolver when the IG instance is behind the TLS termination point, for example, when IG is running behind a load balancer or other ingress point.

Usage

{
  "name": string,
  "type": "CertificateThumbprintFilter",
  "config": {
    "certificate": runtime expression<certificate>,
    "failureHandler": Handler reference,
  }
}

Properties

"certificate": runtime expression<certificate>, required

An EL expression which, when evaluated, yields an instance of a java.security.cert.Certificate.

Use the following Functions in the expression to define hash, decoding, and certificate format:

  • digestSha256, to calculate the SHA-256 hash of the certificate.

  • decodeBase64url, to decode an incoming base64url-encoded string.

  • pemCertificate, to convert a PEM representation string into a certificate.

See Examples.

"failureHandler": Handler reference, optional

Handler to treat the request on failure.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

Examples

The following example uses the certificate associated with the incoming HTTP connection:

{
  "name": "CertificateThumbprintFilter-1",
  "type": "CertificateThumbprintFilter",
  "config": {
    "certificate": "${contexts.client.certificates[0]}"
  }
}

The following example is adapted for a deployment with NGINX as the TLS termination, where NGINX fronts IG. NGINX provides the client certificate associated with its own incoming connection in the x-ssl-client-cert header. The certificate is encoded as PEM, and then url-encoded:

{
  "name": "CertificateThumbprintFilter-2",
  "type": "CertificateThumbprintFilter",
  "config": {
    "certificate": "${pemCertificate(urlDecode(request.headers['x-ssl-client-cert'][0]))}"
  }
}

CircuitBreakerFilter

Monitors failures. When the number of failures reaches a configured failure threshold, the circuit breaker trips, and the circuit is considered open. Calls to downstream filters are stopped, and a runtime exception is returned.

After a configured delay, the circuit breaker is reset, and is the circuit considered closed. Calls to downstream filters are restored.

Usage

{
  "name": string,
  "type": "CircuitBreakerFilter",
  "config": {
    "maxFailures":  configuration expression<integer>,
    "openDuration": configuration expression<duration>,
    "openHandler": Handler reference,
    "slidingCounter": object,
    "executor":  ScheduledExecutorService reference
  }
}

Properties

"maxFailures": configuration expression<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.

"openDuration": configuration expression<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, 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, 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.
{
  "slidingCounter":  {
    "size": configuration expression<number>
  }
}
"size": configuration expression<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, optional

A ScheduledExecutorService to schedule closure of the circuit after the duration given by openDuration.

Default: The default ScheduledExecutorService in the heap

Example

In the following example, the circuit breaker opens after 11 failures in the previous 100 requests, throwing a runtime exception with a "circuit-breaker open" message. The default ScheduledExecutorService in the heap closes the circuit-breaker after 10 seconds.

{
  "type": "CircuitBreakerFilter",
  "config": {
    "maxFailures": 10,
    "openDuration": "10 seconds",
    "openHandler": {
      "type": "StaticResponseHandler",
      "config": {
        "status": 500,
        "headers": {
          "Content-Type": [ "text/plain" ]
        },
        "entity": "Too many failures; circuit opened to protect downstream services."
      }
    },
    "slidingCounter": {
      "size": 100
    }
  }
}

ClientCredentialsOAuth2ClientFilter

Authenticates OAuth 2.0 clients by using the client’s OAuth 2.0 credentials to obtain an access token from an Authorization Server, and injecting the access token into the inbound request as a Bearer Authorization header. The access token is valid for the configured scopes.

The ClientCredentialsOAuth2ClientFilter obtains the client’s access token by using the client_credentials grant type. Client authentication is provided by the endpointHandler property, which uses a client authentication filter, such as ClientSecretBasicAuthenticationFilter. The filter refreshes the access token as required.

Use the ClientCredentialsOAuth2ClientFilter in a service-to-service context, where services need to access resources protected by OAuth 2.0.

Usage

{
  "name": string,
  "type": "ClientCredentialsOAuth2ClientFilter",
  "config": {
    "secretsProvider": SecretsProvider reference,
    "tokenEndpoint": configuration expression<url>,
    "scopes": [ configuration expression<string>, ... ],
    "endpointHandler": Handler reference,
    "clientId": configuration expression<sting>, //deprecated
    "clientSecretId": configuration expression<secret-id>, //deprecated
    "handler": Handler reference //deprecated
  }
}

Properties

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

"tokenEndpoint": configuration expression<url>, required

The URL to the Authorization Server’s OAuth 2.0 token endpoint.

"scopes": array of configuration expression<strings>, optional

Array of scope strings to request from the Authorization Server.

Default: Empty, request no scopes.

"endpointHandler": Handler reference, optional

The Handler to exchange tokens on the authorization endpoint.

Configure this property as a Chain, using one of the following client authentication filters:

{
  "name": "myHandler",
  "type": "Chain",
  "config": {
    "handler": "ForgeRockClientHandler",
    "filters": [
      {
        "type": "ClientSecretBasicAuthenticationFilter",
        "config": {
          "clientId": "myConfidentialClient",
          "clientSecretId": "my.client.secret.id",
          "secretsProvider" : "mySystemAndEnvSecretStore",
        }
      }
    ]
  }
}

Default: ForgeRockClientHandler

"clientId": configuration expression<string>, required
This property is deprecated. Use endpointHandler instead. For more information, refer to the Deprecated section of the Release Notes.

The ID of the OAuth 2.0 client registered with the Authorization Server.

If you use the deprecated properties, provide clientId, clientSecretId to obtain the client secret, which authenticates using the client_secret_basic method.

"clientSecretId": configuration expression<secret-id>, required
This property is deprecated. Use endpointHandler instead. For more information, refer to the Deprecated section of the Release Notes.

The ID to use when querying the secretsProvider for the client secret.

This secret ID must point to a GenericSecret.

"handler": Handler reference or inline Handler declaration, optional
This property is deprecated. Use endpointHandler instead. For more information, refer to the Deprecated section of the Release Notes.

The Handler to use to access the Authorization Server’s OAuth 2.0 token endpoint. Provide either the name of a handler object defined in the heap or specify a handler object inline.

Default: ClientHandler

Examples

For an example, refer to Using OAuth 2.0 client credentials.

ClientSecretBasicAuthenticationFilter

Supports client authentication with the method client_secret_basic. Clients that have received a client_secret value from the Authorization Server authenticate through the HTTP basic access authentication scheme, as in the following example:

POST /oauth2/token HTTP/1.1
Host: as.example.com
Authorization: Basic ....
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=...

Use this filter with an endpoint Handler that requires client_secret_basic authentication. For example, endpointHandler in the OAuth2TokenExchangeFilter or ClientCredentialsOAuth2ClientFilter.

Usage

{
  "name": string,
  "type": "ClientSecretBasicAuthenticationFilter",
  "config": {
    "clientId": configuration expression<string>,
    "clientSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference
  }
}

Configuration

"clientId": configuration expression<string>, required

The OAuth 2.0 client ID to use for authentication.

"clientSecretId": configuration expression<secret-id>, required

The OAuth 2.0 client secret to use for authentication.

This secret ID must point to a GenericSecret.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

Example

{
  "name": "ExchangeHandler",
  "type": "Chain",
  "config": {
    "handler": "ForgeRockClientHandler",
    "filters": [
      {
        "type": "ClientSecretBasicAuthenticationFilter",
        "config": {
          "clientId": "serviceConfidentialClient",
          "clientSecretId": "client.secret.id",
          "secretsProvider" : "SystemAndEnvSecretStore-1"
        }
      }
    ]
  }
}

ClientSecretPostAuthenticationFilter

Supports client authentication with the method client_secret_post. Clients that have received a client_secret value from the Authorization Server authenticate by including the client credentials in the request body, as in the following example:

POST /oauth2/token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&;
client_id=...&
client_secret=...&
code=...

Use this filter with an endpoint Handler that requires client_secret_post authentication. For example, endpointHandler in the OAuth2TokenExchangeFilter or ClientCredentialsOAuth2ClientFilter.

Usage

{
  "name": string,
  "type": "ClientSecretPostAuthenticationFilter",
  "config": {
    "clientId": configuration expression<string>,
    "clientSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference
  }
}

Configuration

"clientId": configuration expression<string>, required

The OAuth 2.0 client ID to use for authentication.

"clientSecretId": configuration expression<secret-id>, required

The OAuth 2.0 client secret to use for authentication.

This secret ID must point to a GenericSecret.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

ConditionalFilter

Verifies that a specified condition is met. If the condition is met, the request is dispatched to a delegate Filter. Otherwise, the delegate Filter is skipped.

Use ConditionalFilter to easily use or skip a Filter depending on whether a condition is met. To easily use or skip a set of Filters, use a ChainOfFilters as the delegate Filter and define a set of Filters. For information, refer to ChainOfFilters.

Usage

{
    "name": string,
    "type": "ConditionalFilter",
    "config": {
        "condition": runtime expression<boolean>,
        "delegate": Filter reference
   }
}

Properties

"condition": runtime expression<boolean>, required

If the expression evaluates to true, the request is dispatched to the delegate Filter. Otherwise the delegate Filter is skipped.

"delegate": Filter reference, required

Filter to treat the request when the condition expression evaluates as true.

See also Filters.

Example

The following example tests whether a request finishes with .js or .jpg:

{
  "type": "Chain",
  "config": {
    "filters": [{
      "type": "ConditionalFilter",
      "config": {
        "condition": "${not (find(request.uri.path, '.js$') or find(request.uri.path, '.jpg$'))}",
        "delegate": "mySingleSignOnFilter"
      }
    }],
    "handler": "ReverseProxyHandler"
  }
}

If the request is to access a .js file or .jpg file, it skips the delegate SingleSignOnFilter filter declared in the heap, and passes straight to the ReverseProxyHandler.

If the request is to access another type of resource, it must pass through the delegate SingleSignOnFilter for authentication with AM before it can pass to the ReverseProxyHandler.

ConditionEnforcementFilter

Verifies that a specified condition is met. If the condition is met, the request continues to be executed. Otherwise, the request is referred to a failure handler, or IG returns 403 Forbidden and the request is stopped.

Usage

{
    "name": string,
    "type": "ConditionEnforcementFilter",
    "config": {
        "condition": runtime expression<boolean>,
        "failureHandler": Handler reference
    }
}

Properties

"condition": runtime expression<boolean>, required

If the expression evaluates to true, the request continues to be executed.

"failureHandler": Handler reference, optional

Handler to treat the request if the condition expression evaluates as false.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

Example

The following example tests whether a request contains a session username. If it does, the request continues to be executed. Otherwise, the request is dispatched to the ConditionFailedHandler failure handler.

{
    "name": "UsernameEnforcementFilter",
    "type": "ConditionEnforcementFilter",
    "config": {
        "condition": "${not empty (session.username)}",
        "failureHandler": "ConditionFailedHandler"
    }
}

ChainOfFilters

Dispatches a request to an ordered list of filters. Use this filter to assemble a list of filters into a single filter that you can then use in different places in the configuration.

A ChainOfFilters can be placed in a configuration anywhere that a filter can be placed.

Unlike Chain, ChainOfFilters does not finish by dispatching the request to a handler. For more information, refer to Chain.

Usage

{
    "name": string,
    "type": "ChainOfFilters",
    "config": {
        "filters": [ Filter reference, ... ]
    }
}

Properties

"filters": array of Filter references, 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.

Example

{
    "name": "MyChainOfFilters",
    "type": "ChainOfFilters",
    "config": {
        "filters": [ "Filter1", "Filter2" ]
   }
}

CookieFilter

Manages, suppresses, and relays cookies for stateful sessions. This filter is not currently compatible with stateless sessions.

Usage

{
     "name": string,
     "type": "CookieFilter",
     "config": {
         "managed": [ configuration expression<string>, ... ],
         "suppressed": [ configuration expression<string>, ... ],
         "relayed": [ configuration expression<string>, ... ],
         "defaultAction": configuration expression<enumeration>
     }
}

Properties

"managed": array of configuration expression<strings>, optional

A list of the names of cookies to be managed.

IG stores cookies from the protected application in the session and manages them as follows:

  • Requests with a Cookie header: IG removes managed cookies so that protected applications cannot see them.

  • Responses with a Set-Cookie header: IG removes managed cookies and keeps a copy of them. IG then adds the managed cookies in a Cookie header to future requests that traverse the CookieFilter.

"suppressed": array of configuration expression<strings>, optional

A list of the names of cookies to be suppressed.

IG removes cookies from the request and response. Use this option to hide domain cookies, such as the AM session cookie, that are used by IG but are not usually used by protected applications.

"relayed": array of configuration expression<strings>, optional

A list of the names of cookies to be relayed.

IG transmits cookies freely from the user agent to the remote server, and vice versa.

"defaultAction": configuration expression<enumeration>, optional

Action to perform for cookies that do not appear in one of the above lists. Set to MANAGE, SUPPRESS, or RELAY.

If a cookie appears in more than one of the above lists, it is treated in the following order of precedence: managed, suppressed, relayed. For example, if a cookie is in both the managed and relayed lists, the cookie is managed.

Default: "MANAGE".

CorsFilter

Configures policies for cross-origin resource sharing (CORS), to allow cross-domain requests from user agents.

Usage

{
   "name": string,
   "type": "CorsFilter",
   "config": {
     "policies": [ object, ... ],
     "failureHandler": Handler reference
   }
}

Properties

"policies": array of objects, required

One or more policies to apply to the request. A policy is selected when the origin of the request matches the accepted origins of the policy.

When multiple policies are declared, they are tried in the order that they are declared, and the first matching policy is selected.

{
  "acceptedOrigins": [ configuration expression<url>, ... ] or "*",
  "acceptedMethods": [ configuration expression<string>, ... ] or "*",
  "acceptedHeaders": [ configuration expression<string>, ... ] or "*",
  "exposedHeaders": [ configuration expression<string>, ... ],
  "maxAge": configuration expression<duration>,
  "allowCredentials": configuration expression<boolean>,
  "origins": [ configuration expression<url>, ... ] or "*" //deprecated
}
"acceptedOrigins": array of configuration expression<urls> or "*", required

A comma-separated list of origins, to match the origin of the CORS request. Alternatively, use * to allow requests from any URL.

If the request origin is not in the list of accepted origins, the failure handler is invoked or an HTTP 403 Forbidden is returned, and the request stops being executed.

Origins are URLs with a scheme, hostname, and optionally a port number, for example, http://www.example.com. If a port number is not defined, origins with no port number or with the default port number (80 for HTTP, 443 for HTTPS) are accepted.

Examples:

{
  "acceptedOrigins": [
    "http://www.example.com",
    "https://example.org:8433"
  ]
}
{
  "acceptedOrigins": "*"
}
"acceptedMethods": array of configuration expression<strings> or "*", optional

A comma-separated list of case-sensitive HTTP method names that are allowed when making CORS requests. Alternatively, use * to allow requests with any method.

In preflight requests, browsers use the Access-Control-Request-Method header to let the server know which HTTP method might be used in the actual request.

  • If all requested methods are allowed, the requested methods are returned in the preflight response, in the Access-Control-Allow-Methods header.

  • If any requested method is not allowed, the Access-Control-Allow-Methods header is omitted. The failure handler is not invoked, but the user agent interprets the preflight response as a CORS failure.

Examples:

{
  "acceptedMethods": [
    "GET",
    "POST",
    "PUT",
    "MyCustomMethod"
  ]
}
{
  "acceptedMethods": "*"
}

Default: All methods are rejected.

"acceptedHeaders": array of configuration expression<strings> or "*", optional

A comma-separated list of case-insensitive request header names that are allowed when making CORS requests. Alternatively, use * to allow requests with any header.

In preflight requests, browsers use the Access-Control-Request-Headers header to let the server know which HTTP headers might be used in the actual request.

  • If all requested headers are allowed, the requested headers are returned in the preflight response, in the Access-Control-Allow-Headers header.

  • If any requested header is not allowed, the Access-Control-Allow-Headers header is omitted. The failure handler is not invoked, but the user agent interprets the preflight response as a CORS failure.

Examples:

{
  "acceptedHeaders": [
    "iPlanetDirectoryPro",
    "X-OpenAM-Username",
    "X-OpenAM-Password",
    "Accept-API-Version",
    "Content-Type",
    "If-Match",
    "If-None-Match"
  ]
}
{
  "acceptedHeaders": "*"
}

Default: All requested headers are rejected.

"exposedHeaders": list of configuration expression<string>, optional

A comma-separated list of case-insensitive response header names that are returned in the Access-Control-Expose-Headers header.

Only headers in this list, safe headers, and the following simple response headers are exposed to frontend JavaScript code:

  • Cache-Control

  • Content-Language

  • Expires

  • Last-Modified

  • Pragma

  • Content-Type

Example:

{
  "exposedHeaders": [
    "Access-Control-Allow-Origin",
    "Access-Control-Allow-Credentials",
    "Set-Cookie"
  ]
}

Default: No headers are exposed.

"maxAge": configuration expression<duration>, optional

The maximum duration for which a browser is allowed to cache a preflight response. The value is included in the Access-Control-Max-Age header of preflight responses.

When this maxAge is greater than the browser’s maximum internal value, the browser value takes precedence.

Default: 5 seconds

"allowCredentials": configuration expression<boolean>, optional

A flag to allow requests that use credentials, such as cookies, authorization headers, or TLS client certificates.

Set to true to set the Access-Control-Allow-Credentials header to true, and allow browsers to expose the response to frontend JavaScript code.

Default: False

"origins": list of configuration expression<url> or "*", required
This property is deprecated; use acceptedOrigins instead. For more information, refer to the Deprecated section of the Release Notes.

A comma-separated list of origins, to match the origin of the CORS request. Alternatively, use * to allow requests from any URL.

Origins are URLs with a scheme, hostname, and optionally a port number, for example, http://www.example.com. If a port number is not defined, origins with no port number or with the default port number (80 for HTTP, 443 for HTTPS) are accepted.

"failureHandler": Handler reference, optional

Handler invoked during the preflight request, when the request origin does not match any of the acceptedOrigins defined in policies.

The failure handler is not invoked when requested headers or requested methods are not allowed.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

CrossDomainSingleSignOnFilter

When IG and AM are running in the same domain, the SingleSignOnFilter can be used for SSO. When IG and AM are running in different domains, AM cookies aren’t visible to IG because of the same-origin policy. The CrossDomainSingleSignOnFilter provides a mechanism to push tokens issued by AM to IG running in a different domain.

When this filter processes a request, it injects the CDSSO token, the session user ID, and the full claims set into the CdSsoContext. If an error occurs during authentication, information is captured in the CdSsoFailureContext.

For an example of how to configure CDSSO and information about the CDSSO data flow, refer to Cross-domain single sign-on.

WebSocket notifications for sessions

When WebSocket notifications are set up for sessions, IG receives a notification from AM when a user logs out of AM, or when the AM session is modified, closed, or times out. IG then evicts entries that are related to the event from the sessionCache.

For information about setting up WebSocket notifications, using them to clear the session cache, and including them in the server logs, refer to WebSocket notifications.

Usage

{
  "name": string,
  "type": "CrossDomainSingleSignOnFilter",
  "config": {
    "amService": AmService reference,
    "redirectEndpoint": configuration expression<url>,
    "authenticationService": configuration expression<string>,
    "authCookie": object,
    "redirectionMarker": object,
    "defaultLogoutLandingPage": configuration expression<url>,
    "logoutExpression": runtime expression<boolean>,
    "failureHandler": Handler reference,
    "verificationSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference
  }
}

Properties

"amService": AmService reference, required

The AmService heap object to use. See AmService.

"redirectEndpoint": configuration expression<url>, required

The URI to which AM redirects the browser with the authentication token or an authentication error. The filter checks that the authentication was initiated by IG.

Configure this URI to be the same as that in AM.

To make sure the redirect is routed back to the CrossDomainSingleSignOnFilter, include the endpoint in the route condition in one of the following ways:

  • As a sub-path of the condition path.

    For example, use the following route condition with the following endpoint:

    "condition": "${find(request.uri.path, '^/home/cdsso')}"
    "redirectEndpoint": "/home/cdsso/callback"
  • To match the route condition.

    For example, use the following route condition with the following endpoint:

    "condition": "${find(request.uri.path, '^/home/cdsso')}"
    "redirectEndpoint": "/home/cdsso"

    With this route condition, all POST requests on the condition path are treated as AM CDSSO callbacks. Any POST requests that aren’t the result of an AM CDSSO callback will fail.

  • As a specific path that is not related to the condition path.

    To make sure the redirect is routed back to this filter, include the redirectEndpoint as a path in the filter condition.

    For example, use the following route condition with the following endpoint:

    "condition": "${find(request.uri.path, '^/home/cdsso/redirect') || find(request.uri.path, '^/ig/cdssoRedirectUri')}"
    "redirectEndpoint": "/ig/cdssoRedirectUri"
"authenticationService": configuration expression<string>,optional

The name of an AM authentication tree or authentication chain to use for authentication.

Use only authentication trees with ForgeRock Identity Cloud. Authentication modules and chains are not supported.

Default: AM’s default authentication tree.

For more information about authentication trees and chains, refer to Authentication nodes and trees and Authentication modules and chains in AM’s Authentication and SSO guide.

"authCookie": object, optional

The configuration of the cookie used to store the authentication.

{
  "name": configuration expression<string>,
  "domain": configuration expression<string>,
  "httpOnly": configuration expression<boolean>,
  "path": configuration expression<string>,
  "sameSite": configuration expression<enumeration>,
  "secure": configuration expression<boolean>
}
"name": configuration expression<string>, optional

Name of the cookie containing the authentication token from AM.

For security, change the default name of cookies.

Default: ig-token-cookie

"domain": configuration expression<string>, optional

Domain to which the cookie applies.

Set a domain only if the user agent is able to re-emit cookies on that domain on its next hop. For example, to re-emit a cookie on the domain example.com, the user agent must be able to access that domain on its next hop.

Default: The fully qualified hostname of the user agent’s next hop.

"httpOnly": configuration expression<boolean>, optional

Flag to mitigate the risk of client-side scripts accessing protected cookies.

Default: true

"path": configuration expression<string>, optional

Path protected by this authentication.

Set a path only if the user agent is able to re-emit cookies on the path. For example, to re-emit a cookie on the path /home/cdsso, the user agent must be able to access that path on its next hop.

Default: The path of the request that got the Set-Cookie in its response.

"sameSite": configuration expression<enumeration>, optional

Options to manage the circumstances in which a cookie is sent to the server. Use one of the following values to reduce the risk of CSRF attacks:

  • STRICT: Send the cookie only if the request was initiated from the cookie domain. Not case-sensitive.

    Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • LAX: Send the cookie only with GET requests in a first-party context, where the URL in the address bar matches the cookie domain. Not case-sensitive.

    Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • NONE: Send the cookie whenever a request is made to the cookie domain. Not case-sensitive.

    With this setting, consider setting secure to true to prevent browsers from rejecting the cookie. For more information, refer to SameSite cookies.

Default: LAX

For CDSSO, set "sameSite":"none" and "secure":"true". For security reasons, many browsers require the connection used by the browser to be secure (HTTPS) for "sameSite":"none". Therefore, if the connection used by the browser is not secure (HTTP), the browser might not supply cookies with "sameSite":"none". For more information, refer to Authenticate with CDSSO.
"secure": configuration expression<boolean>, optional

Flag to limit the scope of the cookie to secure channels.

Set this flag only if the user agent is able to re-emit cookies over HTTPS on its next hop. For example, to re-emit a cookie with the secure flag, the user agent must be connected to its next hop by HTTPS.

Default: false

"redirectionMarker": configuration expression<object>, optional

A redirect marker for the CDSSO flow. If the marker is present in the CDSSO flow, the request isn’t redirected for authentication.

This feature is on by default to prevent redirect loops when the session cookie isn’t present in the CDSSO flow. The cookie can be absent from the flow if it doesn’t include IG’s domain.

"redirectionMarker": {
  "enabled": configuration expression<boolean>,
  "name": configuration expression<string>
}
"enabled": configuration expression<boolean>, optional
  • true: When the session is empty or invalid, IG checks the request goto query parameter for the presence of the redirection marker:

    • If the redirection marker is present, IG fails the request.

    • If the redirection marker isn’t present, IG redirects the user agent for login.

  • false: IG never checks the request goto query parameter for the presence of a redirection marker.

Default: true

"name": configuration expression<string>, optional

The name of the redirection marker query parameter to use when enabled is true.

Default: _ig

"defaultLogoutLandingPage": configuration expression<url>, optional

The URL to which a request is redirected if logoutExpression is evaluated as true.

If this property is not an absolute URL, the request is redirected to the IG domain name.

This parameter is effective only when logoutExpression is specified.

Default: None, processing continues.

"logoutExpression": runtime expression<boolean>, optional

A flag to indicate whether a request initiates logout processing before reaching the protected application.

  • false: The request does not initiate logout processing:

    • If a valid AM session is found, the request is forwarded to the protected application.

    • If a valid AM session is not found, the request triggers login.

  • true: The request initiates logout processing:

    • If a valid AM session is found, the session is revoked and the request is forwarded as follows:

      • If defaultLogoutLandingPage is defined, the request is forwarded to the specified logout page.

      • If defaultLogoutLandingPage is not defined, the request is forwarded to the protected application without any other validation.

    • If a valid session is not found, the request is forwarded to the protected application without any other validation.

To prevent unwanted access to the protected application, use logoutExpression with extreme caution as follows:

  • Define a defaultLogoutLandingPage.

  • If you don’t define a defaultLogoutLandingPage, specify logoutExpression to resolve to true only for requests that target dedicated logout pages of the protected application.

Consider the following examples when a defaultLogoutLandingPage is not configured:

  • This expression resolves to true only for requests with /app/logout in their path:

    "logoutExpression": ${startsWith(request.uri.rawPath, '/app/logout')}

    When a request matches the expression, the AM session is revoked and the request is forwarded to the /app/logout page.

  • This expression resolves to true for all requests that contain logOff=true in their query parameters:

    "logoutExpression": ${find(request.uri.query, 'logOff=true')}

    When a request matches the expression, the AM session is revoked and the request is forwarded to the protected application without any other validation. In this example, an attacker can bypass IG’s security mechanisms by simply adding ?logOff=true to a request.

Default: ${false}

"failureHandler": Handler reference, optional

Handler to treat the request if an error occurs during authentication.

If an error occurs during authentication, a CdSsoFailureContext is populated with details of the error and any associated Throwable. This is available to the failure handler so that it can respond appropriately.

Be aware that the failure handler does not itself play a role in user authentication. It is only invoked if there is a problem that prevents user authentication from taking place.

A number of circumstances may cause the failure handler to be invoked, including:

  • The redirect endpoint is invalid.

  • The redirect endpoint is invoked without a valid CDSSO token.

  • The redirect endpoint is invoked inappropriately.

  • An error was reported by AM during authentication.

If no failure handler is configured, the default failure handler is used.

See also Handlers.

Default: HTTP 200 OK. The response entity contains details of the error.

"verificationSecretId": configuration expression<secret-id>, optional

The secret ID for the secret to verify the signature of AM session tokens. verificationSecretId must point to a CryptoKey.

Default: IG discovers and uses the AM JWK set to verify the signature of AM session tokens. If the JWK set isn’t available, IG does not verify the tokens.

For information about how IG verifies signatures, refer to Validate the signature of signed tokens. For information about how secret stores resolve named secrets, refer to Secrets.

"secretsProvider": SecretsProvider reference, optional

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

Example

For an example that uses the CrossDomainSingleSignOnFilter, refer to Cross-domain single sign-on (CDSSO).

CryptoHeaderFilter (deprecated)

This object is deprecated and is not considered secure. For more information, refer to the Deprecated section of the Release Notes.

The CryptoHeaderFilter conveys encrypted data between hosts by using insecure ECB mode ciphers. Consider using a JwtBuilderFilter with a HeaderFilter for a more secure way to pass identity or other runtime information to the protected application.

Encrypts or decrypts headers in a request or response, using a symmetric or asymmetric key. CryptoHeaderFilter supports key rotation.

Usage

{
  "name": string,
  "type": "CryptoHeaderFilter",
  "config": {
    "messageType": configuration expression<enumeration>,
    "operation": configuration expression<enumeration>,
    "keySecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "algorithm": configuration expression<string>,
    "charset": configuration expression<string>,
    "headers": [ configuration expression<string>, ... ]
  }
}

Properties

"messageType": configuration expression<enumeration>, required

The type of message whose headers to encrypt or decrypt.

Must be one of: "REQUEST", "RESPONSE".

"operation": configuration expression<enumeration>, required

Indication of whether to encrypt or decrypt.

Must be one of: "ENCRYPT", "DECRYPT".

"keySecretId": configuration expression<secret-id>, required

The secret ID of the key to encrypt or decrypt the headers.

This secret ID must point to a CryptoKey.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider object to query for the key to encrypt or decrypt the headers. For more information, refer to SecretsProvider.

"algorithm": configuration expression<string>, optional

The algorithm name, mode, and padding used for encryption and decryption.

CryptoHeaderFilter does not support EC-based encryption. Use other cipher algorithm values given in Java Security Standard Algorithm Names.

Default: AES/ECB/PKCS5Padding

"charset": configuration expression<string>, optional

The name of the charset used to encrypt or decrypt values, as described in Class Charset.

Default: UTF-8

"headers": array of configuration expression<strings>, optional

The names of header fields to encrypt or decrypt.

Default: Empty

Example

{
  "name": "DecryptReplayPasswordFilter",
  "type": "CryptoHeaderFilter",
  "config": {
    "messageType": "REQUEST",
    "operation": "DECRYPT",
    "keySecretId": "decryption.secret.id",
    "secretsProvider": "KeyStoreSecretStore-1",
    "algorithm": "AES/ECB/PKCS5Padding",
    "headers": [ "replaypassword" ]
  }
}

CsrfFilter

Prevent Cross Site Request Forgery (CSRF) attacks when using cookie-based authentication, as follows:

  • When a session is created or updated for a client, generate a CSRF token as a hash of the session cookie.

  • Send the token in a response header to the client, and require the client to provide that header in subsequent requests.

  • In subsequent requests, compare the provided token to the generated token.

  • If the token is not provided or can’t be validated, reject the request and return a valid CSRF token transparently in the response header.

    Rogue websites that attempt CSRF attacks operate in a different website domain to the targeted website. Because of same-origin policy, rogue websites can’t access a response from the targeted website, and cannot, therefore, access the CSRF token.

Usage

{
  "name": string,
  "type": "CsrfFilter",
  "config": {
    "cookieName": configuration expression<string>,
    "headerName": configuration expression<string>,
    "excludeSafeMethods": configuration expression<boolean>,
    "failureHandler": Handler reference
  }
}

Properties

"cookieName": configuration expression<string>, required

The name of the HTTP session cookie used to store the session ID. For example, use the following cookie names for the following processes:

"headerName": configuration expression<string>, optional

The name of the header that carries the CSRF token. The same header is used to create and verify the token.

Default: X-CSRF-Token

"excludeSafeMethods": configuration expression<boolean>, optional

Whether to exclude GET, HEAD, and OPTION methods from CSRF testing. In most cases, these methods are assumed as safe from CSRF.

Default: true

"failureHandler": Handler reference, optional

Handler to treat the request if the CSRF the token is not provided or can’t be validated. Provide an inline handler declaration, or the name of a handler object defined in the heap.

Although IG returns the CSRF token transparently in the response header, this handler cannot access the CSRF token.

Default: Handler that generates HTTP 403 Forbidden.

Example

For an example of how to harden protection against CSRF attacks, see CSRF protection.

{
  "name": "CsrfFilter-1",
  "type": "CsrfFilter",
  "config": {
    "cookieName": "openig-jwt-session",
    "headerName": "X-CSRF-Token",
    "excludeSafeMethods": true
  }
}

DataPreservationFilter

The DataPreservationFilter triggers POST data preservation when an unauthenticated client posts HTML form data to a protected resource.

When an authentication redirect is triggered, the filter stores the data in the HTTP session, and redirects the client for authentication. After authentication, the filter generates an empty self-submitting form POST to emulate the original POST. It then replays the stored data into the request before passing it along the chain.

The data can be any POST content, such as HTML form data or a file upload.

For more information, refer to POST data preservation.

Usage

{
  "type": "DataPreservationFilter",
  "config": {
    "noJavaScriptMessage": configuration expression<string>,
    "maxContentLength": configuration expression<positive integer>,
    "lifetime": configuration expression<duration>
  }
}

Properties

"noJavaScriptMessage": configuration expression<string>, optional

JavaScript is used to replay the preserved data from the original POST that triggered the login redirect. This property configures a message to display if the user-agent does not support JavaScript.

Default: Javascript is disabled in your browser, click on this button to replay the preserved original request

"maxContentLength": configuration expression<positive integer>, optional

The maximum number of bytes of POST data the filter can preserve. The size is taken from the Content-Length header.

Default: 4096

"lifetime": configuration expression<duration>, optional

The maximum time that the filter can store POST data in an HTTP session.

The filter deletes stored POST data when the following events occur:

  • The lifetime has expired.

  • The POST data preservation process from an earlier request hasn’t completed.

  • A new request arrives that triggers a new POST data preservation process.

Stored POST data is also deleted when the session expires.

Default: 5 minutes

Example

For an example of use, refer to POST data preservation.

DateHeaderFilter

Inserts the server date in an HTTP Date header on the response, if the Date header is not present.

Usage

{
  "type": "DateHeaderFilter"
}

Properties

There are no configuration properties for this filter.

Example

The following example includes a DateHeaderFilter in a chain:

{
  "condition": "...",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [{
          ...
        },
        {
          "type": "DateHeaderFilter"
        }
      ],
      "handler": {
        "name": "StaticResponseHandler-1",
        ...
      }
    }
  }
}

More information

For information about Date format, see RFC 7231 - Date.

This filter is also available to support Financial-Grade API, for information, see Financial-grade API Security Profile 1.0 - Part 1: Baseline

EncryptedPrivateKeyJwtClientAuthenticationFilter

Supports client authentication with the private_key_jwt client-assertion, using a signed and encrypted JWT.

Clients send a signed and encrypted JWT to the Authorization Server. IG builds, signs and encrypts the JWT, and prepares the request as in the following example:

POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=...&
client_id=<clientregistration_id>&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=PHNhbWxwOl ... ZT

Use this filter with an endpoint Handler that requires authentication with the private_key_jwt client-assertion, using an encrypted JWT. For example, the endpointHandler handler in the OAuth2TokenExchangeFilter.

Usage

{
  "name": string,
  "type": "EncryptedPrivateKeyJwtClientAuthenticationFilter",
  "config": {
    "encryptionAlgorithm": configuration expression<enumeration>,
    "encryptionMethod": configuration expression<string>,
    "encryptionSecretId": configuration expression<secret-id>,
    "clientId": configuration expression<string>,
    "tokenEndpoint": configuration expression<url>,
    "secretsProvider": SecretsProvider reference,
    "signingSecretId": configuration expression<string>,
    "signingAlgorithm": configuration expression<string>,
    "jwtExpirationTimeout": configuration expression<duration>,
    "claims": map or configuration expression<map>
  }
}

Configuration

"encryptionAlgorithm": configuration expression<string>, required

The algorithm name used for encryption and decryption. Use algorithm names from Java Security Standard Algorithm Names.

"encryptionMethod": configuration expression<string>, optional

The algorithm method to use for encryption. Use algorithms from RFC 7518, section-5.1.

"encryptionSecretId": configuration expression<secret-id>, required

The secret-id of the keys used to encrypt the JWT.

This secret ID must point to a CryptoKey.

"clientId": configuration expression<string>, required

The client_id obtained when registering with the Authorization Server.

"tokenEndpoint": configuration expression<url>, required

The URL to the Authorization Server’s OAuth 2.0 token endpoint.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to resolve queried secrets, such as passwords and cryptographic keys. For allowed formats, refer to SecretsProvider.

"signingSecretId": configuration expression<string>, required

Reference to the keys used to sign the JWT.

This secret ID must point to a CryptoKey.

"signingAlgorithm": configuration expression<string>, optional

The JSON Web Algorithm (JWA) used to sign the JWT, such as:

  • RS256: RSA using SHA-256

  • ES256: ECDSA with SHA-256 and NIST standard P-256 elliptic curve

  • ES384: ECDSA with SHA-384 and NIST standard P-384 elliptic curve

  • ES512: ECDSA with SHA-512 and NIST standard P-521 elliptic curve

Default: RS256

"jwtExpirationTimeout": configuration expression<duration>, optional

The duration for which the JWT is valid.

Default: 1 minute

"claims": map or configuration expression<map>, optional

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

  • The key is the name of a claim used in authentication

  • The value is the value of the claim, or a configuration expression that evaluates to the value

The following formats are allowed:

{
  "args": {
    "string": "configuration expression<string>",
    ...
  }
}
{
  "args": "configuration expression<map>"
}

Default: Empty

EntityExtractFilter

Extracts regular expression patterns from a message entity, and stores their values in a target object. Use this object in password replay, to find a login path or extract a nonce.

If the message type is REQUEST, the pattern is extracted before the request is handled. If the message type is RESPONSE, the pattern is extracted out of the response body.

Each pattern can have an associated template, which is applied to its match result.

For information, see Patterns.

Usage

{
    "name": string,
    "type": "EntityExtractFilter",
    "config": {
        "messageType": configuration expression<enumeration>,
        "charset": configuration expression<string>,
        "target": lvalue-expression,
        "bindings": [
            {
                "key": configuration expression<string>,
                "pattern": pattern,
                "template": pattern
            }, ...
        ]
    }
}

Properties

"messageType": configuration expression<enumeration>, required

The message type to extract patterns from.

Must be REQUEST or RESPONSE.

"charset": configuration expression<string>, optional

Overrides the character set encoding specified in message.

Default: The message encoding is used.

"target": <lvalue-expression>, required

Expression that yields the target object that contains the extraction results.

The bindings determine what type of object is stored in the target location.

The object stored in the target location is a Map<String, String>. You can then access its content with ${target.key} or ${target['key']}.

See also Expressions.

"key": configuration expression<string>, required

Name of the element in the target object to contain an extraction result.

"pattern": pattern, required

The regular expression pattern to find in the entity.

See also Patterns.

"template": pattern-template, optional

The template to apply to the pattern, and store in the named target element.

Default: store the match result itself.

See also Patterns.

Examples

Extracts a nonce from the response, which is typically a login page, and sets its value in the attributes context to be used by the downstream filter posting the login form. The nonce value would be accessed using the following expression: ${attributes.extract.wpLoginToken}.

The pattern finds all matches in the HTTP body of the form wpLogintokenvalue="abc". Setting the template to $1 assigns the value abc to attributes.extract.wpLoginToken:

{
    "name": "WikiNoncePageExtract",
    "type": "EntityExtractFilter",
    "config": {
        "messageType": "response",
        "target": "${attributes.extract}",
        "bindings": [
            {
                "key": "wpLoginToken",
                "pattern": "wpLoginToken\"\\s.*value=\"(.*)\"",
                "template": "$1"
            }
        ]
    }
}

The following example reads the response looking for the AM login page. When found, it sets isLoginPage = true to be used in a SwitchFilter to post the login credentials:

{
    "name": "FindLoginPage",
    "type": "EntityExtractFilter",
    "config": {
        "messageType": "response",
        "target": "${attributes.extract}",
        "bindings": [
            {
                "key": "isLoginPage",
                "pattern": "OpenAM\s\(Login\)",
                "template": "true"
            }
        ]
    }
}

FapiInteractionIdFilter

Tracks the interaction ID of requests, according to the Financial-grade API (FAPI) WG, as follows:

  • If a FAPI header is provided in a client request, includes the interaction ID in the x-fapi-interaction-id property of the response header.

  • If a FAPI header is not provided in the request, includes a new Universally Unique Identifier (UUID) in the x-fapi-interaction-id property of the response header.

  • Adds the value of x-fapi-interaction-id to the log.

Usage

{
  "name": string,
  "type": "FapiInteractionIdFilter"
}

Properties

There are no configuration properties for this filter.

Example

The following example, based on Validate Certificate-Bound Access Tokens, adds a FapiInteractionIdFilter to the end of the chain:

{
  "name": "mtls",
  "condition": "${find(request.uri.path, '/mtls')}",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [ {
          "name": "OAuth2ResourceServerFilter-1",
           ...
        },
        {
          "type": "FapiInteractionIdFilter"
        }
      ],
      "handler": {
          "name": "StaticResponseHandler-1",
          ...
      }
    }
  }
}

FragmentFilter

Tracks the fragment part of a URI when a request triggers a login redirect, as follows:

  • Before authentication, the filter captures the URI fragment information and stores it in a cookie.

  • After authentication, when the request is issued again to the original URI, the filter redirects the browser to the original URI, including any URI fragment.

The full fragment capture process is described in URI fragments in redirect.

The FragmentFilter doesn’t handle multiple fragment captures in parallel. If a fragment capture is in progress while IG performs another login redirect, a second fragment capture process isn’t triggered and the fragment is lost.

When a browser request loads a favicon, it can cause the fragment part of a URI to be lost. Prevent problems by serving static resources with a separate route. As an example, use the route in Serve static resources.

Use this filter with SingleSignOnFilter, CrossDomainSingleSignOnFilter, AuthorizationCodeOAuth2ClientFilter, and PolicyEnforcementFilter. This filter is not required for SAML because the final redirect is done with a DispatchHandler and a StaticResponseFilter.

Usage

{
  "name": string,
  "type": "FragmentFilter",
  "config": {
    "fragmentCaptureEndpoint": configuration expression<string>,
    "noJavaScriptMessage": configuration expression<string>,
    "cookie": object
  }
}
"fragmentCaptureEndpoint": configuration expression<string>, required

The IG endpoint used to capture the fragment form data.

Configure the endpoint to match the condition of the route in which the filter is used.

"noJavaScriptMessage": configuration expression<string>, optional

A message to display on the fragment form when JavaScript is not enabled.

Default: No message

"cookie": object, optional

The configuration of the cookie used to store the fragment information.

{
  "name": configuration expression<string>,
  "domain": configuration expression<string>,
  "httpOnly": configuration expression<boolean>,
  "path": configuration expression<string>,
  "sameSite": configuration expression<enumeration>,
  "secure": configuration expression<boolean>,
  "maxAge": configuration expression<duration>
}
"name": configuration expression<string>, optional

Cookie name.

Default: ig-fragment-cookie

"domain": configuration expression<string>, optional

Domain to which the cookie applies.

Default: The fully qualified hostname of the IG host.

"httpOnly": configuration expression<boolean>, optional

Flag to mitigate the risk of client-side scripts accessing protected cookies.

Default: true

"path": configuration expression<string>, optional

Path to apply to the cookie.

Default: /

"sameSite": configuration expression<enumeration>, optional

Options to manage the circumstances in which a cookie is sent to the server. Use one of the following values to reduce the risk of CSRF attacks:

  • STRICT: Send the cookie only if the request was initiated from the cookie domain. Not case-sensitive.

    Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • LAX: Send the cookie only with GET requests in a first-party context, where the URL in the address bar matches the cookie domain. Not case-sensitive.

    Use this value to reduce the risk of cross-site request forgery (CSRF) attacks.

  • NONE: Send the cookie whenever a request is made to the cookie domain. Not case-sensitive.

    With this setting, consider setting secure to true to prevent browsers from rejecting the cookie. For more information, refer to SameSite cookies.

Default: LAX

"secure": configuration expression<boolean>, optional

Flag to limit the scope of the cookie to secure channels.

Default: false

"maxAge": configuration expression<duration>, optional

The maximum duration for which the FragmentFilter cookie can be valid.

When this maxAge is greater than the browser’s maximum internal value, the browser value takes precedence.

Default: 1 hour

Example

For an example of how the FragmentFilter is used in an SSO flow, refer to URI fragments in redirect.

FileAttributesFilter

Retrieves and exposes a record from a delimiter-separated file. Lookup of the record is performed using a specified key, whose value is derived from an expression. The resulting record is exposed in an object whose location is specified by the target expression. If a matching record cannot be found, then the resulting object is empty.

The retrieval of the record is performed lazily; it does not occur until the first attempt to access a value in the target. This defers the overhead of file operations and text processing until a value is first required. This also means that the value expression is not evaluated until the object is first accessed.

Usage

{
     "name": string,
     "type": "FileAttributesFilter",
     "config": {
         "file": configuration expression<string>,
         "charset": configuration expression<string>,
         "separator": configuration expression<enumeration>,
         "header": configuration expression<boolean>,
         "fields": [ configuration expression<string>, ... ],
         "target": lvalue-expression,
         "key": configuration expression<string>,
         "value": runtime expression<string>
     }
}

For an example, refer to Password replay from a file.

Properties

"file": configuration expression<string>, required

The file containing the record to be read.

"charset": configuration expression<string>, optional

The character set in which the file is encoded.

Default: "UTF-8".

"separator": configuration expression<enumeration>, optional

The separator character, which is one of the following:

COLON

Unix-style colon-separated values, with backslash as the escape character.

COMMA

Comma-separated values, with support for quoted literal strings.

TAB

Tab-separated values, with support for quoted literal strings.

Default: COMMA

"header": configuration expression<boolean>,optional

A flag to treat the first row of the file as a header row.

When the first row of the file is treated as a header row, the data in that row is disregarded and cannot be returned by a lookup operation.

Default: true.

"fields": array of configuration expression<strings>, optional

A list of keys in the order they appear in a record.

If fields is not set, the keys are assigned automatically by the column numbers of the file.

"target": <lvalue-expression>, required

Expression that yields the target object to contain the record.

The target object is a Map<String, String>, where the fields are the keys. For example, if the target is ${attributes.file} and the record has a username field and a password field mentioned in the fields list, Then you can access the user name as ${attributes.file.username} and the password as ${attributes.file.password}.

See also Expressions.

"key": configuration expression<string>, required

The key used for the lookup operation.

"value": runtime expression<string>, required

The value to be looked-up in the file.

See also Expressions.

ForwardedRequestFilter

Rebase the request URI to a computed scheme, host name, and port.

Use this filter to configure redirects when a request is forwarded by an upstream application such as a TLS offloader.

Usage

{
  "name": string,
  "type": "ForwardedRequestFilter",
  "config": {
    "scheme": runtime expression<string>,
    "host": runtime expression<string>,
    "port": runtime expression<number>
  }
}

Properties

At least one of scheme, host, or port must be configured.

"scheme": runtime expression<string>, optional

The scheme to which the request is rebased, for example, https.

Default: Not rebased to a different scheme

"host": runtime expression<string>, optional

The host to which the request is rebased.

Default: Not rebased to a different host

"port": runtime expression<number>, optional

The port to which the request is rebased.

Default: Not rebased to a different port

Example

In the following configuration, IG runs behind an AWS load balancer, to perform a login page redirect to an authentication party, using the original URI requested by the client.

IG can access the URI used by the load balancer to reach IG, but can’t access the original request URI.

The load balancer breaks the original request URI into the following headers, and adds them to the incoming request:

  • X-Forwarded-Proto: Scheme

  • X-Forwarded-Port: Port

  • Host: Original host name, and possibly the port.

{
  "type": "ForwardedRequestFilter",
  "config": {
    "scheme": "${request.headers['X-Forwarded-Proto'][0]}",
    "host": "${split(request.headers['Host'][0], ':')[0]}",
    "port": "${integer(request.headers['X-Forwarded-Port'][0])}"
  }
}

GrantSwapJwtAssertionOAuth2ClientFilter

Transforms requests for OAuth 2.0 access tokens into secure JWT bearer grant type requests. Propagates transformed requests to Identity Cloud or AM to obtain an access token.

Use this filter with Identity Cloud or AM to increase the security of less-secure grant-type requests, such as Client credentials grant requests or Resource owner password credentials grant requests.

The GrantSwapJwtAssertionOAuth2ClientFilter obtains access tokens from the /oauth2/access_token endpoint. To prevent unwanted or malicious access to the endpoint, make sure only a well-defined set of clients can use this filter.

Consider the following options to secure access to the GrantSwapJwtAssertionOAuth2ClientFilter:

  • Deploy IG on a trusted network.

  • Use mutual TLS (mTLS) and X.509 certificates for authentication between clients and IG. For more information, refer to OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens.

  • Configure an AllowOnlyFilter in front of the GrantSwapJwtAssertionOAuth2ClientFilter to control access within a route.

  • Define restrictive Route conditions to allow access only for expected grant-type requests. For example, define a route condition that requires a specific client ID, grant-type, or scope.

  • Configure a ScriptableFilter in front of the GrantSwapJwtAssertionOAuth2ClientFilter to validate requests.

For an example that uses GrantSwapJwtAssertionOAuth2ClientFilter, refer to Secure the OAuth 2.0 access token endpoint.

Usage

{
  "name": string,
  "type": "GrantSwapJwtAssertionOAuth2ClientFilter",
  "config": {
    "clientId": configuration expression<string>,
    "scopes": [ runtime expression<string>, ... ] or ResourceAccess reference,
    "assertion": object,
    "secretsProvider": SecretsProvider reference,
    "signature": object,
    "encryption": object,
    "failureHandler": Handler reference
  }
}

Properties

"clientId": configuration expression<string>, optional

The OAuth 2.0 client ID to use for authentication.

"scopes": array of runtime expression<strings> or ResourceAccess <reference>, required

A list of one or more scopes required by the OAuth 2.0 access token. Provide the scopes as strings or through a ResourceAccess such as a RequestFormResourceAccess or ScriptableResourceAccess:

Array of runtime expression<strings>, required if a ResourceAccess isn’t used

A string, array of strings, runtime expression<string>, or array of runtime expression<string> to represent one or more scopes.

RequestFormResourceAccess <reference>

A ResourceAccess that transfers scopes from the inbound request to a JWT bearer grant-type request.

In the following example request, the ResourceAccess extracts scopes from the request:

$ POST 'http://openig.example.com:8081/am/oauth2/access_token'
header 'Content-Type: application/x-www-form-urlencoded'
urlencoded form-data 'grant_type=client_credentials'
urlencoded form-data 'client_id=service-account'
urlencoded form-data 'scope=fr:idm:*'

Default: Empty

ScriptableResourceAccess <reference>

A script that evaluates each request dynamically and returns the scopes that the request needs to access the protected resource. The script must return a Set<String>.

For information about the properties of ScriptableResourceAccess, refer to Scripts.

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

Default: Empty

"assertion": object, required

The JWT claims. The GrantSwapJwtAssertionOAuth2ClientFilter checks that all mandatory fields are present and sets the JWT expiry. The filter doesn’t check the fields in otherClaims.

{
  "assertion": {
    "issuer": runtime expression<string>,
    "subject": runtime expression<string>,
    "audience": runtime expression<string>,
    "expiryTime": runtime expression<duration>,
    "otherClaims": map<string, runtime expression<string>>
  }
}
"issuer": string, required

The JWT iss claim. Can’t be null.

"subject": string, required

The JWT sub claim. Can’t be null.

"audience": string, required

The JWT aud claim. Can’t be null.

"expiryTime": duration, required

The JWT exp claim. Can’t be zero or unlimited.

Default: 2 minutes

"otherClaims": map or map, optional

A map of additional JWT claims with the format Map<String, RuntimeExpression<String>>, where:

  • Key: Claim name

  • Value: Claim value

Use the following format:

{
  "otherClaims": {
    "string": "runtime expression<string>",
    ...
  }
}

The filter doesn’t check otherClaims in the JWT.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

"signature": object, optional

A JWT signature to validate the authenticity of claims and data.

{
  "signature": {
    "secretId": configuration expression<secret-id>,
    "includeKeyId": configuration expression<boolean>
  }
}
"secretId": configuration expression<secret-id>, required if signature is used

The secret ID of the key to sign the JWT. The secret ID must point to a CryptoKey.

"includeKeyId": configuration expression<boolean>, optional

A flag to include the ID of the signature key in the JWT header:

  • true: Include the flag

  • false: Don’t include the flag

Default: true

"failureHandler": Handler <reference>, optional

Handler to manage a failed request.

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

Default: 500 Internal Server Error, the request stops being executed.

Example

For an example that uses GrantSwapJwtAssertionOAuth2ClientFilter, refer to Secure the OAuth 2.0 access token endpoint.

HeaderFilter

Removes headers from and adds headers to request and response messages. Headers are added to any existing headers in the message. To replace a header, remove the header and then add it again.

Usage

{
  "name": string,
  "type": "HeaderFilter",
  "config": {
    "messageType": configuration expression<enumeration>,
    "remove": [ configuration expression<string>, ... ],
    "add": {
      string: [ runtime expression<string>, ... ], ...
    }
  }
}

Properties

`"messageType": configuration expression<enumeration>, required

The type of message for which to filter headers. Must be either "REQUEST" or "RESPONSE".

"remove": array of configuration expression<strings>, optional

The names of header fields to remove from the message.

"add": object, optional

One or more headers to add to a request, with the format name: [ value, …​ ], where:

  • name is a string for a header name.

  • value is a runtime expression that resolves to one or more header values.

Examples

Replace host header on an incoming request

The following example replaces the host header on the incoming request with the value myhost.com:

{
  "name": "ReplaceHostFilter",
  "type": "HeaderFilter",
  "config": {
    "messageType": "REQUEST",
    "remove": [ "host" ],
    "add": {
      "host": [ "myhost.com" ]
    }
  }
}

The following example adds a Set-Cookie header to the response:

{
  "name": "SetCookieFilter",
  "type": "HeaderFilter",
  "config": {
    "messageType": "RESPONSE",
    "add": {
      "Set-Cookie": [ "mysession=12345" ]
    }
  }
}
Add headers to a request

The following example adds the headers custom1 and custom2 to the request:

{
  "name": "SetCustomHeaders",
  "type": "HeaderFilter",
  "config": {
    "messageType": "REQUEST",
    "add": {
      "custom1": [ "12345", "6789" ],
      "custom2": [ "abcd" ]
    }
  }
}
Add a token value to a response

The following example adds the value of session’s policy enforcement token to the pef_sso_token header in the response:

{
  "type": "HeaderFilter",
  "config": {
    "messageType": "RESPONSE",
    "add": {
      "pef_sso_token": ["${session.pef_token}"]
    }
  }
}
Add headers and logging results

The following example adds a message to the request and response as it passes through the Chain, and the capture on the ReverseProxyHandler logs the result. With IG and the sample application set up as described in the Quick install, access this route on http://ig.example.com:8080/home/chain.

{
  "condition": "${find(request.uri.path, '^/home/chain')}",
  "handler": {
    "type": "Chain",
    "comment": "Base configuration defines the capture decorator",
    "config": {
      "filters": [
        {
          "type": "HeaderFilter",
          "comment": "Add a header to all requests",
          "config": {
            "messageType": "REQUEST",
            "add": {
              "MyHeaderFilter_request": [
                "Added by HeaderFilter to request"
              ]
            }
          }
        },
        {
          "type": "HeaderFilter",
          "comment": "Add a header to all responses",
          "config": {
            "messageType": "RESPONSE",
            "add": {
              "MyHeaderFilter_response": [
                "Added by HeaderFilter to response"
              ]
            }
          }
        }
      ],
      "handler": {
        "type": "ReverseProxyHandler",
        "comment": "Log request, pass it to the sample app, log response",
        "capture": "all",
        "baseURI": "http://app.example.com:8081"
      }
    }
  }
}

The chain receives the request and context and processes it as follows:

  • The first HeaderFilter adds a header to the incoming request.

  • The second HeaderFilter manages responses not requests, so it simply passes the request and context to the handler.

  • The ReverseProxyHandler captures (logs) the request.

  • The ReverseProxyHandler forwards the transformed request to the protected application.

  • The protected application passes a response to the ReverseProxyHandler.

  • The ReverseProxyHandler captures (logs) the response.

  • The second HeaderFilter adds a header added to the response.

  • The first HeaderFilter is configured to manage requests, not responses, so it simply passes the response back to IG.

The following example lists some of the HTTP requests and responses captured as they flow through the chain. You can search the log files for MyHeaderFilter_request and MyHeaderFilter_response.

# Original request from user-agent
GET http://ig.example.com:8080/home/chain HTTP/1.1
Accept: /
Host: ig.example.com:8080

# Add a header to the request (inside IG) and direct it to the protected application
GET http://app.example.com:8081/home/chain HTTP/1.1
Accept: /
Host: ig.example.com:8080
MyHeaderFilter_request: Added by HeaderFilter to request

# Return the response to the user-agent
HTTP/1.1 200 OK
Content-Length: 1809
Content-Type: text/html; charset=ISO-8859-1

# Add a header to the response (inside IG)
HTTP/1.1 200 OK
Content-Length: 1809
MyHeaderFilter_response: Added by HeaderFilter to response

HttpBasicAuthenticationClientFilter

Authenticates clients according to the HTTP basic access authentication scheme.

HTTP basic access authentication is a simple challenge and response mechanism, where a server requests credentials from a client, and the client passes them to the server in an Authorization header. The credentials are base-64 encoded. To protect them, use SSL encryption for the connections between the server and client. For more information, refer to RFC 2617.

Compare the purpose of this filter with that of the following filters:

Use HttpBasicAuthenticationClientFilter in a service-to-service context, where services need to access resources protected by HTTP basic access authentication.

Usage

{
  "name": string,
  "type": "HttpBasicAuthenticationClientFilter",
  "config": {
    "username": configuration expression<string>,
    "passwordSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "urlEncodeCredentials": configuration expression<boolean>
  }
}

Properties

"username": configuration expression<string>, required

The username of the client to authenticate.

"passwordSecretId": configuration expression<string>, required

The secret ID required to obtain the client password.

This secret ID must point to a GenericSecret.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to obtain the passwordSecretId. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

"urlEncodeCredentials": configuration expression<boolean>, optional

Set to true to URL-encoded credentials before base64-encoding them.

Default: false

Example

The following example shows the flow of information when a client service accesses a resource protected by HTTP basic access authentication:

HttpBasicAuthenticationClientFilter
Set Up the Example
  1. Add the following script to the IG configuration:

    • Linux

    • Windows

    $HOME/.openig/scripts/groovy/BasicAuthResourceServerFilter.groovy
    %appdata%\OpenIG\scripts\groovy\BasicAuthResourceServerFilter.groovy
    /*
     * This script is a simple implementation of HTTP basic access authentication on
     * server side.
     * It expects the following arguments:
     *  - realm: the realm to display when the user agent prompts for
     *    username and password if none were provided.
     *  - username: the expected username
     *  - passwordSecretId: the secretId to find the password
     *  - secretsProvider: the SecretsProvider to query for the password
    */
    import static org.forgerock.util.promise.Promises.newResultPromise;
    
    import java.nio.charset.Charset;
    import org.forgerock.util.encode.Base64;
    import org.forgerock.secrets.Purpose;
    import org.forgerock.secrets.GenericSecret;
    
    String authorizationHeader = request.getHeaders().getFirst("Authorization");
    if (authorizationHeader == null) {
        // No credentials provided, return 401 Unauthorized
        Response response = new Response(Status.UNAUTHORIZED);
        response.getHeaders().put("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
        return newResultPromise(response);
    }
    
    return secretsProvider.getNamed(Purpose.PASSWORD, passwordSecretId)
            .thenAsync(password -> {
                // Build basic authentication string -> username:password
                StringBuilder basicAuthString = new StringBuilder(username).append(":");
                password.revealAsUtf8{ p -> basicAuthString.append(new String(p).trim()) };
                String expectedAuthorization = "Basic " + Base64.encode(basicAuthString.toString().getBytes(Charset.defaultCharset()));
                // Incorrect credentials provided, return 403 forbidden
                if (!expectedAuthorization.equals(authorizationHeader)) {
                    return newResultPromise(new Response(Status.FORBIDDEN));
                }
                // Correct credentials provided, continue.
                return next.handle(context, request);
            },
                    noSuchSecretException -> { throw new RuntimeException(noSuchSecretException); });

    The script is a simple implementation of the HTTP basic access authentication scheme. For information about scripting filters and handlers, refer to Extensibility.

  2. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/http-basic-access.json
    %appdata%\OpenIG\config\routes\http-basic-access.json
    {
      "name": "http-basic-access",
      "baseURI": "http://ig.example.com:8080",
      "condition" : "${find(request.uri.path, '^/http-basic-access')}",
      "heap": [
        {
          "name": "httpBasicAuthEnabledClientHandler",
          "type": "Chain",
          "capture": "all",
          "config": {
            "filters": [
              {
                "type": "HttpBasicAuthenticationClientFilter",
                "config": {
                  "username": "myclient",
                  "passwordSecretId": "password.secret.id",
                  "secretsProvider": {
                    "type": "Base64EncodedSecretStore",
                    "config": {
                      "secrets": {
                        "password.secret.id": "cGFzc3dvcmQ="
                      }
                    }
                  }
                }
              }
            ],
            "handler": "ForgeRockClientHandler"
          }
        }
      ],
      "handler": {
        "type": "ScriptableHandler",
        "config": {
          "type": "application/x-groovy",
          "clientHandler": "httpBasicAuthEnabledClientHandler",
          "source": [
            "request.uri.path = '/http-basic-protected-resource'",
            "return http.send(context, request);"
          ]
        }
      }
    }

    Note the following features of the route:

    • The route matches requests to /http-basic-access.

    • The ScriptableHandler rewrites the request to target it to /http-basic-protected-resource, and then calls the HTTP client, that has been redefined to use the httpBasicAuthEnabledClientHandler.

    • The httpBasicAuthEnabledClientHandler calls the HttpBasicAuthenticationClientFilter to authenticate the client, using the client’s credentials.

  3. Add the following route to IG:

    • Linux

    • Windows

    $HOME/.openig/config/routes/http-basic-protected-resource.json
    %appdata%\OpenIG\config\routes\http-basic-protected-resource.json
    {
      "heap": [
        {
          "name": "mySecretsProvider",
          "type": "Base64EncodedSecretStore",
          "config": {
            "secrets": {
              "password.secret.id": "cGFzc3dvcmQ="
            }
          }
        }
      ],
      "name": "http-basic-protected-resource",
      "condition": "${find(request.uri.path, '^/http-basic-protected-resource')}",
      "handler": {
        "type": "Chain",
        "config": {
          "filters": [
            {
              "name": "HttpBasicAuthResourceServerFilter",
              "type": "ScriptableFilter",
              "config": {
                "type": "application/x-groovy",
                "file": "BasicAuthResourceServerFilter.groovy",
                "args": {
                  "realm": "IG Protected Area",
                  "username": "myclient",
                  "passwordSecretId": "password.secret.id",
                  "secretsProvider": "${heap['mySecretsProvider']}"
    
                }
              }
            }
          ],
          "handler": {
            "type": "StaticResponseHandler",
            "config": {
              "status": 200,
              "headers": {
                "Content-Type": [ "text/html; charset=UTF-8" ]
              },
              "entity": "<html><body><h2>Access Granted</h2></body></html>"
            }
          }
        }
      }
    }

    Notice the following features of the route:

    • The route matches requests to /http-basic-protected-resource.

    • The ScriptableFilter provides a script to implement a simple HTTP basic access authentication scheme, that compares the provided credentials with the expected credentials.

    • When the client is authenticated, the StaticResponseHandler returns a message that access is granted.

  4. Access the route on http://ig.example.com:8080/http-basic-access.

    Because the expected credentials were provided in the request, a message shows that access is granted.

HttpBasicAuthFilter

Authenticate clients by providing the client credentials as a basic authorization header in the request. The credentials are base64-encoded.

This filter performs HTTP basic access authentication, described in RFC 2617.

Use this filter primarily for password replay scenarios, where the password is stored externally in clear text.

If challenged for authentication via a 401 Unauthorized status code by the server, this filter retries the request with credentials attached. After an HTTP authentication challenge is issued from the remote server, all subsequent requests to that remote server that pass through the filter include the user credentials.

If authentication fails (including the case where no credentials are yielded from expressions), then processing is diverted to the specified authentication failure handler.

Usage

{
    "name": string,
    "type": "HttpBasicAuthFilter",
    "config": {
        "username": runtime expression<string>,
        "password": runtime expression<string>,
        "failureHandler": Handler reference,
        "cacheHeader": configuration expression<boolean>
    }
}

Properties

"username": runtime expression<string>, required

The username to supply during authentication.

See also Expressions.

"password": runtime expression<string>, required

The password to supply during authentication.

See also Expressions.

"failureHandler": Handler reference, required

Dispatch to this Handler if authentication fails.

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

See also Handlers.

"cacheHeader": configuration expression<boolean>,optional

Whether or not to cache credentials in the session after the first successful authentication, and then replay those credentials for subsequent authentications in the same session.

With "cacheHeader": false, the filter generates the header for each request. This is useful, for example, when users change their passwords during a browser session.

Default: true

Example

{
    "name": "MyAuthenticator",
    "type": "HttpBasicAuthFilter",
    "config": {
        "username": "demo",
        "password": "password",
        "failureHandler": "AuthFailureHandler",
        "cacheHeader": false
    }
}

IdTokenValidationFilter

Validates an ID token by checking the standard claims, aud, exp, and iat. If specified in the configuration, this filter also checks the ID token issuer and signature.

This filter passes data into the context as follows:

  • If the JWT is validated, the request continues down the chain. The data is provided in the JwtValidationContext.

  • If the JWT is not validated, data is provided in the JwtValidationErrorContext.

    If a failure handler is configured, the request passes to the failure handler. Otherwise, an HTTP 403 Forbidden is returned.

The iat claim is required, and the iat minus the skewAllowance must be before the current time on the IG clock. For information, see OpenID Connect Core 1.0 incorporating errata set 1.

Usage

{
   "name": string,
   "type": "IdTokenValidationFilter",
   "config": {
     "idToken": runtime expression<string>,
     "audience": configuration expression<string>,
     "issuer": configuration expression<string>,
     "skewAllowance": configuration expression<duration>,
     "verificationSecretId": configuration expression<secret-id>,
     "secretsProvider": SecretsProvider reference,
     "customizer": JwtValidatorCustomizer reference,
     "failureHandler": Handler reference
   }
}

Properties

"idToken": runtime expression<string>, required

The ID token as an expression representing the JWT or signed JWT in the request. Cannot be null.

"audience": configuration expression<string>, required

One aud claim to check on the JWT. Cannot be null.

"issuer": configuration expression<string>, optional

One iss claim to check on the JWT. Can be null.

"skewAllowance": configuration expression<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

"verificationSecretId": configuration expression<secret-id>, required to verify the signature of signed tokens

The secret ID for the secret to verify the signature of signed tokens.

This secret ID must point to a CryptoKey.

If configured, the token must be signed. If not configured, IG does not verify the signature.

For information about how signatures are validated, refer to Validate the signature of signed tokens. For information about how each type of secret store resolves named secrets, refer to Secrets.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

"customizer": JwtValidatorCustomizer reference, optional

A set of validation constraints for JWT claims and sub-claims. If a claim is not validated against the constraint, the JWT is not validated.

The customizer does not override existing constraints, such as aud, iss, exp, and iat, which are predefined in the IdTokenValidationFilter, Defining a new constraint on an already constrained claim has an impact only if the new constraint is more restrictive.

JwtValidatorCustomizer provides a ScriptableJwtValidatorCustomizer to enrich a builder object by using its methods. Get more information about the following items:

The following examples provide checks:

Check that the value of the claim greaterThan5 is greater than 5
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('/greaterThan5', JsonValue::asInteger, isGreaterThan(5))"
    ]
  }
}
Check that the value of the claim sub is george
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('subname', JsonValue::asString, isEqualTo('george'))"
    ]
  }
}
Check that the value of the custom sub-claim is ForgeRock
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('customclaim/subclaim', JsonValue::asString, isEqualTo('ForgeRock'));"
    ]
  }
}
Check the value of multiple claims
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('aud', listOf(JsonValue::asString), contains('My App'))",
      "       .claim('iat', instant(), isInThePast())",
      "       .claim('exp', instant(), isInTheFuture());",
      "builder.claim('iss', JsonValue::asString, isEqualTo('ForgeRock AM'));"
    ]
  }
}
Check that the value of val1 is greater than val2
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [ "builder.claim('/val1', JsonValue::asInteger, isGreaterThan(claim('/val2').asInteger()))" ]
  }
}
Check that the value of val1 is greater than val2, when both are YYYY-MM-DD dates
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "Function<JsonValue, java.time.LocalDate, Exception> asDate() {",
      "  return (jsonValue) -> java.time.LocalDate.parse(jsonValue.asString());",
      "}",
      "builder.claim('claim1', asDate(), isGreaterThan(claim('claim2').as(asDate())));"
    ]
  }
}
Check that the claim issuer matches the regex pattern
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [ "builder.claim('iss', JsonValue::asString, find(~/.*am\.example\.(com|org)/))" ]
  }
}

Default: Claims are not validated

"failureHandler": Handler reference, optional

Handler to treat the request on failure.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

Example

Validate an id_token
  1. Set up AM:

    1. Set up AM as described in Validate access tokens through the introspection endpoint.

    2. Select Applications > OAuth 2.0 > Clients, and add the additional scope openid to client-application.

  2. Set up IG:

    1. Add the following route to IG:

      • Linux

      • Windows

      $HOME/.openig/config/routes/idtokenvalidation.json
      %appdata%\OpenIG\config\routes\idtokenvalidation.json
      {
        "name": "idtokenvalidation",
        "condition": "${find(request.uri.path, '^/idtokenvalidation')}",
        "capture": "all",
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [{
              "type": "IdTokenValidationFilter",
              "config": {
                "idToken": "<id_token_value>",
                "audience": "client-application",
                "issuer": "http://am.example.com:8088/openam/oauth2",
                "failureHandler": {
                  "type": "ScriptableHandler",
                  "config": {
                    "type": "application/x-groovy",
                    "source": [
                      "def response = new Response(Status.FORBIDDEN)",
                      "response.headers['Content-Type'] = 'text/html; charset=utf-8'",
                      "def errors = contexts.jwtValidationError.violations.collect{it.description}",
                      "def display = \"<html>Can't validate id_token:<br> ${contexts.jwtValidationError.jwt} \"",
                      "display <<=\"<br><br>For the following errors:<br> ${errors.join(\"<br>\")}</html>\"",
                      "response.entity=display as String",
                      "return response"
                    ]
                  }
                },
                "verificationSecretId": "verify",
                "secretsProvider": {
                  "type": "JwkSetSecretStore",
                  "config": {
                    "jwkUrl": "http://am.example.com:8088/openam/oauth2/connect/jwk_uri"
                  }
                }
              }
            }],
            "handler": {
              "type": "StaticResponseHandler",
              "config": {
                "status": 200,
                "headers": {
                  "Content-Type": [ "text/html; charset=UTF-8" ]
                },
                "entity": "<html><body>Validated id_token:<br> ${contexts.jwtValidation.value}</body></html>"
              }
            }
          }
        }
      }

      Notice the following features of the route:

      • The route matches requests to /idtokenvalidation.

      • A SecretsProvider declares a JwkSetSecretStore to validate secrets for signed JWTs, which specifies the URL to a JWK set on AM that contains the signing keys.

      • The property verificationSecretId is configured with a value. If this property is not configured, the filter does not verify the signature of tokens.

      • The JwkSetSecretStore specifies the URL to a JWK set on AM, that contains verification keys identified by a kid. The signature of the token is verified as follows:

        • If the value of a kid in the JWK set matches a kid in the the signed JWT, the JwkSetSecretStore verifies the signature.

        • If the JWT doesn’t have a kid, or if the JWK set doesn’t contain a key with the same value, the JwkSetSecretStore looks for valid secrets with the same purpose as the value of verificationSecretId.

      • If the filter validates the token, the StaticResponseHandler displays the token value from the context ${contexts.jwtValidation.value}. Otherwise, the ScriptableHandler displays the token value and a list of violations from the context ${contexts.jwtValidationError.violations}

  3. Test the setup:

    1. In a terminal window, use a curl command similar to the following to retrieve an id_token:

      $ curl -s \
      --user "client-application:password" \
      --data "grant_type=password&username=demo&password=Ch4ng31t&scope=openid" \
      http://am.example.com:8088/openam/oauth2/access_token
      
      {
       "access_token":"...",
       "scope":"openid",
       "id_token":"...",
       "token_type":"Bearer",
       "expires_in":3599
      }
      • In the route, replace <id_token_value> with the value of the id_token returned in the previous step.

    2. Access the route on http://ig.example.com:8080/idtokenvalidation.

      The validated token is displayed.

      • In the route, invalidate the token by changing the value of the audience or issuer, and then access the route again.

        The value of the token, and the reasons that the token is invalid, are displayed.

JwtBuilderFilter

Collects data at runtime, packs it in a JSON Web Token (JWT), and places the resulting JWT into the JwtBuilderContext.

Configure JwtBuilderFilter to create an unsigned JWT, a signed JWT, a signed then encrypted JWT, or an encrypted JTW:

  • Sign the JWT so that an application can validate the authenticity of the claims/data. The JWT can be signed with a shared secret or private key, and verified with a shared secret or corresponding public key.

  • Encrypt the JWT to reduce the risk of a data breach.

For a flexible way to pass identity or other runtime information to the protected application, use this filter with a HeaderFilter.

To enable downstream filters and handlers to verify signed and/or encrypted JWTs built by this filter, use this filter with a JwkSetHandler.

Usage

{
  "name": string,
  "type": "JwtBuilderFilter",
  "config": {
    "template": map or runtime expression<map>,
    "secretsProvider": SecretsProvider reference,
    "signature": object,
    "encryption": object
  }
}

Properties

"template": map or runtime expression<map>, required

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

  • The key is the name of a data field

  • The value is a data object, or a runtime expression that evaluates to a data object

The following formats are allowed:

{
  "template": {
    "string": "runtime expression<object>",
    ...
  }
}
{
  "template": "runtime expression<map>"
}

In the following example, the property is a map whose values are runtime expressions that evaluate to objects in the context:

{
  "template": {
    "name": "${contexts.userProfile.commonName}",
    "email": "${contexts.userProfile.rawInfo.mail[0]}",
    "address": "${contexts.userProfile.rawInfo.postalAddress[0]}",
    "phone": "${contexts.userProfile.rawInfo.telephoneNumber[0]}"
  }
}

In the following example, the property is a runtime expression that evaluates to a map with the format Map<String, Object>:

{
  "template": "${contexts.attributes}"
}

Use the now dynamic binding to dynamically set the value of an attribute that represents time. For example, set the value of attributes to a defined time after the expressions are evaluated, as follows:

{
  "name": "JwtBuilderFilter-1",
  "type": "JwtBuilderFilter",
    "config": {
    "template": {
      "iat": "${now.epochSeconds}",
      "nbf": "${now.plusSeconds(10).epochSeconds}",
      "exp": "${now.plusSeconds(20).epochSeconds}"
    },
    "secretsProvider": "FileSystemSecretStore-1",
      "signature": {
      "secretId": "id.key.for.signing.jwt",
      "algorithm": "RS512"
    }
  }
}
"secretsProvider": SecretsProvider reference, optional

The SecretsProvider object to query for JWT signing or encryption keys. For more information, refer to SecretsProvider.

Default: The route’s default secret service. For more information, refer to Default secrets object.

"signature": object, optional
The use of unsigned or unencrypted JWTs is deprecated and not considered secure. For more information, refer to the Deprecated section of the Release Notes.

A JWT signature to allow the authenticity of the claims/data to be validated. A signed JWT can be encrypted.

JwtBuilderFilter.encryption takes precedence over this property.

{
  "signature": {
    "secretId": configuration expression<secret-id>,
    "includeKeyId": configuration expression<secret-id>
    "algorithm": configuration expression<string>,
    "encryption": object,
    "keystore":  Keystore reference, //deprecated
    "alias": configuration expression<string>, //deprecated
    "password": configuration expression<string> //deprecated
  }
}
"secretId": configuration expression<secret-id>, required if signature is used

The secret ID of the key to sign the JWT.

This secret ID must point to a CryptoKey.

"includeKeyId": configuration expression<boolean>, optional

When true, include the ID of the signature key in the JWT header.

Default: true

"algorithm": configuration expression<string>, optional

The algorithm to sign the JWT.

The following algorithms are supported but not necessarily tested in IG:

"encryption": object, optional

Configuration to encrypt the JWT signature.

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

The secret ID of the key used to encrypt the JWT signature. The value is mapped to key aliases in KeyStoreSecretStore.

This secret ID must point to a CryptoKey.

"algorithm": configuration expression<string>, required

The algorithm used to encrypt the JWT signature.

For information about available algorithms, refer to RFC 7518: "alg" (Algorithm) Header Parameter Values for JWE.

"method": configuration expression<string>, required

The method used to encrypt the JWT signature.

For information about available methods, refer to RFC 7518: "enc" (Encryption Algorithm) Header Parameter Values for JWE.

"keystore": KeyStore reference, optional
This property is deprecated; use the signature subproperty secretId instead. For more information, refer to the Deprecated section of the Release Notes.

The Java KeyStore containing the key used to sign the JWT.

The name of a KeyStore object defined in the heap or an inline KeyStore configuration object.

"alias": configuration expression<string>, required if signature is used
This property is deprecated; use the signature subproperty secretId instead. For more information, refer to the Deprecated section of the Release Notes.

Alias for the key.

Note Because KeyStore converts all characters in its key aliases to lower case, use only lowercase in alias definitions of a KeyStore.

"password": expression<string>, required if signature is used
This property is deprecated; use the signature subproperty secretId instead. For more information, refer to the Deprecated section of the Release Notes.

Password for the key.

"encryption": object, optional
The use of unsigned or unencrypted JWTs is deprecated and not considered secure. For more information, refer to the Deprecated section of the Release Notes.

Configuration to encrypt the JWT. This property take precedence over JwtBuilderFilter.signature.

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

The secret ID of the key used to encrypt the JWT. The value is mapped to key aliases in KeyStoreSecretStore.

This secret ID must point to a CryptoKey.

"algorithm": configuration expression<string>, required

The algorithm used to encrypt the JWT.

For information about available algorithms, refer to RFC 7518: "alg" (Algorithm) Header Parameter Values for JWE.

"method": configuration expression<enumeration>, required

The method used to encrypt the JWT.

For information about available methods, refer to RFC 7518: "enc" (Encryption Algorithm) Header Parameter Values for JWE.

Examples

For examples, refer to Passing data along the chain

JwtValidationFilter

Validates an unsigned, signed, encrypted, or signed and encrypted JWT. The order of signing and encryption is not important; a JWT can be signed and then encrypted, or encrypted and then signed.

If the JWT is validated, the request continues down the chain. The data is provided in the JwtValidationContext.

If the JWT is not validated, data is provided in the JwtValidationErrorContext. If a failure handler is configured, the request passes to the failure handler. Otherwise, an HTTP 403 Forbidden is returned.

Usage

{
  "name": string,
  "type": "JwtValidationFilter",
  "config": {
    "jwt": runtime expression<string>,
    "verificationSecretId": configuration expression<secret-id>,
    "decryptionSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "skewAllowance": configuration expression<duration>,
    "customizer": JwtValidatorCustomizer reference,
    "failureHandler": Handler reference
  }
}

Properties

"jwt": runtime expression<string>, required

The value of the JWT in the request. Cannot be null.

"verificationSecretId": configuration expression<secret-id>, required to verify the signature of signed tokens

The secret ID for the secret to verify the signature of signed tokens.

This secret ID must point to a CryptoKey.

If configured, the token must be signed. If not configured, IG does not verify the signature.

For information about how signatures are validated, refer to Validate the signature of signed tokens. For information about how each type of secret store resolves named secrets, refer to Secrets.

"decryptionSecretId": configuration expression<secret-id>, required if AM secures access tokens with encryption

The secret ID for the secret to verify the encryption of tokens.

This secret ID must point to a CryptoKey.

If configured, the token must be encrypted. If not configured, IG does not verify the encryption.

For information about how each type of secret store resolves named secrets, see Secrets.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap or specify a SecretsProvider object inline.

"customizer": JwtValidatorCustomizer reference, optional

A set of validation constraints for JWT claims and sub-claims. If a claim is not validated against the constraint, the JWT is not validated.

The customizer does not override existing constraints, such as aud, iss, exp, and iat, which are predefined in the IdTokenValidationFilter, Defining a new constraint on an already constrained claim has an impact only if the new constraint is more restrictive.

JwtValidatorCustomizer provides a ScriptableJwtValidatorCustomizer to enrich a builder object by using its methods. Get more information about the following items:

The following examples provide checks:

Check that the value of the claim greaterThan5 is greater than 5
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('/greaterThan5', JsonValue::asInteger, isGreaterThan(5))"
    ]
  }
}
Check that the value of the claim sub is george
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('subname', JsonValue::asString, isEqualTo('george'))"
    ]
  }
}
Check that the value of the custom sub-claim is ForgeRock
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('customclaim/subclaim', JsonValue::asString, isEqualTo('ForgeRock'));"
    ]
  }
}
Check the value of multiple claims
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "builder.claim('aud', listOf(JsonValue::asString), contains('My App'))",
      "       .claim('iat', instant(), isInThePast())",
      "       .claim('exp', instant(), isInTheFuture());",
      "builder.claim('iss', JsonValue::asString, isEqualTo('ForgeRock AM'));"
    ]
  }
}
Check that the value of val1 is greater than val2
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [ "builder.claim('/val1', JsonValue::asInteger, isGreaterThan(claim('/val2').asInteger()))" ]
  }
}
Check that the value of val1 is greater than val2, when both are YYYY-MM-DD dates
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [
      "Function<JsonValue, java.time.LocalDate, Exception> asDate() {",
      "  return (jsonValue) -> java.time.LocalDate.parse(jsonValue.asString());",
      "}",
      "builder.claim('claim1', asDate(), isGreaterThan(claim('claim2').as(asDate())));"
    ]
  }
}
Check that the claim issuer matches the regex pattern
"customizer": {
  "type": "ScriptableJwtValidatorCustomizer",
  "config": {
    "type": "application/x-groovy",
    "source": [ "builder.claim('iss', JsonValue::asString, find(~/.*am\.example\.(com|org)/))" ]
  }
}

Default: Claims are not validated

"skewAllowance": configuration expression<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

"failureHandler": Handler reference, optional

Handler to treat the request on failure.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

Example

For an example of using JwtValidationFilter, refer to JWT validation.

LocationHeaderFilter

For a response that generates a redirect to the proxied application, this filter rewrites the Location header on the response to redirect the user to IG.

Usage

{
    "name": string,
    "type": "LocationHeaderFilter",
    "config": {
        "baseURI": runtime expression<url>
    }
}

An alternative value for type is RedirectFilter.

Properties

"baseURI": runtime expression<url>,optional

The base URI of the IG instance. This is used to rewrite the Location header on the response.

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.

Default: Redirect to the original URI specified in the request.

See also Expressions.

Example

In the following example, IG listens on https://ig.example.com:443 and the application it protects listens on http://app.example.com:8081. The filter rewrites redirects that would normally take the user to locations under http://app.example.com:8081 to go instead to locations under https://ig.example.com:443.

{
     "name": "LocationRewriter",
     "type": "LocationHeaderFilter",
     "config": {
         "baseURI": "https://ig.example.com:443/"
      }
}

OAuth2ClientFilter

In IG 7.2, this filter was renamed to AuthorizationCodeOAuth2ClientFilter.

For backward compatibility, the name OAuth2ClientFilter can still be used in routes in this release. However, to prevent problems in future releases, update your configuration as soon as possible.

OAuth2ResourceServerFilter

Validates a request containing an OAuth 2.0 access token. The filter expects an OAuth 2.0 token from the HTTP Authorization header of the request, such as the following example header, where the OAuth 2.0 access token is 1fc…​ec9:

Authorization: Bearer 1fc...ec9

The filter performs the following tasks:

  • Extracts the access token from the request header.

  • Uses the configured access token resolver to resolve the access token against an Authorization Server, and validate the token claims.

  • Checks that the token has the scopes required by the filter configuration.

  • Injects the access token info into the OAuth2Context.

The following errors can occur during access token validation:

Error Response from the filter to the user agent

Combination of the filter configuration and access token result in an invalid request to the Authorization Server.

HTTP 400 Bad Request

There is no access token in the request header.

HTTP 401 Unauthorized WWW-Authenticate: Bearer realm="IG"

The access token isn’t valid, for example, because it has expired.

HTTP 401 Unauthorized

The access token doesn’t have all of the scopes required in the OAuth2ResourceServerFilter configuration.

HTTP 403 Forbidden

Usage

{
  "name": string,
  "type": "OAuth2ResourceServerFilter",
  "config": {
    "accessTokenResolver": AccessTokenResolver reference,
    "cache": object,
    "executor": Executor service reference,
    "requireHttps": configuration expression<boolean>,
    "realm": configuration expression<string>,
    "scopes": [ runtime expression<string>, ... ] or ScriptableResourceAccess reference
  }
}

An alternative value for type is OAuth2RSFilter.

Properties

"accessTokenResolver": AccessTokenResolver reference, required

Resolves an access token against an Authorization Server. Configure one of the following access token resolvers:

To decorate an AccessTokenResolver, add the decoration at the accessTokenResolver level. The following example uses the default timer decorator to record the time that a TokenIntrospectionAccessTokenResolver takes to process a request:

{
  "accessTokenResolver": {
    "type": "TokenIntrospectionAccessTokenResolver",
    "config": {
      ...
    },
  "timer": true
  }
}
"cache": object, optional

Configuration of caching for OAuth 2.0 access tokens. By default, access tokens are not cached. For an alternative way of caching of OAuth 2.0 access tokens, configure CacheAccessTokenResolver.

When an access token is cached, IG can reuse the token information without repeatedly asking the Authorization Server to verify the access token. When caching is disabled, IG must ask the Authorization Server to verify the access token for each request.

(From AM 6.5.3.) When an access_token is revoked on AM, the CacheAccessTokenResolver can delete the token from the cache when both of the following conditions are true:

  • The notification property of AmService is enabled.

  • The delegate AccessTokenResolver provides the token metadata required to update the cache.

When a refresh_token is revoked on AM, all associated access tokens are automatically and immediately revoked.

"cache": {
  "enabled": configuration expression<boolean>,
  "defaultTimeout": configuration expression<duration>,
  "maxTimeout": configuration expression<duration>,
  "amService": AmService reference,
  "onNotificationDisconnection": configuration expression<enumeration>
}
enabled: configuration expression<boolean>, optional

Enable or disable caching.

Default: false

defaultTimeout: configuration expression<duration>, optional

The duration for which to cache an OAuth 2.0 access token if it doesn’t provide a valid expiry value.

If an access token provides an expiry value that falls before the current time plus the maxTimeout, IG uses the token expiry value.

The following example caches access tokens for these times:

  • One hour, if the access token doesn’t provide a valid expiry value.

  • The duration specified by the token expiry value, when the token expiry value is shorter than one day.

  • One day, when the token expiry value is longer than one day.

"cache": {
  "enabled": true,
  "defaultTimeout": "1 hour",
  "maxTimeout": "1 day"
}

Default: 1 minute

maxTimeout: configuration expression<duration>, optional

The maximum duration for which to cache OAuth 2.0 access tokens.

If an access token provides an expiry value that falls after the current time plus the maxTimeout, IG uses the maxTimeout.

The duration cannot be zero or unlimited.

"amService": AmService reference, optional

(From AM 6.5.3.) The AmService to use for the WebSocket notification service. To evict revoked access tokens from the cache, enable the notifications property of AmService.

onNotificationDisconnection: configuration expression<enumeration>, optional

An amService must be configured for this property to have effect.

The strategy to manage the cache when the WebSocket notification service is disconnected, and IG receives no notifications for AM events. If the cache is not cleared it can become outdated, and IG can allow requests on revoked sessions or tokens.

Cached entries that expire naturally while the notification service is disconnected are removed from the cache.

Use one of the following values:

  • NEVER_CLEAR

    • When the notification service is disconnected:

      • Continue to use the existing cache.

      • Deny access for requests that are not cached, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Continue to use the existing cache.

      • Query AM for incoming requests that are not found in the cache, and update the cache with these requests.

  • CLEAR_ON_DISCONNECT

    • When the notification service is disconnected:

      • Clear the cache.

      • Deny access to all requests, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Query AM for all requests that are not found in the cache. (Because the cache was cleared, the cache is empty after reconnection.)

      • Update the cache with these requests.

  • CLEAR_ON_RECONNECT

    • When the notification service is disconnected:

      • Continue to use the existing cache.

      • Deny access for requests that are not cached, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Query AM for all requests that are not found in the cache. (Because the cache was cleared, the cache is empty after reconnection.)

      • Update the cache with these requests.

Default: CLEAR_ON_DISCONNECT

"executor": Executor service reference, optional

An executor service to schedule the execution of tasks, such as the eviction of entries in the access token cache.

Default: ScheduledExecutorService

"requireHttps": configuration expression<boolean>, optional

Whether to require that original target URI of the request uses the HTTPS scheme.

If the received request doesn’t use HTTPS, it is rejected.

Default: true.

"realm": configuration expression<string>, optional

HTTP authentication realm to include in the WWW-Authenticate response header field when returning an HTTP 401 Unauthorized status to a user agent that need to authenticate.

Default: OpenIG

"scopes": array of runtime expression<strings> or ResourceAccess <reference>, required

A list of one or more scopes required by the OAuth 2.0 access token. Provide the scopes as strings or through a ResourceAccess such as a ScriptableResourceAccess:

Array of runtime expression<strings>, required if a ResourceAccess isn’t used

A string, array of strings, runtime expression<string>, or array of runtime expression<string> to represent one or more scopes.

ScriptableResourceAccess <reference>

A script that evaluates each request dynamically and returns the scopes that the request needs to access the protected resource. The script must return a Set<String>.

For information about the properties of ScriptableResourceAccess, refer to Scripts.

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

Default: Empty

Examples

For examples using OAuth2ResourceServerFilter, see Act as an OAuth 2.0 resource server.

OAuth2TokenExchangeFilter

Identifies a client’s access token or ID token (a subject token), and communicates with an authorization service, such as AM, to exchange it for a new token (an issued token):

  • When the OAuth2TokenExchangeFilter succesfully exchanges a token, it injects the issued token and its scopes into the OAuth2TokenExchangeContext.

  • When the OAuth2TokenExchangeFilter fails to exchange a token, it injects information about the failure into the OAuth2FailureContext, which is provided to the failureHandler.

The scopes for issued token can be restricted or expanded by the authorization services:

  • Restricted when the token scopes are a subset of those available to the subject token.

  • Expanded when they have scopes that are not included in the subject token.

Use this filter in the impersonation use case. For more information, refer to Token Exchange in AM’s OAuth 2.0 guide.

Usage

{
  "name": string,
  "type": "OAuth2TokenExchangeFilter",
    "config": {
      "subjectToken": runtime expression<string>,
      "amService": AmService reference,
      "endpoint": configuration expression<url>,
      "subjectTokenType": configuration expression<string>,
      "requestedTokenType": configuration expression<string>,
      "scopes": [ runtime expression<string>, ... ] or ScriptableResourceAccess reference,
      "resource": configuration expression<url>,
      "audience": configuration expression<string>,
      "endpointHandler": Handler reference,
      "failureHandler": Handler reference
  }
}

Configuration

"subjectToken": runtime expression<string>, required

The location of the subject token in the inbound request.

"amService": AmService reference, required if endpoint is not configured

The AmService to use as the authorization service.

Configure either 'amService' or 'endpoint'. If both are configured, 'amService' takes precedence.

"endpoint": configuration expression<url>, required if amService is not configured

The URI for the authorization service.

Configure either 'amService' or 'endpoint'. If both are configured, 'amService' takes precedence.

"subjectTokenType": configuration expression<string>, optional

The subject token type.

Default: URN_ACCESS_TOKEN

"requestedTokenType": configuration expression<string>, optional

The type of token being requested.

Default: URN_ACCESS_TOKEN

"scopes": array of runtime expression<strings> or ResourceAccess <reference>, required

A list of one or more scopes required by the OAuth 2.0 access token. Provide the scopes as strings or through a ResourceAccess such as a ScriptableResourceAccess:

Array of runtime expression<strings>, required if a ResourceAccess isn’t used

A string, array of strings, runtime expression<string>, or array of runtime expression<string> to represent one or more scopes.

ScriptableResourceAccess <reference>

A script that evaluates each request dynamically and returns the scopes that the request needs to access the protected resource. The script must return a Set<String>.

For information about the properties of ScriptableResourceAccess, refer to Scripts.

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

Default: Empty

"resource": configuration expression<url>, optional

The target service URI where the issued token is intended to be used.

"audience": configuration expression<url>, optional

The target service name where the token is intended to be used.

"endpointHandler": Handler reference, optional

The handler to exchange tokens on the authorization endpoint.

Configure this property as a Chain, using one of the following filters for client authentication:

{
  "name": "EndpointHandler",
  "type": "Chain",
  "config": {
    "handler": "ForgeRockClientHandler",
    "filters": [
      {
        "type": "ClientSecretBasicAuthenticationFilter",
        "config": {
          "clientId": "serviceConfidentialClient",
          "clientSecretId": "client.secret.id",
          "secretsProvider" : "SystemAndEnvSecretStore-1",
        }
      }
    ]
  }
}

Default: ForgeRockClientHandler

"failureHandler": Handler <reference>, optional

Handler to manage a failed request.

Provide an inline handler configuration object or the name of a handler object declared in the heap. The handler can access information in the OAuth2FailureContext.

Default: 500 Internal Server Error, the request stops being executed.

Example

For an example of how this filter is used, refer to Token exchange.

PasswordReplayFilter

Extracts credentials from AM and replays them to a login page or to the next filter or handler in the chain. The PasswordReplayFilter does not retry failed authentication attempts.

The PasswordReplayFilter filter uses the AM Post Authentication Plugin com.sun.identity.authentication.spi.JwtReplayPassword. The plugin is triggered for AM authentication chains but not currently for AM authentication trees.

Do not use the PasswordReplayFilter with AM authentication trees.

Usage

{
  "name": string,
  "type": "PasswordReplayFilter",
  "config": {
    "request": object,
    "loginPage": runtime expression<boolean>,
    "loginPageContentMarker": pattern,
    "credentials": Filter reference,
    "headerDecryption": object,
    "loginPageExtractions": [ object, ... ]
  }
}

Properties

"request": <object>, required

The HTTP request message that replays the credentials.

{
  "request": object,
    "method": config expression<string>,
    "uri": runtime expression<string>,
    "version": configuration expression<string>,
    "entity": runtime expression<string>,
    "headers": map,
    "form": map
}

For information about the properties of `request`refer to Request.

The JSON object of request is the config content of a StaticRequestFilter.

"loginPage": runtime expression<boolean>, required unless loginPageContentMarker is defined

true: Direct the request to a login page, extract credentials, and replay them.

false: Pass the request unchanged to the next filter or handler in the chain.

The following example expression resolves to true when the request is an HTTP GET, and the request URI path is /login:

${find(request.uri.path, '/login') and (request.method == 'GET')}
"loginPageContentMarker": pattern, required unless loginPage is defined

A pattern that matches when a response entity is a login page.

For an example route that uses this property, refer to Login form with password replay and cookie filters.

See also Patterns.

"credentials": Filter reference, optional

Filter that injects credentials, making them available for replay. Consider using a FileAttributesFilter or an SqlAttributesFilter.

When this is not specified, credentials must be made available to the request by other means.

See also Filters.

"headerDecryption": object, optional

Object to decrypt request headers that contain credentials to replay.

{
  "headerDecryption": object,
    "algorithm": configuration expression<string>,
    "headers": [ configuration expression<string>, ... ],
    "keySecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "charset": configuration expression<string>,
    "key": string, //deprecated
    "keyType": string //deprecated
}
"algorithm": configuration expression<string>, optional

Algorithm used for decryption. Use the same algorithm that is used to send the encrypted credentials.

Default: AES/ECB/PKCS5Padding

"headers": array of configuration expression<strings>, optional

The names of header fields to decrypt.

Default: Do not decrypt any headers.

"keySecretId": configuration expression<secret-id>, required

The secret ID of the key to encrypt or decrypt the headers. This property takes precedence over the deprecated property key.

This secret ID must point to a CryptoKey.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to resolve queried secrets, such as passwords and cryptographic keys. For allowed formats, refer to SecretsProvider.

"charset": configuration expression<string>, optional

The name of the charset used to encrypt or decrypt values, as described in Class Charset.

Default: UTF-8

"key": string, optional
The use of this property is deprecated; use keySecretId and secretsProvider instead. For more information, refer to the Deprecated section of the Release Notes.

Base64 encoded key value.

"keyType": string, required
The use of this property is deprecated; use keySecretId and secretsProvider instead. For more information, refer to the Deprecated section of the Release Notes.

Algorithm name for the secret key.

Default: AES

"loginPageExtractions": array of <objects>, optional

Objects to extract values from the login page entity.

{
  "loginPageExtractions": [
    {
      "name": string,
      "pattern": pattern
    },
    ...
  ]
}

For an example route that uses this property, refer to Login which requires a hidden value from the login page.

The extract configuration array is a series of configuration objects. To extract multiple values, use multiple extract configuration objects. Each object has the following fields:

"name": string, required

Name of the field where the extracted value is put.

The names are mapped into attributes.extracted.

For example, if the name is nonce, the value can be obtained with the expression ${attributes.extracted.nonce}.

The name isLoginPage is reserved to hold a boolean that indicates whether the response entity is a login page.

"pattern": pattern, required

The regular expression pattern to find in the entity.

The pattern must contain one capturing group. (If it contains more than one, only the value matching the first group is placed into attributes.extracted.)

For example, suppose the login page entity contains a nonce required to authenticate, and the nonce in the page looks like nonce='n-0S6_WzA2Mj'. To extract n-0S6_WzA2Mj, set "pattern": " nonce='(.*)'".

Example

The following example authenticates requests using static credentials when the request URI path is /login. This PasswordReplayFilter example does not include any mechanism for remembering when authentication has already been successful, it simply replays the authentication every time that the request URI path is /login:

{
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [{
        "type": "PasswordReplayFilter",
        "config": {
          "loginPage": "${request.uri.path == '/login'}",
          "request": {
            "method": "POST",
            "uri": "https://www.example.com:8444/login",
            "form": {
              "username": [
                "MY_USERNAME"
              ],
              "password": [
                "MY_PASSWORD"
              ]
            }
          }
        }
      }],
      "handler": "ReverseProxyHandler"
    }
  }
}

For additional examples, refer to Configuration templates, and the Javadoc for the PasswordReplayFilter class.

PolicyEnforcementFilter

Requests and enforces policy decisions from AM. For more information, refer to IG’s Policy enforcement and AM’s Authorization guide.

Attributes and advices are stored in the policyDecision context. For information, refer to PolicyDecisionContext.

When the PolicyEnforcementFilter is preceded by a SingleSignOnFilter or CrossDomainSingleSignOnFilter in a Chain, it can respond to the following advice types from AM:

  • AuthLevel: The minimum authentication level at which a user agent must authenticate to access a resource.

  • AuthenticateToService: The name of an authorization chain or service to which a user agent must authenticate to access a resource.

  • AuthenticateToRealm: The name of a realm to which a user agent must authenticate to access a resource.

  • AuthScheme: The name of an authentication module to which a user agent must authenticate to access a resource, the policy set name, and the authentication timeout.

  • Transaction: The additional actions that a user agent must perform before having a one-time access to the protected resource.

When the PolicyEnforcementFilter isn’t preceded by a SingleSignOnFilter or CrossDomainSingleSignOnFilter in a Chain, it can’t respond to advices from AM. Requests that return policy decisions with advices fail with an HTTP 403 Forbidden.

Notes on configuring policies in AM

In the AM policy, remember to configure the Resources parameter with the URI of the protected application.

The request URI from IG must match the Resources parameter defined in the AM policy. If the URI of the incoming request is changed before it enters the policy filter (for example, by rebasing or scripting), remember to change the Resources parameter in AM policy accordingly.

WebSocket notifications for policy changes

When WebSocket notifications are set up for changes to policies, IG receives a notification from AM when a policy decision is created, deleted, or updated.

For information about setting up WebSocket notifications, using them to clear the policy cache, and including them in the server logs, refer to WebSocket Notifications.

Usage

{
  "name": string,
  "type": "PolicyEnforcementFilter",
  "config": {
    "amService": AmService reference,
    "pepRealm": configuration expression<string>,
    "ssoTokenSubject": runtime expression<string>,
    "jwtSubject": runtime expression<string>,
    "claimsSubject": map or runtime expression<map>,
    "cache": object,
    "application": configuration expression<string>,
    "environment": map or runtime expression<map>,
    "failureHandler": Handler reference,
    "resourceUriProvider": ResourceUriProvider reference,
    "authenticateResponseRequestHeader": configuration expression<string>,
    "useLegacyAdviceEncoding": configuration expression<boolean> //deprecated
  }
}

Properties

"amService": AmService reference, required

The AM instance to use for policy decisions.

"pepRealm": configuration expression<string>, optional

The AM realm where the policy set is located.

Default: The realm declared for amService.

"ssoTokenSubject": _runtime expression<string>, required if neither of the following properties are present: jwtSubject, claimsSubject

The AM token ID string for the subject making the request to the protected resource.

ssoTokenSubject can take the value of the session token from the following sources:

  • When the PolicyEnforcementFilter is preceded by a SingleSignOnFilter, ${contexts.ssoToken.value}.

  • When the PolicyEnforcementFilter is preceded by a CrossDomainSingleSignOnFilter, ${contexts.ssoToken.value} or ${contexts.cdsso.value}.

  • When the PolicyEnforcementFilter isn’t preceded by a SingleSignOnFilter or CrossDomainSingleSignOnFilter, ssoTokenSubject usually points to the token value.

    The token value can be in the request message, a header, or a cookie. For example, the ssoTokenSubject can point to a header value such as ${request.headers.cookie name}, where cookie name is the AM session cookie name.

    Requests that return a policy decision with advices fail with an HTTP 403 and no advice handling.

"jwtSubject": _runtime expression<string>, required if neither of the following properties are present: ssoTokenSubject, claimsSubject

The JWT string for the subject making the request to the protected resource.

To use the raw id_token (base64, not decoded) returned by the OpenID Connect Provider during authentication, place an AuthorizationCodeOAuth2ClientFilter filter before the PEP filter, and then use ${attributes.openid.id_token} as the expression value.

"claimsSubject": map or runtime expression<map>, required if neither of the following properties are present: jwtSubject, `"ssoTokenSubject`

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

  • The key is the name of a claim

  • The value is a claim object, or a runtime expression that evaluates to a claims object

The following formats are allowed:

{
  "claimsSubject": {
    "string": "runtime expression<object>",
    ...
  }
}
{
  "claimsSubject": "runtime expression<map>"
}

The claim "sub" must be specified; other claims are optional.

In the following example, the property is a map whose first value is a runtime expression that evaluates to a JWT claim for the subject, and whose second value is a JWT claim for the subject:

"claimsSubject": {
  "sub": "${attributes.subject_identifier}",
  "iss": "am.example.com"
}

In the following example, the property is a runtime expression that evaluates to a map with the format Map<String, Object>:

"claimsSubject": "${attributes.openid.id_token_claims}"

For an example that uses claimsSubject as a map, refer to Example policy enforcement using claimsSubject on this reference page.

"application": configuration expression<string>, optional

The ID of the AM policy set to use when requesting policy decisions.

Default: iPlanetAMWebAgentService, provided by AM’s default policy set

cache: object, optional

Enable and configure caching of policy decisions from AM, based on Caffeine. For more information, see the GitHub entry, Caffeine.

When a request matches a cached policy decision, IG can reuse the decision without asking AM for a new decision. When caching is disabled, IG must ask AM to make a decision for each request.

{
  "cache": {
    "enabled": configuration expression<boolean>,
    "defaultTimeout": configuration expression<duration>,
    "executor": Executor service reference,
    "maximumSize": configuration expression<number>,
    "maximumTimeToCache": configuration expression<duration>,
    "onNotificationDisconnection": configuration expression<enumeration>
  }
}

Default: Policy decisions are not cached.

Policy decisions that contain advices are never cached.

The following code example caches AM policy decisions without advices for these times:

  • One hour, when the policy decision doesn’t provide a ttl value.

  • The duration specified by the ttl, when ttl is shorter than one day.

  • One day, when ttl is longer than one day.

"cache": {
  "enabled": true,
  "defaultTimeout": "1 hour",
  "maximumTimeToCache": "1 day"
}
enabled: configuration expression<boolean>, optional

Enable or disable caching of policy decisions.

Default: false

defaultTimeout: configuration expression<duration>, optional

The default duration for which to cache AM policy decisions.

If an AM policy decision provides a valid ttl value to specify the time until which the policy decision remains valid, IG uses that value or the maxTimeout.

Default: 1 minute

"executor": Executor service reference, optional

An executor service to schedule the execution of tasks, such as the eviction of entries in the cache.

Default: ForkJoinPool.commonPool()

"maximumSize": configuration expression<number>, optional

The maximum number of entries the cache can contain.

Default: Unlimited/unbound.

maximumTimeToCache: configuration expression<duration>, optional

The maximum duration for which to cache AM policy decisions.

If the ttl value provided by the AM policy decision is after the current time plus the maximumTimeToCache, IG uses the maximumTimeToCache.

The duration cannot be zero or unlimited.

onNotificationDisconnection: configuration expression<enumeration>, optional

The strategy to manage the cache when the WebSocket notification service is disconnected, and IG receives no notifications for AM events. If the cache is not cleared it can become outdated, and IG can allow requests on revoked sessions or tokens.

Cached entries that expire naturally while the notification service is disconnected are removed from the cache.

Use one of the following values:

  • NEVER_CLEAR

    • When the notification service is disconnected:

      • Continue to use the existing cache.

      • Deny access for requests that are not cached, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Continue to use the existing cache.

      • Query AM for incoming requests that are not found in the cache, and update the cache with these requests.

  • CLEAR_ON_DISCONNECT

    • When the notification service is disconnected:

      • Clear the cache.

      • Deny access to all requests, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Query AM for all requests that are not found in the cache. (Because the cache was cleared, the cache is empty after reconnection.)

      • Update the cache with these requests.

  • CLEAR_ON_RECONNECT

    • When the notification service is disconnected:

      • Continue to use the existing cache.

      • Deny access for requests that are not cached, but do not update the cache with these requests.

    • When the notification service is reconnected:

      • Query AM for all requests that are not found in the cache. (Because the cache was cleared, the cache is empty after reconnection.)

      • Update the cache with these requests.

Default: CLEAR_ON_DISCONNECT

"environment": map or runtime expression<map>, optional

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

  • The key is the name of a field in the request environment or context, such as a request header

  • The value is the object to forward to AM with a policy decision request, or a runtime expression that evaluates to the object

The following formats are allowed:

{
  "claimsSubject": {
    "string": "runtime expression<object>",
    ...
  }
}
{
  "claimsSubject": "runtime expression<map>"
}

AM uses environment conditions to set the circumstances under which a policy applies. For example, environment conditions can specify that the policy applies only during working hours or only when accessing from a specific IP address.

Forward any HTTP header or any value that the AM policy definition can use.

In the following example, the property is a map whose values are runtime expressions that evaluate to request headers, an ID token, and the IP address of the subject making the request:

"environment": {
  "H-Via": "${request.headers['Via']}",
  "H-X-Forwarded-For": "${request.headers['X-Forwarded-For']}",
  "H-myHeader": "${request.headers['myHeader']}",
  "id_token": [
    "${attributes.openid.id_token}"
  ],
  "IP": [
    "${contexts.client.remoteAddress}"
  ]
}
"failureHandler": Handler reference, optional

Handler to treat the request if it is denied by the policy decision.

In the following example, the failureHandler is a chain with a scriptable filter. If there are some advices with the policy decision, the script recovers the advices for processing. Otherwise, it passes the request to the StaticResponseHandler to display a message.

"failureHandler": {
  "type": "Chain",
  "config": {
    "filters": [
      {
        "type": "ScriptableFilter",
        "config": {
          "type": "application/x-groovy",
          "source": [
            "if (contexts.policyDecision.advices['MyCustomAdvice'] != null) {",
            "  return handleCustomAdvice(context, request)",
            "} else {",
            "  return next.handle(context, request)",
            "}"
          ]
        }
      }
    ],
    "handler": {
      "type": "StaticResponseHandler",
      "config": {
        "status": 403,
        "headers": {
          "Content-Type": [ "text/plain; charset=UTF-8" ]
        },
        "entity": "Restricted area. You do not have sufficient privileges."
      }
    }
  }
}

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: HTTP 403 Forbidden, the request stops being executed.

"resourceUriProvider": ResourceUriProvider reference, optional

Use one of the following providers to return a resource URL to include in policy decision requests to AM:

The PolicyEnforcementFilter uses the returned resource URL to identify the policy decision in the policy cache.

When a request matches a cached policy decision, IG can reuse the decision without asking AM for a new decision. When caching is disabled, IG must ask AM to make a decision for each request.

Default: RequestResourceUriProvider configured to use the request URI with all query parameters included.

Maximize the cache hit ratio by managing the returned resource URL in conjuction with AM policies.

Strip all query parameters from the returned resource URL

Consider the following AM policy that matches requests on the specified path. The policy ignores query parameters:

http://ig.example.com:8080/app

The following requests match the path but have additional query parameters:

http://ig.example.com:8080/app?day=monday
http://ig.example.com:8080/app?day=monday&place=london
http://ig.example.com:8080/app?day=monday&place=london&building=x

When includeQueryParams in RequestResourceUriProvider is true, the ResourceUriProvider includes all query parameters in requests for policy decisions. The PolicyEnforcementFilter requests a policy desicion for the first request /app?day=monday and caches the descision. The second request app?day=monday&place=london doesn’t match the cached decision so the PolicyEnforcementFilter requests another policy decision and adds it to the cache. Similarly for the third request.

When includeQueryParams in RequestResourceUriProvider is false, the ResourceUriProvider strips all query parameters from the requests. The PolicyEnforcementFilter requests a policy decision for the first request without query parameters and caches the policy desicion. The following two requests without query parameters match the cached decision and IG uses the cached decision without consulting AM.

Include only specified query parameters in the returned resource URL

Consider a similar example where an AM policy matches requests on the specified path but also requires one query parameter:

http//ig.example.com:8080/app?day=monday

The following requests match the path and query parameter but two of them have additional query parameters:

http://ig.example.com:8080/app?day=monday
http://ig.example.com:8080/app?day=monday&place=london
http://ig.example.com:8080/app?day=monday&place=london&building=x

Because the policy requires a query parameter, you can’t use RequestResourceUriProvider to strip all query parameters from the requests.

Instead, use ScriptableResourceUriProvider to include the ?day=monday query parameter but strip all other query parameters.

Query order is important. The following queries are semantically the same but don’t match: ?day=monday&place=london and ?place=london&day=monday.
"resourceUriProvider": {
  "type": "ScriptableResourceUriProvider",
  "config": {
    "type": "application/x-groovy",
    "source": [
      // Define a list of paramaeters to keep
        def keepOnly = { [ "place", "day" ].contains(it.key) }
      // Build a new URI based on the original request URI
      return new MutableUri(request.uri).with { uri ->
        // Build a filtered and normalized query string
        uri.rawQuery = new Form().with { form ->
          // Keep only the wanted parameters and sort by name
          form.addAll(request.queryParams.findAll(keepOnly).sort())
          return form.toQueryString()
        }
        // Return the full modified URI
        return uri.toASCIIString()
      }
    ]
  }
}
authenticateResponseRequestHeader: configuration expression<string>, optional

A header to include in a request to manage the way IG handles policy advices from AM. The header name and value is case-insensitive. The header value can be set as follows:

  • HEADER: Return policy advices in a WWW-Authenticate header as base64-encoded JSON in a parameter called advices.

  • Any other value: Return policy advices as parameters in a redirect response (default).

For information about how the header is used in policy enforcement, refer to Deny requests with advices in a header.

Default: x-authenticate-response

useLegacyAdviceEncoding: configuration expression<boolean>, optional
The use of this property is deprecated and should be used only to support SDK in legacy installations. Refer to the Deprecated section of the Release Notes.
  • True: Do not encode advices

  • False: Encode advices with the encoder used by the AM version

Default: False

Examples

For examples of policy enforcement, refer to Policy enforcement.

PrivateKeyJwtClientAuthenticationFilter

Supports client authentication with the private_key_jwt client-assertion, using an unencrypted JWT.

Clients send a signed JWT to the Authorization Server. IG builds and signs the JWT, and prepares the request as in the following example:

POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=...&
client_id=<clientregistration_id>&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=PHNhbWxwOl ... ZT

Use this filter with an endpoint handler that requires authentication with the with the private_key_jwt client-assertion, using an unencrypted JWT. For example, the endpointHandler handler in the OAuth2TokenExchangeFilter.

Usage

{
  "name": string,
  "type": "PrivateKeyJwtClientAuthenticationFilter",
  "config": {
    "clientId": configuration expression<string>,
    "tokenEndpoint": configuration expression<url>,
    "secretsProvider": SecretsProvider reference,
    "signingSecretId": configuration expression<secret-id>,
    "signingAlgorithm": configuration expression<string>,
    "jwtExpirationTimeout": configuration expression<duration>,
    "claims": map or configuration expression<map>
  }
}

Configuration

"clientId": configuration expression<string>, required

The client_id obtained when registering with the Authorization Server.

"tokenEndpoint": configuration expression<url>, required

The URL to the Authorization Server’s OAuth 2.0 token endpoint.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to resolve queried secrets, such as passwords and cryptographic keys. For allowed formats, refer to SecretsProvider.

"signingSecretId": configuration expression<string>, required

Reference to the keys used to sign the JWT.

This secret ID must point to a CryptoKey.

"signingAlgorithm": configuration expression<string>, optional

The JSON Web Algorithm (JWA) used to sign the JWT, such as:

  • RS256: RSA using SHA-256

  • ES256: ECDSA with SHA-256 and NIST standard P-256 elliptic curve

  • ES384: ECDSA with SHA-384 and NIST standard P-384 elliptic curve

  • ES512: ECDSA with SHA-512 and NIST standard P-521 elliptic curve

Default: RS256

"jwtExpirationTimeout": configuration expression<duration>, optional

The duration for which the JWT is valid.

Default: 1 minute

"claims": map or configuration expression<map>, optional

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

  • The key is the name of a claim used in authentication

  • The value is the value of the claim, or a configuration expression that evaluates to the value

The following formats are allowed:

{
  "args": {
    "string": "configuration expression<string>",
    ...
  }
}
{
  "args": "configuration expression<map>"
}

Default: Empty

ResourceOwnerOAuth2ClientFilter

This filter uses the Resource Owner Password Credentials grant type. According to information in the The OAuth 2.0 Authorization Framework, minimize use of this grant type and utilize other grant types whenever possible. Use this filter in a service-to-service context, where services need to access resources protected by OAuth 2.0.

Authenticates OAuth 2.0 clients by using the resource owner’s OAuth 2.0 credentials to obtain an access token from an Authorization Server, and injecting the access token into the inbound request as a Bearer Authorization header.

Client authentication is provided by the endpointHandler property, which uses a client authentication filter.

The ResourceOwnerOAuth2ClientFilter refreshes the access token as required.

For more information, refer to RFC 6749 - Resource Owner Password Grant.

Usage

{
  "name": string,
  "type": "ResourceOwnerOAuth2ClientFilter",
  "config": {
    "username": configuration expression<string>,
    "passwordSecretId": configuration expression<secret-id>,
    "secretsProvider": SecretsProvider reference,
    "tokenEndpoint": configuration expression<url>,
    "scopes": [ configuration expression<string>, ... ],
    "endpointHandler": Handler reference
  }
}

Properties

"username": configuration expression<string>, required

The resource owner username to supply during authentication.

"passwordSecretId": configuration expression<secret-id>, required

The secret ID to obtain the resource owner password.

This secret ID must point to a GenericSecret.

"secretsProvider": SecretsProvider reference, required

The SecretsProvider to resolve queried secrets, such as passwords and cryptographic keys. For allowed formats, refer to SecretsProvider.

"tokenEndpoint": configuration expression<url>, required

The URL to the Authorization Server’s OAuth 2.0 token endpoint.

"scopes": array of configuration expression<strings>, optional

Array of scope strings to request from the Authorization Server.

Default: Empty, request no scopes.

"endpointHandler": Handler reference, optional

The Handler to exchange tokens on the authorization endpoint.

Configure this property as a Chain, using one of the following client authentication filters:

{
  "name": "myHandler",
  "type": "Chain",
  "config": {
    "handler": "ForgeRockClientHandler",
    "filters": [
      {
        "type": "ClientSecretBasicAuthenticationFilter",
        "config": {
          "clientId": "myConfidentialClient",
          "clientSecretId": "my.client.secret.id",
          "secretsProvider" : "mySystemAndEnvSecretStore",
        }
      }
    ]
  }
}

Default: ForgeRockClientHandler

Examples

SamlFederationFilter

Initiates the login or logout of a SAML 2.0 Service Provider (SP) with a SAML 2.0 Identity Provider (IDP). Login is initiated for requests that don’t:

  • Trigger a logout expression

  • Match a SAML endpoint

  • Include a valid session

Requests with a valid session are passed along the chain.

Usage

{
  "name": string,
  "type": "SamlFederationFilter",
  "config": {
    "redirectURI": configuration expression<url>,
    "assertionMapping": map or configuration expression<map>,
    "subjectMapping": configuration expression<string>,
    "sessionIndexMapping": configuration expression<string>,
    "authnContext": configuration expression<string>,
    "authnContextDelimiter": configuration expression<string>,
    "assertionConsumerEndpoint": configuration expression<url>,
    "SPinitiatedSSOEndpoint": configuration expression<url>,
    "SPinitiatedSLOEndpoint": configuration expression<url>,
    "singleLogoutEndpoint": configuration expression<url>,
    "singleLogoutEndpointSoap": configuration expression<url>,
    "useOriginalUri": configuration expression<boolean>,
    "logoutExpression": runtime expression<boolean>,
    "logoutURI": configuration expression<url>,
    "redirectionMarker": object,
    "secretsProvider": SecretsProvider reference,
    "spEntityId": configuration expression<string>,
    "failureHandler": Handler reference
  }
}

Properties

"redirectURI": configuration expression<url>, required

The URI to use if there is no RelayState value.

"assertionMapping": 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:

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

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

{
  "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.

"subjectMapping": configuration expression<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": "vtO…​zuL".

Default: map to session.subjectName

"sessionIndexMapping": configuration expression<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": "s24c…​801".

Default: map to session.sessionIndex

"authnContext": configuration expression<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>, optional

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

Default: |

"assertionConsumerEndpoint": configuration expression<string>, optional

Part of the URI that designates the consumer endpoint as defined in the SP metadata shared with the IDP.

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

Default: fedletapplication

"SPinitiatedSSOEndpoint": configuration expression<string>, optional

Part of the URI that designates the SP initiated SSO endpoint.

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

Default: SPInitiatedSSO

"SPinitiatedSLOEndpoint": configuration expression<string>, optional

Part of the URI that designates the SP initiated SLO endpoint.

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

Default: SPInitiatedSLO

"singleLogoutEndpoint": configuration expression<string>, optional

Part of the URI that designates the SP SLO endpoint as defined in the SP metadata shared with the IDP.

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

Default: fedletSLORedirect (same as the Fedlet)

"singleLogoutEndpointSoap": configuration expression<string>, optional

Part of the URI that designates the SP SLO SOAP endpoint as defined in the SPs metadata shared with the IDP.

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

Default: fedletSloSoap (same as the Fedlet)

"useOriginalUri": configuration expression<boolean>, optional

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

Default: true

"logoutExpression": runtime expression<boolean>, optional

A flag to indicate whether a request initiates logout processing before reaching the protected application.

  • false: The request does not initiate logout processing:

    • If a valid SAML session is found, the request is forwarded to the protected application.

    • If a valid SAML session is not found, the request triggers the SAML login flow.

  • true: The request initiates logout processing:

    • If a valid SAML session is found, the request triggers the SAML logout flow:

      • If there is a RelayState URL parameter, the request is forwarded to that URL. RelayState provides backwards compatibility for SamlFederationHandler.

      • If there is no RelayState URL parameter and logoutURI is defined, the request is forwarded to the logout page.

      • If there is no RelayState URL parameter and logoutURI is not defined, the request is forwarded to the protected application without any other validation.

    • If a valid session is not found, the request is forwarded to the protected application without any other validation.

To prevent unwanted access to the protected application, use logoutExpression with extreme caution as follows:

  • Define a logoutURI.

  • If you don’t define a logoutURI, specify logoutExpression to resolve to true only for requests that target dedicated logout pages of the protected application.

Consider the following examples when a logoutURI is not defined:

  • This expression resolves to true only for requests with /app/logout in their path:

    "logoutExpression": "${startsWith(request.uri.rawPath, '/app/logout')}"

    When a request matches the expression, the SAML session is revoked and the request is forwarded to the /app/logout page.

  • This expression resolves to true for all requests that contain logOff=true in their query parameters:

    "logoutExpression": "${find(request.uri.query, 'logOff=true')}"

    When a request matches the expression, the SAML session is revoked and the request is forwarded to the protected application without any other validation. In this example, an attacker can bypass IG’s security mechanisms by simply adding ?logOff=true to a request.

Default: ${false}

"logoutURI": configuration expression<string>, optional

The URL to which a request is redirected if logoutExpression is evaluated as true or when the protected application uses the single logout feature of the Identity Provider.

Default: None, processing continues.

"redirectionMarker": configuration expression<object>, optional

A redirect marker for the SAML flow. If the marker is present in the flow, the request isn’t redirected for authentication.

This feature is on by default to prevent redirect loops when the session cookie isn’t present in the SAML flow. The cookie can be absent from the flow if it doesn’t include IG’s domain.

"redirectionMarker": {
  "enabled": configuration expression<boolean>,
  "name": configuration expression<string>
}
"enabled": configuration expression<boolean>, optional
  • true: When the session is empty or invalid, IG checks the request goto query parameter for the presence of the redirection marker:

    • If the redirection marker is present, IG fails the request.

    • If the redirection marker isn’t present, IG redirects the user agent for login.

  • false: IG never checks the request goto query parameter for the presence of a redirection marker.

Default: true

"name": configuration expression<string>, optional

The name of the redirection marker query parameter to use when enabled is true.

Default: _ig

"secretsProvider": SecretsProvider 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.

"spEntityId": configuration expression<string>, optional

The entity ID that this SP represents. Configure this property when more than one SP is defined in the metadata.

Default:

  • When no SPs are defined in the metadata an error is generated.

  • When there one SP defined in the metadata the filter uses that SP.

  • When there is more than one SP defined in the metadata the filter uses the first SP in the list of discovered metadata and logs a warning. Because ordering is not deterministic, the discovered SP can be the wrong SP.

"failureHandler": Handler reference, optional

Handler to invoke when SAML processing fails.

Provide an inline handler configuration object or the name of a handler object declared in the heap. See also Handlers.

Default: Return an error response containing a SAML processing error.

ScriptableFilter

Processes requests and responses by executing a Groovy script. Executed scripts must return one of the following:

To execute the next element in a chain (a filter or a handler), the script must call the expression next.handle(context, request). If the script does not call next.handle(context, request), the chain flow breaks and the script has to build and return its own response by calling one of the following expressions:

  • return myResponse

  • return newResultPromise(myResponse)

Actions on the response returned from the downstream flow must be performed in the Promise’s callback methods.

For information about script properties, available global objects, and automatically imported classes, refer to Scripts. For information about creating scriptable objects in Studio, refer to Scripts in Studio and Configure scriptable throttling.

Usage

{
    "name": string,
    "type": "ScriptableFilter",
    "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 ScriptableFilter, refer to Scripts.

Examples

For an example scriptable filter that recovers policy advices from AM, see the failureHandler property of PolicyEnforcementFilter.

SessionInfoFilter

Calls the AM endpoint for session information, and makes the data available as a new context to downstream IG filters and handlers. For information, refer to SessionInfoContext.

WebSocket notifications for sessions

When WebSocket notifications are set up for sessions, IG receives a notification from AM when a user logs out of AM, or when the AM session is modified, closed, or times out. IG then evicts entries that are related to the event from the sessionCache.

For information about setting up WebSocket notifications, using them to clear the session cache, and including them in the server logs, refer to WebSocket notifications.

Usage

{
  "name": string,
  "type": "SessionInfoFilter",
  "config": {
    "amService": AmService reference,
    "ssoToken": runtime expression<string>
  }
}

Properties

"amService": AmService reference, required

The AmService object to use for communication with AM.

The following sessionProperties, are retrieved from AM:

  • When sessionProperties in AmService is configured, listed session properties with a value.

  • When sessionProperties in AmService is not configured, all session properties with a value.

  • Properties with a value that are required by IG but not specified by sessionProperties in AmService. For example, when the session cache is enabled, session properties related to the cache are automatically retrieved.

Properties with a value are returned, properties with a null value are not returned.

"ssoToken": runtime expression<string>, optional

Location of the AM SSO or CDSSO token.

This property can take the following values:

  • ${contexts.ssoToken.value}, when the SingleSignOnFilter is used for authentication

  • ${contexts.ssoToken.value} or ${contexts.cdsso.token}, when the CrossDomainSingleSignOnFilter is used for authentication

  • ${request.headers['mySsoToken'][0]}, where the SSO or CDSSO token is the first value of the mySsoToken header in the request.

Default: ${request.cookies['AmService-ssoTokenHeader'][0].value}, where AmService-ssoTokenHeader is the name of the header or cookie where the AmService expects to find SSO or CDSSO tokens.

Examples

For an example that uses the SessionInfoFilter, refer to Retrieve a Username From the sessionInfo Context.

SetCookieUpdateFilter

Updates the attribute values of Set-Cookie headers in a cookie. This filter facilitates the transition to the SameSite and secure cookie settings required by newer browsers. Use SetCookieUpdateFilter at the beginning of a chain to guarantee security along the chain.

Set-Cookie headers must conform to grammar in RFC 6265: Set-Cookie.

Usage

{
  "name": string,
  "type": "SetCookieUpdateFilter",
  "config": {
   "cookies": {
     "cookie-name": {
       "attribute-name": "attribute-value",
       ...
     }
     ...
   }
 }
}

Properties

"cookies": map, required

Configuration that matches case-sensitive cookie names to response cookies, and specifies how matching cookies attribute values should be updated. Each cookie begins with a name-value pair, where the value is one or more attribute-value pairs.

cookie-name: pattern, required

The name of a cookie contained in the Set-Cookie header, as a pattern.

To change the attribute value on all existing cookies, specify .*.

If a cookie is named more than once, either explicitly or by the wildcard (*), the rules are applied to the cookie in the order they appear in the map.

In the following example, the SameSite attribute of the CSRF cookie first takes the value none, and then that value is overwritten by the value LAX.

"cookies": {
  "CSRF": {
    "value": "myValue",
    "secure": ${true},
    "SameSite": "none"
  }
  ".*": {
    "SameSite": "LAX"
  }
}
attribute-name: enumeration, required

A case-insensitive enumeration of a Set-Cookie attribute name.

Attribute names include SameSite, secure, http-only, value, expires, Max-Age, path, and domain. For more information, refer to RFC 6265: Set-Cookie.

Use the now dynamic binding to dynamically set the value of a cookie attribute that represents time. For example, set the value of the attribute expires to one day after the expression is evaluated, as follows:

{
  "type": "SetCookieUpdateFilter",
    "config": {
      "cookies": {
        ".*": {
          "expires": "${now.plusDays(1).rfc1123}",
...
attribute-value: runtime expression<string, boolean, or integer>, required

The replacement value for the named attribute. The value must conform to the expected type for the attribute name:

  • secure: runtime expression<boolean>. Required if SameSite is none

  • http-only: runtime expression<boolean>.

  • Max-Age: runtime expression<number>.

  • SameSite, and all other attribute names: runtime expression<string>.

For all values except expires, specify ${previous} to reuse the existing value for the attribute. The following example adds five seconds to the Max-Age attribute:

"Max-Age": "${integer(previous+5)}",

If the named the Set-Cookie header doesn’t contain the named attribute, ${previous} returns null.

Examples

The following example updates attributes of all existing Set-Cookie headers:

{
  "name": "SetCookieUpdateFilter",
  "condition": "${find(request.uri.path, '/home')}",
  "baseURI": "http://app.example.com:8081",
  "heap": [],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [{
        "type": "SetCookieUpdateFilter",
        "config": {
          "cookies": {
            ".*": {
              "SameSite": "LAX",
              "domain": "ig.example.com",
              "Max-Age": "${session.maxAge}",
              "Secure": "${true}",
              "expires": 155...833
            }
          }
        }
      }],
      "handler": "ReverseProxyHandler"
    }
  }
}

SingleSignOnFilter

When this filter processes a request, it injects the SSO token, the session user ID, and the full claims set into the SsoTokenContext.

For an example of how to configure SSO and information about the SSO data flow, refer to Single sign-on.

To prevent issues with performance when accessing large resources, such as .jpg and .js files, consider using the SingleSignOnFilter with the following options:

  • The sessionCache, so that IG can reuse session token information without repeatedly asking AM to verify the session token.

  • A ConditionalFilter, so that requests to access large resources skip the SingleSignOnFilter. For an example configuration, see the example in ConditionalFilter.

When AM is using CTS-based sessions, it does not monitor idle time for client-side sessions, and so refresh requests are ignored.

When the SingleSignOnFilter is used for authentication with AM, after a time AM can view the session as idle even though the user continues to interact with IG. The user session can eventually time out.

(From AM 6.5.3.) When AM is using CTS-based sessions, use the sessionIdleRefresh property of AmService to refresh idle sessions, and prevent unwanted timeouts.

WebSocket notifications for sessions

When WebSocket notifications are set up for sessions, IG receives a notification from AM when a user logs out of AM, or when the AM session is modified, closed, or times out. IG then evicts entries that are related to the event from the sessionCache.

For information about setting up WebSocket notifications, using them to clear the session cache, and including them in the server logs, refer to WebSocket notifications.

Usage

{
  "name": string,
  "type": "SingleSignOnFilter",
    "config": {
      "amService": AmService reference,
      "authenticationService": configuration expression<string>,
      "redirectionMarker": object,
      "realm": configuration expression<string>,
      "defaultLogoutLandingPage": configuration expression<url>,
      "loginEndpoint": runtime expression<url>,
      "logoutExpression": runtime expression<boolean>,
      "logoutEndpoint": pattern //deprecated
  }
}

Properties

"amService": AmService reference, required

An AmService object to use for the following properties:

  • agent, the credentials of the IG agent in AM. When the agent is authenticated, the token can be used for tasks such as getting the user’s profile, making policy evaluations, and connecting to the AM notification endpoint.

  • realm: Realm of the IG agent in AM.

  • url, the URL of an AM service to use for session token validation and authentication when loginEndpoint is not specified.

  • ssoTokenHeader, the name of the cookie that contains the session token created by AM.

  • amHandler, the handler to use when communicating with AM to validate the token in the incoming request.

  • sessionCache, the configuration of a cache for session information from AM.

  • version: The version of the AM server.

    The AM version is derived as follows, in order of precedence:

    • Discovered value: AmService discovers the AM version. If version is configured with a different value, AmService ignores the value of version and issues a warning.

    • Value in version: AmService cannot discover the AM version, and version is configured.

    • Default value of AM 6: AmService cannot discover the AM version, and version is not configured.

redirectionMarker: object, optional

A redirect marker for the SSO flow. If the marker is present in the SSO flow, the request isn’t redirected for authentication.

This feature is on by default to prevent redirect loops when the session cookie isn’t present in the SSO flow. The cookie can be absent from the flow if it doesn’t include IG’s domain.

"redirectionMarker": {
  "enabled": configuration expression<boolean>,
  "name": configuration expression<string>
}
"enabled": configuration expression<boolean>, optional
  • true: When the session is empty or invalid, IG checks the request goto query parameter for the presence of the redirection marker:

    • If the redirection marker is present, IG fails the request.

    • If the redirection marker isn’t present, IG redirects the user agent for login.

  • false: IG never checks the request goto query parameter for the presence of a redirection marker.

Default: true

"name": configuration expression<string>, optional

The name of the redirection marker query parameter to use when enabled is true.

Default: _ig

"authenticationService": configuration expression<string>,optional

The name of an AM authentication tree or authentication chain to use for authentication.

Use only authentication trees with ForgeRock Identity Cloud. Authentication modules and chains are not supported.

Default: AM’s default authentication tree.

For more information about authentication trees and chains, refer to Authentication nodes and trees and Authentication modules and chains in AM’s Authentication and SSO guide.

"realm": configuration expression<string>, optional

The AM realm where the user is authenticated.

Default: The realm declared for amService.

"defaultLogoutLandingPage": configuration expression<url>, optional

The URL to which a request is redirected if logoutExpression is evaluated as true.

If this property is not an absolute URL, the request is redirected to the IG domain name.

This parameter is effective only when logoutExpression is specified.

Default: None, processing continues.

"loginEndpoint": runtime expression<url>, optional

The URL of a service instance for the following tasks:

  • Manage authentication and the location to which the request is redirected after authentication.

  • Process policy advices after an AM policy decision denies a request with supported advices. The PolicyEnforcementFilter redirects the request to this URL, with information about how to meet the conditions in the advices.

    For examples of different advice types, and the conditions that cause AM to return advices, see AM’s Authorization guide. For information about supported advice types in IG, refer to PolicyEnforcementFilter.

    Default: The value of url in amService

Authentication can be performed in the following ways:

  • Directly through AM, with optional authentication parameters in the query string, such as service, module, and realm. For a list of authentication parameters that you can include in the query string, see Authenticating (browser) in AM’s Authentication and SSO guide.

    The value must include a redirect with a goto parameter.

    The following example uses AM as the authentication service, and includes the service authentication parameter:

    "loginEndpoint": "https://am.example.com/openam?service=TwoFactor&goto=${urlEncodeQueryParameterNameOrValue(contexts.router.originalUri)}"
  • Through the URL of another application, with optional authentication parameters in the query string, such as service, module, and realm. The application must create a session with an AM instance to set an SSO token and return the request to the redirect location.

    The value can optionally include a redirect with a goto parameter or different parameter name.

    The following example uses an authentication service that is not AM, and includes a redirect parameter:

    "loginEndpoint": "https://authservice.example.com/auth?redirect=${urlEncodeQueryParameterNameOrValue(contexts.router.originalUri)}"

    When using this option, review the cookie domains to make sure cookies set by the authentication server are properly conveyed to the IG instance.

"logoutExpression": runtime expression<boolean>, optional

A flag to indicate whether a request initiates logout processing before reaching the protected application.

  • false: The request does not initiate logout processing:

    • If a valid AM session is found, the request is forwarded to the protected application.

    • If a valid AM session is not found, the request triggers login.

  • true: The request initiates logout processing:

    • If a valid AM session is found, the session is revoked and the request is forwarded as follows:

      • If defaultLogoutLandingPage is defined, the request is forwarded to the specified logout page.

      • If defaultLogoutLandingPage is not defined, the request is forwarded to the protected application without any other validation.

    • If a valid session is not found, the request is forwarded to the protected application without any other validation.

To prevent unwanted access to the protected application, use logoutExpression with extreme caution as follows:

  • Define a defaultLogoutLandingPage.

  • If you don’t define a defaultLogoutLandingPage, specify logoutExpression to resolve to true only for requests that target dedicated logout pages of the protected application.

Consider the following examples when a defaultLogoutLandingPage is not configured:

  • This expression resolves to true only for requests with /app/logout in their path:

    "logoutExpression": ${startsWith(request.uri.rawPath, '/app/logout')}

    When a request matches the expression, the AM session is revoked and the request is forwarded to the /app/logout page.

  • This expression resolves to true for all requests that contain logOff=true in their query parameters:

    "logoutExpression": ${find(request.uri.query, 'logOff=true')}

    When a request matches the expression, the AM session is revoked and the request is forwarded to the protected application without any other validation. In this example, an attacker can bypass IG’s security mechanisms by simply adding ?logOff=true to a request.

Default: ${false}

"logoutEndpoint": pattern, optional
The use of this property is deprecated; use logoutExpression instead. For more information, refer to the Deprecated section of the Release Notes.

A string denoting a regular expression pattern for a URL. When a request matches the pattern, IG performs the logout process and the AM authentication token for the end user is revoked.

If a defaultLogoutLandingPage is specified, the request is redirected to that page. Otherwise, the request continues to be processed.

Default: Logout is not managed by this filter.

SqlAttributesFilter

This filter uses synchronous architecture. Accessing the filter target triggers a call to the database that blocks the executing thread until the database responds.

Consider the performance impact of this filter, especially for deployments with a small number of gateway units (therefore, a small number of executing threads) and a long execution time for the JDBC call.

Executes a SQL query through a prepared statement and exposes its first result. Parameters in the prepared statement are derived from expressions. The query result is exposed in an object whose location is specified by the target expression. If the query yields no result, then the resulting object is empty.

The execution of the query is performed lazily; it does not occur until the first attempt to access a value in the target. This defers the overhead of connection pool, network and database query processing until a value is first required. This also means that the parameters expressions is not evaluated until the object is first accessed.

Usage

{
  "name": string,
  "type": "SqlAttributesFilter",
   "config": {
     "dataSource": JdbcDataSource reference,
     "preparedStatement": configuration expression<string>,
     "parameters": [ runtime expression<string>, ... ],
     "target": lvalue-expression
   }
}

Properties

"dataSource": JdbcDataSource reference, required
dataSource as a JNDI lookup name is deprecated; use dataSource as a JdbcDataSource configuration object instead. For more information, refer to the Deprecated section of the Release Notes.

The JdbcDataSource to use for connections. Configure JdbcDataSource as described in JdbcDataSource.

"preparedStatement": configuration expression<string>, required

The parameterized SQL query to execute, with ? parameter placeholders.

"parameters": array of runtime expressions<strings>, optional

The parameters to evaluate and include in the execution of the prepared statement.

See also Expressions.

"target": <lvalue-expression>, required

Expression that yields the target object containing the query results. For example, ${target.sql.queryresult}.

Access to target triggers a call to the database that blocks the executing thread until the database responds.

See also Expressions.

Example

Using the user’s session ID from a cookie, query the database to find the user logged in and set the profile attributes in the attributes context:

{
        "name": "SqlAttributesFilter",
        "type": "SqlAttributesFilter",
        "config": {
              "target": "${attributes.sql}",
              "dataSource": "java:comp/env/jdbc/mysql",
              "preparedStatement": "SELECT f.value AS 'first', l.value AS 'last', u.mail AS 'email', GROUP_CONCAT(CAST(r.rid AS CHAR)) AS 'roles' FROM sessions s INNER JOIN users u ON ( u.uid = s.uid AND u.status = 1 ) LEFT OUTER JOIN profile_values f ON ( f.uid = u.uid AND f.fid = 1 ) LEFT OUTER JOIN profile_values l ON ( l.uid = u.uid AND l.fid = 2 ) LEFT OUTER JOIN users_roles r ON ( r.uid = u.uid ) WHERE (s.sid = ? AND s.uid <> 0) GROUP BY s.sid;",
              "parameters": [ "${request.cookies[keyMatch(request.cookies,'JSESSION1234')][0].value}" ]
         }
 }

Lines are folded for readability in this example. In your JSON, keep the values for "preparedStatement" and "parameters" on one line.

StaticRequestFilter

Creates a new request, replacing any existing request. The request can include an entity specified in the entity parameter. Alternatively, the request can include a form, specified in the form parameter, which is included in an entity encoded in application/x-www-form-urlencoded format if request method is POST, or otherwise as (additional) query parameters in the URI. The form and entity parameters cannot be used together when the method is set to POST.

Usage

{
  "name": string,
  "type": "StaticRequestFilter",
  "config": {
    "method": configuration expression<string>,
    "uri": runtime expression<url>,
    "version": configuration expression<string>,
    "headers": {
      configuration expression<string>: [ runtime expression<string>, ... ], ...
    },
    "form": {
      configuration expression<string>: [ runtime expression<string>, ... ], ...
    },
    "entity": runtime expression<string>
  }
}

Properties

"method": configuration expression<string>, required

The HTTP method to be performed on the resource; for example, GET.

"uri": runtime expression<url>, required

The fully-qualified URI of the resource being accessed; for example, http://www.example.com/resource.txt.

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 mutable URI.

"version": configuration expression<string>, optional

Protocol version.

Default: "HTTP/1.1"

"headers": map, optional

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

  • name is a configuration expression<string> that resolve to a header name. If multiple expressions resolve to the same final string, name has multiple values.

  • value is one or more runtime expression<strings> that resolve to header values.

In the following example, the header name is the value of the system variable defined in cookieHeaderName. The header value is stored in contexts.ssoToken.value:

"headers": {
  "${application['header1Name']}": [
    "${application['header1Value'}"
  ]
}

Default: Empty

"form": map, optional

A form to include in the request and/or application/x-www-form-urlencoded entity, as name-value pairs, where:

  • name is a configuration expression<string> that resolves to a form parameter name.

  • value is one or more runtime expression<strings> that resolve to form parameter values.

When a Request method is POST, form is mutually exclusive with entity.

Examples:

  • In the following example, the field parameter names and values are hardcoded in the form:

    "form": {
      "username": [
        "demo"
      ],
      "password": [
        "password"
      ]
    }
  • In the following example, the values take the first value of username and password provided in the session:

    "form": {
      "username": [
        "${session.username[0]}"
      ],
      "password": [
        "${session.password[0]}"
      ]
    }
  • In the following example, the name of the first field parameter takes the value of the expression ${application['formName']} when it is evaluated at startup. The values take the first value of username and password provided in the session:

    "form": {
      "${application['formName']}": [
        "${session.username[0]}"
      ],
      "${application['formPassword']}": [
        "${session.password[0]}"
      ]
    }

    Default: Empty

"entity": runtime expression<string>, optional

The message entity body to include in a request.

When a Request method is POST, entity is mutually exclusive with form.

Methods are provided for accessing the entity as byte, string, or JSON content. For information, refer to Entity.

Attackers during reconnaissance can use 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

In the following example, IG replaces the browser’s original HTTP GET request with an HTTP POST login request containing credentials to authenticate to the sample application. For information about how to set up and test this example, refer to the Quick install.

{
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "StaticRequestFilter",
          "config": {
            "method": "POST",
            "uri": "http://app.example.com:8081/login",
            "form": {
              "username": [
                "demo"
              ],
              "password": [
                "Ch4ng31t"
              ]
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  },
  "condition": "${find(request.uri.path, '^/static')}"
}

SwitchFilter

Verifies that a specified condition is met. If the condition is met or no condition is specified, the request is diverted to the associated handler, with no further processing by the switch filter.

Usage

{
    "name": string,
    "type": "SwitchFilter",
    "config": {
        "onRequest": [
            {
                "condition": runtime expression<boolean>,
                "handler": Handler reference
            },
            ...
        ],
        "onResponse": [
            {
                "condition": runtime expression<boolean>,
                "handler": Handler reference
            },
            ...
        ]
    }
}

Properties

"onRequest": array of objects, optional

Conditions to test (and handler to dispatch to, if true) before the request is handled.

"onResponse": array of objects, optional

Conditions to test (and handler to dispatch to, if true) after the response is handled.

"condition": runtime expression<boolean>, optional

A flag to indicate that a condition is met:

  • true: The request is dispatched to the handler.

  • false: The request is not dispatched to the handler, and the next condition in the list is tried.

    When the last condition in the list returns false, the request is passed to the next filter or handler in the chain.

Default: ${true}

"handler": Handler 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.

Example

This example intercepts the response if it is equal to 200 and executes the LoginRequestHandler. This filter might be used in a login flow where the request for the login page must go through to the target, but the response should be intercepted in order to send the login form to the application. This is typical for scenarios where there is a hidden value or cookie returned in the login page, which must be sent in the login form:

{
    "name": "SwitchFilter",
    "type": "SwitchFilter",
    "config": {
        "onResponse": [
            {
                "condition": "${response.status.code == 200}",
                "handler": "LoginRequestHandler"
            }
        ]
    }
}

ThrottlingFilter

Limits the rate that requests pass through a filter. The maximum number of requests that a client is allowed to make in a defined time is called the throttling rate.

When the throttling rate is reached, IG issues an HTTP status code 429 Too Many Requests and a Retry-After header, whose value is rounded up to the number of seconds to wait before trying the request again.

GET http://ig.example.com:8080/home/throttle-scriptable HTTP/1.1
. . .
HTTP/1.1 429 Too Many Requests
Retry-After: 10

Usage

{
    "name": string,
    "type": "ThrottlingFilter",
    "config": {
        "requestGroupingPolicy": runtime expression<string>,
        "throttlingRatePolicy": ThrottlingPolicy reference,  //Use either "throttlingRatePolicy"
        "rate": {                                            //or "rate", but not both.
            "numberOfRequests": configuration expression<number>,
            "duration": configuration expression<duration>
        },
        "cleaningInterval": configuration expression<duration>,
        "executor": ScheduledExecutorService reference
    }
}

Properties

"requestGroupingPolicy": runtime expression<string>, optional

An expression to identify the partition to use for the request. In many cases the partition identifies an individual client that sends requests, but it can also identify a group that sends requests. The expression can evaluate to the client IP address or user ID, or an OpenID Connect subject/issuer.

The value for this expression must not be null.

Default: Empty string; all requests share the same partition

See also Expressions.

"throttlingRatePolicy": ThrottlingPolicy reference, required if rate is not used

A reference to, or inline declaration of, a policy to apply for throttling rate. The following policies can be used:

This value for this parameter must not be null.

"rate": object, required if throttlingRatePolicy is not used

The throttling rate to apply to requests. The rate is calculated as the number of requests divided by the duration:

"numberOfRequests": configuration expression<integer>, required

The number of requests allowed through the filter in the time specified by "duration".

"duration": configuration expression<duration>, required

A time interval during which the number of requests passing through the filter is counted.

"cleaningInterval": configuration expression<duration>, optional

The time to wait before cleaning outdated partitions. The value must be more than zero but not more than one day.

"executor": ScheduledExecutorService reference, optional

An executor service to schedule the execution of tasks, such as the clean up of partitions that are no longer used.

Default: ScheduledExecutorService

Examples

The following route defines a throttling rate of 6 requests/10 seconds to requests. For information about how to set up and test this example, refer to Configure Simple Throttling.

{
  "name": "00-throttle-simple",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/throttle-simple')}",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "ThrottlingFilter",
          "name": "ThrottlingFilter-1",
          "config": {
            "requestGroupingPolicy": "",
            "rate": {
              "numberOfRequests": 6,
              "duration": "10 s"
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

TokenTransformationFilter

Transforms a token issued by AM to another token type.

The TokenTransformationFilter makes the result of the token transformation

available to downstream handlers in the sts context. For information, refer to StsContext.

The current implementation uses REST Security Token Service (STS) APIs to transform an OpenID Connect ID Token (id_token) into a SAML 2.0 assertion. The subject confirmation method is Bearer, as described in Profiles for the OASIS Security Assertion Markup Language (SAML) V2.0 .

The TokenTransformationFilter makes the result of the token transformation available to downstream handlers in the issuedToken property of the ${contexts.sts} context.

The TokenTransformationFilter configuration references a REST STS instance that must be set up in AM before the TokenTransformationFilter can be used. The REST STS instance exposes a preconfigured transformation under a specific REST endpoint. For information about setting up a REST STS instance, see the AM documentation.

Errors that occur during the token transformation cause a error response to be returned to the client and an error message to be logged for the IG administrator.

Usage

{
    "name": "string",
    "type": "TokenTransformationFilter",
    "config": {
        "amService": AmService reference,
        "idToken": runtime expression<string>,
        "instance": configuration expression<string>,
        "username": configuration expression<string>, //deprecated
        "password": configuration expression<string>  //deprecated
    }
}

Properties

"amService": AmService reference, required

The AmService heap object to use for the following properties:

  • agent, the credentials of the IG agent in AM, to authenticate IG as an AM REST STS client, and to communicate WebSocket notifications from AM to IG. This credentials are evaluated when the route is initialized

  • url, the URL of an AM service to use for session token validation and authentication. Authentication and REST STS requests are made to this service.

  • realm, the AM realm containing the following information:

    • The AM application that can make the REST STS request and whose credentials are the username and password.

    • The STS instance described by the instance field.

  • ssoTokenHeader, the name of the HTTP header that provides the SSO token for the REST STS client subject.

  • amHandler, the handler to use for authentication and STS requests to AM.

"idToken": runtime expression<string>, required

The value of the OpenID Connect ID token. The expected value is a string that is the JWT encoded id_token.

"instance": configuration expression<string>, required

An expression evaluating to the name of the REST STS instance.

This expression is evaluated when the route is initialized, so the expression cannot refer to request or contexts.

"username": string, required
The use of this property is deprecated; use the AmService property agent instead. For more information, refer to the Deprecated section of the Release Notes.

The username to authenticate IG as an AM REST STS client.

"password": expression, required
The use of this property is deprecated; use the AmService property agent instead. For more information, refer to the Deprecated section of the Release Notes.

The password to authenticate IG as an AM REST STS client.

Example

The following example shows a configuration for a TokenTransformationFilter:

{
  "type": "TokenTransformationFilter",
  "config": {
    "amService": "MyAmService",
    "idToken": "${attributes.openid.id_token}",
    "instance": "openig"
  }
}

For an example of how to set up and test the TokenTransformationFilter, refer to Transform OpenID Connect ID tokens into SAML assertions.

TransactionIdOutboundFilter

Inserts the ID of a transaction into the header of a request.

The default TransactionIdOutboundFilter is created by IG, and used in ForgeRockClientHandler, as follows:

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

UmaFilter

This filter acts as a policy enforcement point, protecting access as a User-Managed Access (UMA) resource server. Specifically, this filter ensures that a request for protected resources includes a valid requesting party token with appropriate scopes before allowing the response to flow back to the requesting party.

Usage

{
    "name": string,
    "type": "UmaFilter",
    "config": {
        "protectionApiHandler": Handler reference,
        "umaService": UmaService reference,
        "realm": configuration expression<string>
    }
}

Properties

"protectionApiHandler": Handler reference, required

The handler to use when interacting with the UMA Authorization Server for token introspection and permission requests, such as a ClientHandler capable of making an HTTPS connection to the server.

For information, refer to Handlers.

"umaService": UmaService reference, required

The UmaService to use when protecting resources.

For information, refer to UmaService.

"realm": configuration expression<string>, optional

The UMA realm set in the response to a request for a protected resource that does not include a requesting party token enabling access to the resource.

Default: uma

UriPathRewriteFilter

Rewrite a URL path, using a bidirectional mapping:

  • In the request flow, fromPath is mapped to toPath.

  • In the response flow, toPath is mapped to fromPath.

IG overwrites a response header only when all of the following conditions are true:

  • The response includes a header such as Location or Content-Location

  • The URI of the response header matches the mapping

  • The value of response header is a relative path or its scheme://host:port value matches the base URI.

Usage

{
  "name": string,
  "type": "UriPathRewriteFilter",
  "config": {
    "mappings": object,
    "failureHandler": Handler reference
  }
}

Properties

"mappings": object, required

One or more bidirectional mappings between URL paths. For example mappings, request scenarios, and an example route, refer to Examples.

{
  "mappings": {
    "/fromPath1": "/toPath1",
    "/fromPath2": "/toPath2",
    ...
  }
}

Paths are given by a configuration expression<string>. Consider the following points when you define paths:

  • The incoming URL must start with the mapping path.

  • When more than one mapping applies to a URL, the most specific mapping is used.

  • Duplicate fromPath values are removed without warning.

  • Trailing slashes / are removed from path values.

  • If the response includes a Location or Content-Location header with a toPath in its URL, the response is rewritten with fromPath.

"failureHandler": handler reference, optional

Failure handler to be invoked if an invalid URL is produced when the request path is mapped, or when the response Location or Content-Location header URI path is reverse-mapped.

Provide an inline handler declaration, or the name of a handler object defined in the heap. See also Handlers.

Default: HTTP 500

Examples

Valid and invalid mapping examples

The following mapping examples are valid:

  • Single fromPath and toPath

    "mappings": {
      "/fromPath1": "/toPath1",
      "/fromPath2": "/toPath2"
    }
  • Expressions in the fromPath and toPath

    "mappings": {
      "/${join(array(`fromPath`, 'path1'), `/`)}": "/${join(array(`toPath`, 'path2'), `/`)}"
    }
  • Expressions in the fromPath and toPath that use predefined heap properties

    "mappings": {
      "${fromPath}": "${toPath}"
    }
  • No mappings—the configuration is valid, but has no effect

    "mappings": { }
  • Duplicate toPath

    "mappings": {
      "/fromPath1": "/toPath",
      "/fromPath2": "/toPath"
    }
  • Duplicate fromPath—the configuration is overwritten without warning

    "mappings": {
      "/fromPath": "/toPath1",
      "/fromPath": "/toPath2"
    }

The following mapping examples are not valid

  • No toPath

    "mappings": {
      "/fromPath": ""
    }
    "mappings": {
      "/fromPath": "${unknown}"
    }
  • Invalid toPath

    "mappings": {
      "/fromPath": "${invalidExpression}"
    }
  • No fromPath

    "mappings": {
      "": "/toPath"
    }
    "mappings": {
        "${unknown}": "/toPath"
    }
  • Invalid fromPath

    "mappings": {
        "${invalidExpression}": "/toPath"
    }
Example request scenarios
Description Mapping Inbound URI Rewritten URI

Basic path

"mappings": {
  "/fromPath": "/toPath"
}

http://example.com/fromPath/remainder

http://example.com/toPath/remainder

Root context, where the inbound request URI has a / path segment

"mappings": {
  "/": "/rootcontext"
}

http://example.com/

http://example.com/rootcontext/

Root context, where the inbound URI has a / path segment

"mappings": {
  "/rootcontext": "/"
}

http://example.com/rootcontext/

http://example.com/

Root context, where the inbound request URI has an empty path

"mappings": {
  "/": "/rootcontext"
}

http://example.com

http://example.com/rootcontext

Root context, where the rewritten URI has an empty path

"mappings": {
  "/rootcontext": "/"
}

http://example.com/rootcontext

http://example.com

Root context, with path remainder

"mappings": {
  "/": "/rootcontext"
}

http://example.com/remainder

http://example.com/rootcontext/remainder

Root context, with path remainder

"mappings": {
  "/rootcontext": "/"
}

http://example.com/rootcontext/remainder

http://example.com/remainder

Root context, where the trailing / on toPath is ignored

"mappings": {
  "/": "/rootcontext/"
}

http://example.com/remainder

http://example.com/rootcontext/remainder

Path with dot-segments:

"mappings": {
  "/fromPath": "/toPath1/../toPath2"
}

http://example.com/fromPath

http://example.com/toPath1/../toPath2

Path with syntax:

"mappings": {
  "/fromPath;v=1.1": "/toPath,1.1"
}

http://example.com/fromPath;v=1.1

http://example.com/toPath,1.1

Path with syntax:

"mappings": {
  "/$fromPath": "/$toPath"
}

http://example.com/$fromPath

http://example.com/$toPath

Path with query parameters

"mappings": {
  "/fromPath": "/toPath"
}

http://example.com/fromPath?param1&param2=2

http://example.com/toPath?param1&param2=2

Path with fragment

"mappings": {
  "/fromPath": "/toPath"
}

http://example.com/fromPath#fragment

http://example.com/toPath#fragment

Example route

The example route changes a request URL as follows:

  • The baseURI overrides the scheme, host, and port of a request URL.

  • The UriPathRewriteFilter remaps the path of a request URL.

    Requests to http://ig.example.com:8080/mylogin are mapped to http://app.example.com:8081/login.

    Requests to http://ig.example.com:8080/welcome are mapped to http://app.example.com:8081/home.

    Requests to http://ig.example.com:8080/other are mapped to http://app.example.com:8081/not-found, and result in an HTTP 404.

    Requests to http://ig.example.com:8080/badurl are mapped to the invalid URL http://app.example.com:8081[, and invoke the failure handler.

{
  "name": "UriPathRewriteFilter",
  "baseURI": "http://app.example.com:8081",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "UriPathRewriteFilter",
          "config": {
            "mappings": {
              "/mylogin": "/login",
              "/welcome": "/home",
              "/other": "/not-found",
              "/badurl": "["
            },
            "failureHandler": {
              "type": "StaticResponseHandler",
              "config": {
                "status": 500,
                "headers": {
                  "Content-Type": [
                    "text/plain"
                  ]
                },
                "entity": "Invalid URL produced"
              }
            }
          }
        }
      ],
      "handler": "ClientHandler"
    }
  }
}

UserProfileFilter

Queries AM to retrieve the profile attributes of an user identified by their username.

Only profile attributes that are enabled in AM can be returned by the query. The roles field is not returned.

The data is made available to downstream IG filters and handlers, in the context UserProfileContext.

Usage

{
  "name": string,
  "type": "UserProfileFilter",
  "config": {
    "username": runtime expression<string>,
    "userProfileService": UserProfileService reference
  }
}

Properties

"username": runtime expression<string>, required

The username of an AM subject. This filter retrieves profile attributes for the subject.

"userProfileService": UserProfileService reference, required

The service to retrieve profile attributes from AM, for the subject identified by username.

"userProfileService": {
  "type": "UserProfileService",
  "config": {
    "amService": AmService reference,
    "cache": object,
    "profileAttributes": [ configuration expression<string>, ... ],
    "realm": configuration expression<string>
  }
}
"amService": AmService reference, required

The AmService heap object to use for the following properties:

  • agent, the credentials of the IG agent in AM. When the agent is authenticated, the token can be used for tasks such as getting the user’s profile, making policy evaluations, and connecting to the AM notification endpoint.

    • url: URL of the AM server where the user is authenticated.

    • amHandler: Handler to use when communicating with AM to fetch the requested user’s profile.

  • realm: Realm of the IG agent in AM.

  • version: The version of the AM server.

    The AM version is derived as follows, in order of precedence:

    • Discovered value: AmService discovers the AM version. If version is configured with a different value, AmService ignores the value of version and issues a warning.

    • Value in version: AmService cannot discover the AM version, and version is configured.

    • Default value of AM 6: AmService cannot discover the AM version, and version is not configured.

"cache": object, optional

Caching of AM user profiles, based on Caffeine. For more information, see the GitHub entry, Caffeine.

When caching is enabled, IG can reuse cached profile attributes without repeatedly querying AM. When caching is disabled, IG must query AM for each request, to retrieve the required user profile attributes.

Default: No cache.

"cache": {
    "enabled": configuration expression<boolean>,
    "executor": Executor reference,
    "maximumSize": configuration expression<number>,
    "maximumTimeToCache": configuration expression<duration>,
}
enabled: configuration expression<boolean>,optional

Enable or disable caching of user profiles. When false, the cache is disabled but the cache configuration is maintained.

Default: true when cache is configured

executor: Executor reference, optional

An executor service to schedule the execution of tasks, such as the eviction of entries in the cache.

Default: ForkJoinPool.commonPool()

"maximumSize": configuration expression<number>, optional

The maximum number of entries the cache can contain.

Default: Unlimited/unbound

maximumTimeToCache: configuration expression<duration>, required

The maximum duration for which to cache user profiles.

The duration cannot be zero.

profileAttributes: array of configuration expression<strings>, optional

List of one or more fields to return and store in UserProfileContext.

Field names are defined by the underlying repository in AM. When AM is installed with the default configuration, the repository is ForgeRock Directory Services.

The following convenience accessors are provided for commonly used fields:

  • cn: Retrieved through ${contexts.userProfile.commonName}

  • dn: Retrieved through ${contexts.userProfile.distinguishedName}

  • realm: Retrieved through ${contexts.userProfile.realm}

  • username: Retrieved through ${contexts.userProfile.username}

All other available fields can be retrieved through ${contexts.userProfile.rawInfo} and ${contexts.userProfile.asJsonValue()}.

When profileAttributes is configured, the specified fields and the following fields are returned: username, _id, and _rev.

Default: All available fields are returned.

"realm": configuration expression<string>, optional

The AM realm where the subject is authenticated.

Default: The realm declared for amService.

Example

For examples that use the UserProfileFilter, see Pass profile data downstream.

Decorators

Decorators are heap objects to extend what other objects can do. IG defines baseURI, capture, and timer decorators that you can use without explicitly configuring them.

For more information, refer to Decorators.

BaseUriDecorator

Overrides the scheme, host, and port of the existing request URI, rebasing the URI and so making requests relative to a new base URI. Rebasing changes only the scheme, host, and port of the request URI. Rebasing does not affect the path, query string, or fragment.

Decorator Usage

{
    "name": string,
    "type": "BaseUriDecorator"
}

A BaseUriDecorator does not have configurable properties.

IG creates a default BaseUriDecorator named baseURI at startup time in the top-level heap, so you can use baseURI as the decorator name without adding the decorator declaration

Decorated Object Usage

{
    "name": string,
    "type": string,
    "config": object,
    decorator name: runtime expression<url>
}
"name": string, required except for inline objects

The unique name of the object, just like an object that isn’t decorated.

"type": <string>, required

The class name of the decorated object, which must be either a Filters or a Handlers.

"config": object required unless empty

The configuration of the object, just like an object that is not decorated

decorator name: runtime expression<url>, required

The scheme, host, and port of the new base URI. The port is optional when using the defaults (80 for HTTP, 443 for HTTPS).

The value of the string must not contain underscores, and must conform to the syntax specified in RFC 3986.

Examples

Add a custom decorator to the heap named myBaseUri:

{
    "name": "myBaseUri",
    "type": "BaseUriDecorator"
}

Set a Router’s base URI to https://www.example.com:8443:

{
    "name": "Router",
    "type": "Router",
    "myBaseUri": "https://www.example.com:8443/"
}

CaptureDecorator

Captures request and response messages in SLF4J logs, named in this format:

org.forgerock.openig.decoration.capture.CaptureDecorator.<decoratorName>.<decoratedObjectName>

If the decorated object isn’t named, the object path is used in the log.

During debugging, consider using a CaptureDecorator to capture the entity and context of requests and responses. However, increased logging consumes resources, such as disk space, and can cause performance issues. In production, reduce logging by disabling the CaptureDecorator properties captureEntity and captureContext, or setting maxEntityLength.

For information about using default or custom logging, refer to Manage logs.

Decorator Usage

{
  "name": string,
  "type": "CaptureDecorator",
  "config": {
    "captureEntity": configuration expression<boolean>,
    "captureContext": configuration expression<boolean>,
    "maxEntityLength": configuration expression<number>,
    "masks": object
  }
}
"captureEntity": configuration expression<boolean>, optional

A flag for capture of the message entity:

  • true: Capture the request and response message entity and write it to the logs. The message entity is the body of the HTTP message, which can be a JSON document, XML, HTML, image, or other information.

    When the message is binary, IG writes a [binary entity].

    When streaming is enabled in admin.json, the decorator interrupts streaming for the captured request or response until the whole entity is captured.

  • false: Don’t capture the message entity.

If the Content-Type header is set for a request or response, the decorator uses it to decode the request or response messages, and then writes them to the logs. If the Content-Type header isn’t set, the decorator doesn’t write the request or response messages to the logs.

Default: false

"captureContext": configuration expression<boolean>, optional

A flag for capture of contextual data about the handled request, such as client, session, authentication identity, authorization identity, or any other state information associated with the request:

  • true: Capture contextual data about the handled request.

    The context is captured as JSON. The context chain is used when processing the request inside IG in the filters and handlers.

  • false: Don’t capture contextual data about the handled request.

Default: false

"maxEntityLength": configuration expression<number>, optional

The maximum number of bytes that can be captured for an entity. This property is used when captureEntity is true.

If the captured entity is bigger than maxEntityLength, everything up to maxEntityLength is captured, and an [entity truncated] message is written in the log.

Set maxEntityLength to be big enough to allow capture of normal entities, but small enough to prevent excessive memory use or OutOfMemoryError errors. Setting maxEntityLength to 2 GB or more causes an exception at startup.

Default: 524 288 bytes (512 KB)

"masks": object, optional

The configuration to mask the values of headers and attributes in the logs.

For an example, refer to Masking Values of Headers and Attributes.

{
  "masks": {
    "headers": [ pattern, ... ],
    "trailers": [ pattern, ... ]
    "attributes": [ pattern, ... ]
    "mask": [ configuration expression<string>, ... ]
  }
}
"headers": array of patterns, optional

The case-insensitive name of one or more headers whose value to mask in the logs.

The following value masks headers called X-OpenAM-Username, X-OpenAM-Password and x-openam-token:

"headers": ["X-OpenAM-.*"]

Default: None

"trailers": array of patterns, optional

The case-insensitive name of one or more trailers whose value to mask in the logs.

The following value masks trailers called Expires:

"trailers": ["Expires"]

Default: None

"attributes": array of patterns, optional

The case-insensitive name of one or more attributes whose value to mask in the logs.

Default: None

"mask": configuration expression<string>, optional

Text to replace the masked header value or attribute value in the logs.

Default: *****

Decorated Object Usage

{
    "name": string,
    "type": string,
    "config": object,
    decorator name: capture point(s)
}
"name": string, required except for inline objects

The unique name of the decorated object.

"type": string, required except for inline objects, required_

The class name of the decorated object, which must be either a Filter or a Handler. See also Filters and Handlers.

"config": object required unless empty

The configuration of the decorated object, as documented in the object reference page.

decorator name: capture point(s), optional

The decorator name must match the name of the CaptureDecorator. For example, if the CaptureDecorator has "name": "capture", then decorator name is capture.

The capture point(s) are either a single string, or an array of strings. The strings are documented here in lowercase, but are not case-sensitive:

"all"

Capture at all available capture points.

"none"

Disable capture. If none is configured with other capture points, none takes precedence.

"request"

Capture the request as it enters the Filter or Handler.

"filtered_request"

Capture the request as it leaves the Filter. Only applies to Filters.

"response"

Capture the response as it enters the Filter or leaves the Handler.

"filtered_response"

Capture the response as it leaves the Filter. Only applies to Filters.

Examples

Log the entity

The following example decorator is configured to log the entity:

{
    "name": "capture",
    "type": "CaptureDecorator",
    "config": {
        "captureEntity": true
    }
}
Do not log the entity

The following example decorator is configured not to log the entity:

{
  "name": "capture",
  "type": "CaptureDecorator"
}
Log the context

The following example decorator is configured to log the context in JSON format, excluding the request and the response:

{
  "name": "capture",
  "type": "CaptureDecorator",
  "config": {
    "captureContext": true
  }
}
Log requests and responses with the entity

The following example decorator is configured to log requests and responses with the entity, before sending the request and before returning the response:

{
  "heap": [
    {
      "name": "capture",
      "type": "CaptureDecorator",
      "config": {
        "captureEntity": true
      }
    },
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "capture": [
        "request",
        "response"
      ]
    }
  ],
  "handler": "ReverseProxyHandler"
}
Capture transformed requests and responses

The following example uses the default CaptureDecorator to capture transformed requests and responses, as they leave filters:

{
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [{
        "type": "HeaderFilter",
        "config": {
          "messageType": "REQUEST",
          "add": {
            "X-RequestHeader": [
              "Capture at filtered_request point",
              "And at filtered_response point"
            ]
          }
        }
      },
        {
          "type": "HeaderFilter",
          "config": {
            "messageType": "RESPONSE",
            "add": {
              "X-ResponseHeader": [
                "Capture at filtered_response point"
              ]
            }
          }
        }
      ],
      "handler": {
        "type": "StaticResponseHandler",
        "config": {
          "status": 200,
          "headers": {
            "Content-Type": [ "text/html; charset=UTF-8" ]
          },
          "entity": "<html><body><p>Hello world!</p></body></html>"
        }
      }
    }
  },
  "capture": [
    "filtered_request",
    "filtered_response"
  ]
}
Capture the context as JSON

The following example captures the context as JSON, excluding the request and response, before sending the request and before returning the response:

{
  "heap": [
    {
      "name": "capture",
      "type": "CaptureDecorator",
      "config": {
        "captureContext": true
      }
    },
    {
      "name": "ReverseProxyHandler",
      "type": "ReverseProxyHandler",
      "capture": [
        "request",
        "response"
      ]
    }
  ],
  "handler": "ReverseProxyHandler"
}
Mask values of headers and attributes

This example captures the context, and then masks the value of the cookies and credentials in the logs. To try it, set up the example in Password replay from a file, replace that route with the following route, and search the route log file for the text MASKED:

{
  "heap": [{
    "name": "maskedCapture",
    "type": "CaptureDecorator",
    "config": {
      "captureContext": true,
      "masks": {
        "headers": [ "cookie*", "set-cookie*" ],
        "attributes": [ "credentials" ],
        "mask": "MASKED"
      }
    }
  }],
  "name": "02-file-masked",
  "condition": "${find(request.uri.path, '^/profile')}",
  "maskedCapture": "all",
  "handler": {
    "type": "Chain",
    "baseURI": "http://app.example.com:8081",
    "config": {
      "filters": [
        {
          "type": "PasswordReplayFilter",
          "config": {
            "loginPage": "${find(request.uri.path, '^/profile/george') and (request.method == 'GET')}",
            "credentials": {
              "type": "FileAttributesFilter",
              "config": {
                "file": "/tmp/userfile.txt",
                "key": "email",
                "value": "george@example.com",
                "target": "${attributes.credentials}"
              }
            },
            "request": {
              "method": "POST",
              "uri": "http://app.example.com:8081/login",
              "form": {
                "username": [
                  "${attributes.credentials.username}"
                ],
                "password": [
                  "${attributes.credentials.password}"
                ]
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

TimerDecorator

Records time to process filters, handlers, and access token resolvers.

Decorator usage

{
    "name": string,
    "type": "TimerDecorator",
    "config": {
        "timeUnit": configuration expression<string>
    }
}

IG configures a default TimerDecorator named timer. Use timer as the decorator name without explicitly declaring a decorator named timer.

"timeUnit": configuration expression<string>, optional

Unit of time used in the decorator output. The unit of time can be any unit allowed in the <duration> field.

Default: ms

Decorated object usage

{
    "name": string,
    "type": string,
    "config": object,
    decorator name: boolean
}
"name": string, required except for inline objects

The unique name of the object to decorate.

"type": string, required

The class name of the object to decorate, which must be a Filter, Handler, or the accessTokenResolver property of OAuth2ResourceServerFilter.

"config": object, optional

The configuration of the object, just like an object that is not decorated.

Default: Empty

decorator name: configuration expression<boolean>, required

IG looks for the presence of the decorator name field for the TimerDecorator:

  • true: Activate the timer

  • false: Deactivate the TimerDecorator

Timer metrics at the Prometheus Scrape Endpoint

This section describes the timer metrics recorded at the Prometheus Scrape Endpoint. For more information about metrics, refer to Monitoring Endpoints.

When IG is set up as described in the documentation, the endpoint is http://ig.example.com:8080/openig/metrics/prometheus.

Each timer metric is labelled with the following fully qualified names:

  • decorated_object

  • heap

  • name (decorator name)

  • route

  • router

Timer metrics at the Prometheus Scrape Endpoint
Name Monitoring type Description

ig_timerdecorator_handler_elapsed_seconds

Summary

Time to process the request and response in the decorated handler.

ig_timerdecorator_filter_elapsed_seconds

Summary

Time to process the request and response in the decorated filter and its downstream filters and handler.

ig_timerdecorator_filter_internal_seconds

Summary

Time to process the request and response in the decorated filter.

ig_timerdecorator_filter_downstream_seconds

Summary

Time to process the request and response in filters and handlers that are downstream of the decorated filter.

Timer metrics at the Common REST Monitoring Endpoint

This section describes the metrics recorded at the the ForgeRock Common REST Monitoring Endpoint. For more information about metrics, refer to Monitoring Endpoints.

When IG is set up as described in the documentation, the endpoint is http://ig.example.com:8080/openig/metrics/api?_queryFilter=true.

Metrics are published with an _id in the following pattern:

heap.router-name.route-name.decorator-name.object

Timer metrics at the Common REST Monitoring Endpoint
Name Monitoring type Description

elapsed

Timer

Time to process the request and response in the decorated handler, or in the decorated filter and its downstream filters and handler.

internal

Timer

Time to process the request and response in the decorated filter.

downstream

Timer

Time to process the request and response in filters and handlers that are downstream of the decorated filter.

Timer metrics in SLF4J logs

SLF4J logs are named in this format:

<className>.<decoratorName>.<decoratedObjectName>

If the decorated object is not named, the object path is used in the log.

When a route’s top-level handler is decorated, the timer decorator records the elapsed time for operations traversing the whole route:

2018-09-04T12:16:08,994Z | INFO  | I/O dispatcher 17 | o.f.o.d.t.T.t.top-level-handler | @myroute | Elapsed time: 13 ms

When an individual handler in the route is decorated, the timer decorator records the elapsed time for operations traversing the handler:

2018-09-04T12:44:02,161Z | INFO  | http-nio-8080-exec-8 | o.f.o.d.t.T.t.StaticResponseHandler-1 | @myroute | Elapsed time: 1 ms

Examples

The following example uses the default timer decorator to record the time that TokenIntrospectionAccessTokenResolver takes to process a request:

{
  "accessTokenResolver": {
    "name": "TokenIntrospectionAccessTokenResolver-1",
    "type": "TokenIntrospectionAccessTokenResolver",
    "config": {
      "amService": "AmService-1",
      ...
    },
    "timer": true
  }
}

The following example defines a customized timer decorator in the heap, and uses it to record the time that the SingleSignOnFilter takes to process a request:

{
  "heap": [
    {
      "name": "mytimerdecorator",
      "type": "TimerDecorator",
      "config": {
        "timeUnit": "nano"
      }
    },
    ...
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "SingleSignOnFilter",
          "config": {
            ...
          },
          "mytimerdecorator": true
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

Audit framework

IG uses the ForgeRock common audit framework to record audit events, using an implementation that is common across the ForgeRock platform.

Audit logs use timestamps in UTC format (for example, 2018-07-18T08:48:00.160Z), a unified standard that is not affected by time changes for daylight savings. The timestamps format is not configurable.

The following objects are available for auditing:

AuditService

The audit service is based on the ForgeRock common audit event framework to record access audit events. For information about how to record other types of audit event, refer to Record custom audit events.

By default, no routes in a configuration are audited; the NoOpAuditService object type provides an empty audit service to the top-level heap and its child routes. IG provides a default empty service based on the NoOpAuditService type. The top-level heap and child routes inherit from the setting and use a service equivalent to the following declaration:

{
  "name": "AuditService",
  "type": "NoOpAuditService"
}

Configure auditing in the following ways:

Override the NoOpAuditService for all routes in the configuration

Define an AuditService object named AuditService in config.json. No other configuration is required; all routes use the same AuditService.

Configure an audit service that can be optionally used by all routes in the configuration

Do both of the following:

  • In config.json in the top-level heap, define an AuditService object that is not named AuditService.

  • In a route, configure the Route property auditService to refer to the name of the declared AuditService heaplet.

Configure an audit service specifically for a route

Do one of the following:

  • Define an AuditService object named AuditService in the route heap.

  • In the route heap or a parent heap, define an AuditService object that is not named AuditService; configure the Route property auditService to refer to the name of the declared AuditService heaplet.

  • Configure the Route property auditService with an inline AuditService object.

One configuration can contain multiple AuditServices.

When you define multiple AuditServices that use JsonAuditEventHandler or CsvAuditEventHandler, configure each of the event handlers with a different logDirectory. This prevents the AuditServices from logging to the same audit logging file.

Usage

{
  "name": string,
  "type": "AuditService",
  "config": {
    "config": object,
    "eventHandlers": [ object, ...],
    "topicsSchemasDirectory": configuration expression<string>,
    "event-handlers": [ object, ...] // deprecated
  }
}

Properties

"config": object, required

Configures the audit service itself, rather than event handlers. If the configuration uses only default settings, you can omit the field instead of including an empty object as the field value.

{
  "config": {
    "handlerForQueries": configuration_expression<string>,
    "availableAuditEventHandlers": [configuration_expression<string>, ...],
    "caseInsensitiveFields": [configuration_expression<string>, ...],
    "filterPolicies": {
      "field": {
        "includeIf": [configuration_expression<string>, ...],
        "excludeIf": [configuration_expression<string>, ...]
      }
    }
  }
}
"handlerForQueries": configuration expression<string>, optional

The name of the event handler to use when querying audit event messages over REST.

"availableAuditEventHandlers": array of configuration expression<strings>, optional

A list of fully qualified event handler class names for event handlers available to the audit service.

"caseInsensitiveFields": array of configuration expression<strings>, optional

A list of audit event fields to be considered as case-insensitive for filtering. The fields are referenced using JSON pointer syntax. The list can be null or empty.

Default: /access/http/request/headers and /access/http/response/headers fields are considered case-insensitive for filtering. All other fields are considered case-sensitive.

"filterPolicies": object, optional

To prevent logging of sensitive data for an event, the Common Audit implementation uses a safelist to specify which event fields appear in the logs. By default, only event fields that are safelisted are included in the audit event logs. For more information about safelisting, refer to Safelisting audit event fields for the logs.

"field": object, optional

This property specifies non-safelisted event fields to include in the logs, and safelisted event fields to exclude from the logs.

If includeIf and excludeIf are specified for the same field, excludeIf takes precedence.

Audit event fields use JSON pointer notation, and are taken from the JSON schema for the audit event content.

Default: Include only safelisted event fields in the logs.

"includeIf": array of configuration expression<strings>, optional:

A list of non-safelisted audit event fields to include in the logs. Specify the topic and the hierarchy to the field. Any child fields of the specified field are encompassed.

Before you include non-safelisted event fields in the logs, consider the impact on security. Including some headers, query parameters, or cookies in the logs could cause credentials or tokens to be logged, and allow anyone with access to the logs to impersonate the holder of these credentials or tokens.
"excludeIf": array of configuration expression<strings>, optional:

A list of safelisted audit event fields to exclude from the logs. Specify the topic and the hierarchy to the field. Any child fields of the specified field are encompassed.

The following example excludes fields for the access topic:

{
  "field": {
    "excludeIf": [
      "/access/http/request/headers/host",
      "/access/http/request/path",
      "/access/server",
      "/access/response"
    ]
  }
}

For an example route that excludes fields, see Exclude safelisted audit event fields from logs.

"eventHandlers": array of Event Handler objects, required

An array of one or more audit event handler configuration objects to deal with audit events.

The configuration of the event handler depends on type of event handler. IG supports the event handlers listed in AuditFramework.

"topicsSchemasDirectory": configuration expression<string>, optional

Directory containing the JSON schema for the topic of a custom audit event. The schema defines which fields are included in the topic. For information about the syntax, see JSON Schema.

Default: $HOME/.openig/audit-schemas (Windows, %appdata%\OpenIG\OpenIG\audit-schemas)

For an example of how to configure custom audit events, see Record custom audit events.

The following example schema includes the mandatory fields, _id, timestamp, transactionId, and eventName, and an optional customField:

{
  "schema": {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "id": "/",
    "type": "object",
    "properties": {
      "_id": {
        "type": "string"
      },
      "timestamp": {
        "type": "string"
      },
      "transactionId": {
        "type": "string"
      },
      "eventName": {
        "type": "string"
      },
      "customField": {
        "type": "string"
      }
    }
  }
}
"event-handlers": array of configuration objects, required
This property is deprecated. Use eventHandlers instead. For more information, refer to the Deprecated section of the Release Notes.

The event handlers that deal with audit events.

Example

The following example audit service logs access event messages in a comma-separated variable file, named /path/to/audit/logs/access.csv:

{
  "name": "AuditService",
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [
      {
        "class": "org.forgerock.audit.handlers.csv.CsvAuditEventHandler",
        "config": {
          "name": "csv",
          "logDirectory": "/path/to/audit/logs",
          "topics": [
            "access"
          ]
        }
      }
    ]
  }
}

The following example route uses the audit service:

{
  "handler": "ReverseProxyHandler",
  "auditService": "AuditService"
}

CsvAuditEventHandler

An audit event handler that responds to events by logging messages to files in comma-separated variable (CSV) format.

Declare the configuration in an audit service, as described in AuditService.

The CSV handler does not sanitize messages when writing to CSV log files.

Do not open CSV logs in spreadsheets or other applications that treat data as code.

Usage

{
  "class": "org.forgerock.audit.handlers.csv.CsvAuditEventHandler",
  "config": {
    "name": configuration expression<string>,
    "logDirectory": configuration expression<string>,
    "topics": [ configuration expression<string>, ... ],
    "enabled": configuration expression<boolean>,
    "formatting": {
      "quoteChar": configuration expression<string>,
      "delimiterChar": configuration expression<string>,
      "endOfLineSymbols": configuration expression<string>
    },
    "buffering": {
      "enabled": configuration expression<boolean>,
      "autoFlush": configuration expression<boolean>
    },
    "security": {
      "enabled": configuration expression<boolean>,
      "filename": configuration expression<string>,
      "password": configuration expression<string>,
      "signatureInterval": configuration expression<duration>
    },
    "fileRotation": {
      "rotationEnabled": configuration expression<boolean>,
      "maxFileSize": configuration expression<number>,
      "rotationFilePrefix": configuration expression<string>,
      "rotationFileSuffix": configuration expression<string>,
      "rotationInterval": configuration expression<duration>,
      "rotationTimes": [ configuration expression<duration>, ... ]
    },
    "fileRetention": {
      "maxDiskSpaceToUse": configuration expression<number>,
      "maxNumberOfHistoryFiles": configuration expression<number>,
      "minFreeSpaceRequired": configuration expression<number>
    },
    "rotationRetentionCheckInterval": configuration expression<duration>
  }
}

The values in this configuration object can use expressions as long as they resolve to the correct types for each field. For details about expressions, see Expressions.

Configuration

"name": configuration expression<string>, required

The name of the event handler.

"logDirectory": configuration expression<string>, required

The file system directory where this event handler writes log files.

When multiple AuditServices are defined in the deployment, prevent them from logging to the same audit logging file by setting different values for logDirectory.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"enabled": configuration expression<boolean>, optional

Whether this event handler is active.

Default: true

"formatting": object, optional

Formatting settings for CSV log files.

The formatting object has the following fields:

"quoteChar": configuration expression<string>, optional

A single character to quote CSV entries.

Default: "

"delimiterChar": configuration expression<string>, optional

A single character to delimit CSV entries.

Default: ,

"endOfLineSymbols": configuration expression<string>, optional

A character or characters to separate a line.

Default: System-dependent line separator defined for the JVM

"buffering": object, optional

Do not enable buffering when security is configured for tamper-evident logging.

Buffering settings for writing CSV log files. The default is for messages to be written to the log file for each event.

The buffering object has the following fields:

"enabled": configuration expression<boolean>, optional

Whether log buffering is enabled.

Default: false

"autoFlush": configuration expression<boolean>, optional

Whether events are automatically flushed after being written.

Default: true

"security": object, optional

When security is configured for tamper-evident logging, do not enable buffering.

Security settings for CSV log files. These settings govern tamper-evident logging, whereby messages are signed. By default tamper-evident logging is not enabled.

The security object has the following fields:

"enabled": configuration expression<boolean>, optional

Whether tamper-evident logging is enabled.

Default: false

Tamper-evident logging depends on a specially prepared keystore. For an example, see Recording Access Audit Events in CSV.

"filename": configuration expression<string>, required

File system path to the keystore containing the private key for tamper-evident logging.

The keystore must be a keystore of type JCEKS. For an example, see Recording access audit events in CSV.

"password": configuration expression<string>, required

The password for the keystore for tamper-evident logging.

This password is used for the keystore and for private keys. For an example, see Recording access audit events in CSV.

"signatureInterval": configuration expression<duration>, required

The time interval after which to insert a signature in the CSV file. This duration must not be zero, and must not be unlimited.

"fileRotation": object, optional

File rotation settings for log files.

"rotationEnabled": configuration expression<boolean>, optional

A flag to enable rotation of log files.

Default: false.

"maxFileSize": configuration expression<number>, optional

The maximum file size of an audit log file in bytes. A setting of 0 or less indicates that the policy is disabled.

Default: 0.

"rotationFilePrefix": configuration expression<string>, optional

The prefix to add to a log file on rotation. This has an effect when time-based file rotation is enabled.

"rotationFileSuffix": configuration expression<string>, optional

The suffix to add to a log file on rotation, possibly expressed in SimpleDateFormat.

This has an effect when time-based file rotation is enabled.

Default: -yyyy.MM.dd-HH.mm.ss, where yyyy characters are replaced with the year, MM characters are replaced with the month, dd characters are replaced with the day, HH characters are replaced with the hour (00-23), mm characters are replaced with the minute (00-60), and ss characters are replaced with the second (00-60).

"rotationInterval": configuration expression<duration>, optional

The time interval after which to rotate log files. This duration must not be zero. This has the effect of enabling time-based file rotation.

"rotationTimes": array of configuration expression<durations>, optional

The durations, counting from midnight, after which to rotate files.

The following example schedules rotation six and twelve hours after midnight:

"rotationTimes": [ "6 hours", "12 hours" ]

This has the effect of enabling time-based file rotation.

"fileRetention": object, optional

File retention settings for log files.

"maxNumberOfHistoryFiles": configuration expression<number>, optional

The maximum number of historical audit files that can be stored. If the number exceeds this maximum, older files are deleted. A value of -1 disables purging of old log files.

Default: 0.

"maxDiskSpaceToUse": configuration expression<number>, optional

The maximum disk space in bytes that can be used for audit files. If the audit files use more than this space, older files are deleted. A negative or zero value indicates that this policy is disabled, and historical audit files can use unlimited disk space.

Default: 0

"minFreeSpaceRequired": configuration expression<string>, optional

The minimum free disk space in bytes required on the system that houses the audit files. If the free space drops below this minimum, older files are deleted. A negative or zero value indicates that this policy is disabled, and no minimum space requirements apply.

Default: 0

"rotationRetentionCheckInterval": configuration expression<string>, optional

Interval at which to periodically check file rotation and retention policies. The interval must be a duration, for example, 5 seconds, 5 minutes, or 5 hours.

Default: 5 seconds

Example

For information about how to record audit events in a CSV file, see Recording Access Audit Events in CSV.

The following example configures a CSV audit event handler to write a log file, /path/to/audit/logs/access.csv, that is signed every 10 seconds to make it tamper-evident:

{
  "name": "csv",
  "topics": [
    "access"
  ],
  "logDirectory": "/path/to/audit/logs/",
  "security": {
    "enabled": "true",
    "filename": "/path/to/secrets/audit-keystore",
    "password": "password",
    "signatureInterval": "10 seconds"
  }
}

ElasticsearchAuditEventHandler (deprecated)

This object is deprecated; use one of the following objects instead:

For more information, refer to the Deprecated section of the Release Notes.

An audit event handler that responds to events by logging messages in the Elasticsearch search and analytics engine. For information about downloading and installing Elasticsearch, refer to the Elasticsearch Getting started document.

Usage

Configure the ElasticsearchAuditEventHandler within an AuditService:

{
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [{
      "class": "org.forgerock.audit.handlers.elasticsearch.ElasticsearchAuditEventHandler",
      "config": {
        "name": configuration expression<string>,
        "topics": [ configuration expression<string>, ... ],
        "connection": {
          "host": configuration expression<string>,
          "port": configuration expression<number>,
          "useSSL": configuration expression<boolean>,
          "username": configuration expression<string>,
          "password": configuration expression<string>
        },
        "indexMapping": {
          "indexName": configuration expression<string>
        },
        "buffering": {
          "enabled": configuration expression<boolean>,
          "writeInterval": configuration expression<duration>,
          "maxSize": configuration expression<number>,
          "maxBatchedEvents": configuration expression<number>
        }
      }
    }
  }
}

The ElasticsearchAuditEventHandler relays audit events to Elasticsearch through the HTTP protocol, using a handler defined in a heap. The handler can be of any kind of handler, from a simple ClientHandler to a complex Chain, composed of multiple filters and a final handler or ScriptableHandler.

IG searches first for a handler named ElasticsearchClientHandler. If not found, IG searches for a client handler named AuditClientHandler. If not found, IG uses the route’s default client handler, named ClientHandler.

The following example configures a ClientHandler named ElasticsearchClientHandler:

{
  "name": "ElasticsearchClientHandler",
  "type": "ClientHandler",
  "config": {}
}

The following example configures a ScriptableHandler named AuditClientHandler:

{
  "name": "AuditClientHandler",
  "type": "ScriptableHandler",
  "config": {}
}

Properties

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"connection": object, optional

Connection settings for sending messages to Elasticsearch. If this object is not configured, it takes default values for its fields. This object has the following fields:

"host": configuration expression<string>, optional

Hostname or IP address of Elasticsearch.

Default: localhost

"port": configuration expression<number>, optional

The port used by Elasticsearch. The value must be between 0 and 65535.

Default: 9200

"useSSL": configuration expression<boolean>, optional

Setting to use or not use SSL/TLS to connect to Elasticsearch.

Default: false

"username": configuration expression<string>, optional

Username when basic authentication is enabled through Elasticsearch Shield.

"password": configuration expression<string>, optional

Password when basic authentication is enabled through Elasticsearch Shield.

"indexMapping": object, optional

Defines how an audit event and its fields are stored and indexed.

"indexName": configuration expression<string>, optional

The index name. Set this parameter if the default name audit conflicts with an existing Elasticsearch index.

Default: audit.

"buffering": object, optional

Settings for buffering events and batch writes.

"enabled": configuration expression<boolean>, optional

Setting to use or not use log buffering.

Default: false.

"writeInterval": configuration expression<duration>

The interval at which to send buffered event messages to Elasticsearch. If buffering is enabled, this interval must be greater than 0.

Default: 1 second

"maxBatchedEvents": configuration expression<number>, optional

The maximum number of event messages in a batch write to Elasticsearch for each writeInterval.

Default: 500

"maxSize": configuration expression<number>, optional

The maximum number of event messages in the queue of buffered event messages.

Default: 10000

Example

In the following example, an Elasticsearch audit event handler logs audit events for access. For an example of setting up and testing this configuration, refer to [maintenance-guide:].

{
  "name": "30-elasticsearch",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/elasticsearch-audit')}",
  "heap": [
    {
      "name": "AuditService",
      "type": "AuditService",
      "config": {
        "eventHandlers": [
          {
            "class": "org.forgerock.audit.handlers.elasticsearch.ElasticsearchAuditEventHandler",
            "config": {
              "name": "elasticsearch",
              "indexMapping": {
                "indexName": "audit"
              },
              "connection": {
                "host": "localhost",
                "port": 9200,
                "useSSL": false
              },
              "topics": [
                "access"
              ]
            }
          }
        ]
      }
    }
  ],
  "auditService": "AuditService",
  "handler": "ReverseProxyHandler"
}

JdbcAuditEventHandler

An audit event handler that responds to events by logging messages to an appropriately configured relational database table.

Declare the configuration in an audit service, as described in AuditService.

To configure IG to use the database, add the database .jar file containing the Driver as follows:

  • Create the directory $HOME/.openig/extra, where $HOME/.openig is the instance directory, and add .jar files to the directory.

The JDBC handler library is in the lib directory.

Unpack the library, then find the examples under the db/ folder.

Usage

{
  "class": "org.forgerock.audit.handlers.jdbc.JdbcAuditEventHandler",
  "config": {
    "name": configuration expression<string>,
    "topics": [ configuration expression<string>, ... ],
    "databaseType": configuration expression<string>,
    "enabled": configuration expression<boolean>,
    "buffering": {
      "enabled": configuration expression<boolean>,
      "writeInterval": configuration expression<duration>,
      "autoFlush": configuration expression<boolean>,
      "maxBatchedEvents": configuration expression<number>,
      "maxSize": configuration expression<number>,
      "writerThreads": configuration expression<number>
    },
    "connectionPool": {
      "driverClassName": configuration expression<string>,
      "dataSourceClassName": configuration expression<string>,
      "jdbcUrl": configuration expression<string>,
      "username": configuration expression<string>,
      "password": configuration expression<string>,
      "autoCommit": configuration expression<boolean>,
      "connectionTimeout": configuration expression<number>,
      "idleTimeout": configuration expression<number>,
      "maxLifetime": configuration expression<number>,
      "minIdle": configuration expression<number>,
      "maxPoolSize": configuration expression<number>,
      "poolName": configuration expression<string>
    },
    "tableMappings": [
      {
        "event": configuration expression<string>,
        "table": configuration expression<string>,
        "fieldToColumn": map or configuration expression<map>
      }
    ]
  }
}

Configuration

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"databaseType": configuration expression<string>, required

The database type name.

Built-in support is provided for oracle, mysql, and h2.

"enabled": configuration expression<boolean>, optional

Whether this event handler is active.

Default: true.

"buffering": object, optional

Buffering settings for sending messages to the database. The default is for messages to be written to the log file for each event.

The buffering object has the following fields:

"enabled": configuration expression<boolean>, optional

Whether log buffering is enabled.

Default: false.

"writeInterval": configuration expression<duration>, required

The interval at which to send buffered event messages to the database.

This interval must be greater than 0 if buffering is enabled.

"autoFlush": configuration expression<boolean>, optional

Whether the events are automatically flushed after being written.

Default: true.

"maxBatchedEvents": configuration expression<number>, optional

The maximum number of event messages batched into a PreparedStatement.

Default: 100.

"maxSize": : configuration expression<number>, optional

The maximum size of the queue of buffered event messages.

Default: 5000.

"writerThreads": configuration expression<number>, optional

The number of threads to write buffered event messages to the database.

Default: 1.

"connectionPool": object, required

When a JdbcDataSource object named AuditService is defined in the route heap. This configuration is not required.

Connection pool settings for sending messages to the database.

"driverClassName": configuration expression<string>, optional

The class name of the driver to use for the JDBC connection. For example, with MySQL Connector/J, the class name is com.mysql.jdbc.Driver.

"dataSourceClassName": configuration expression<string>, optional

The class name of the data source for the database.

"jdbcUrl": configuration expression<string>, required

The JDBC URL to connect to the database.

"username": configuration expression<string>, required

The username identifier for the database user with access to write the messages.

"password": configuration expression<number>, optional

The password for the database user with access to write the messages.

"autoCommit": configuration expression<boolean>, optional

Whether to commit transactions automatically when writing messages.

Default: true.

"connectionTimeout": configuration expression<number>, optional

The number of milliseconds to wait for a connection from the pool before timing out.

Default: 30000.

"idleTimeout": configuration expression<number>, optional

The number of milliseconds to allow a database connection to remain idle before timing out.

Default: 600000.

"maxLifetime": configuration expression<number>, optional

The number of milliseconds to allow a database connection to remain in the pool.

Default: 1800000.

"minIdle": configuration expression<number>, optional

The minimum number of idle connections in the pool.

Default: 10.

"maxPoolSize": configuration expression<number>, optional

The maximum number of connections in the pool.

Default: 10.

"poolName": configuration expression<string>, optional

The name of the connection pool.

"tableMappings": array of objects, required

Table mappings for directing event content to database table columns.

A table mappings object has the following fields:

"event": configuration expression<string>, required

The audit event that the table mapping is for.

Set this to access.

"table": configuration expression<string>, required

The name of the database table that corresponds to the mapping.

"fieldToColumn": map or configuration expression<map>, required

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

  • The key is the name of an audit event field

  • The value is the name of a database column, or a configuration expression that evaluates to the name of a database column

The following formats are allowed:

{
  "fieldToColumn": {
    "string": "configuration expression<string>",
    ...
  }
}
{
  "fieldToColumn": "configuration expression<map>"
}

Audit event fields use JSON pointer notation, and are taken from the JSON schema for the audit event content.

In the following example, the property is a map whose keys and values are strings representing the names of audit event fields and database columns:

{
  "fieldToColumn": {
    "_id": "id",
    "timestamp": "timestamp_",
    ...
  }

Example

Examples including statements to create tables are provided in the JDBC handler library, forgerock-audit-handler-jdbc-version.jar.

For an example of using JdbcAuditEventHandler, refer to Recording access audit events in a database.

In the following example, IG events are logged to an h2 database:

{
  "name": "audit-jdbc",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/audit-jdbc')}",
  "heap": [
    {
      "name": "SystemAndEnvSecretStore-1",
      "type": "SystemAndEnvSecretStore"
    },
    {
      "name": "AuditDataSource",
      "type": "JdbcDataSource",
      "config": {
        "dataSourceClassName" : "org.h2.jdbcx.JdbcDataSource",
        "username"            : "sa",
        "passwordSecretId"    : "database.password",
        "secretsProvider"     : "SystemAndEnvSecretStore-1",
        "properties" : {
          "url"               : "jdbc:h2:tcp://localhost/~/test"
        }
      }
    },
    {
      "name": "AuditService",
      "type": "AuditService",
      "config": {
        "eventHandlers": [
          {
            "class": "org.forgerock.audit.handlers.jdbc.JdbcAuditEventHandler",
            "config": {
              "databaseType": "h2",
              "name": "jdbc",
              "topics": [
                "access"
              ],
              "tableMappings": [
                {
                  "event": "access",
                  "table": "audit.auditaccess",
                  "fieldToColumn": {
                    "_id": "id",
                    "timestamp": "timestamp_",
                    "eventName": "eventname",
                    "transactionId": "transactionid",
                    "userId": "userid",
                    "trackingIds": "trackingids",
                    "server/ip": "server_ip",
                    "server/port": "server_port",
                    "client/ip": "client_ip",
                    "client/port": "client_port",
                    "request/protocol": "request_protocol",
                    "request/operation": "request_operation",
                    "request/detail": "request_detail",
                    "http/request/secure": "http_request_secure",
                    "http/request/method": "http_request_method",
                    "http/request/path": "http_request_path",
                    "http/request/queryParameters": "http_request_queryparameters",
                    "http/request/headers": "http_request_headers",
                    "http/request/cookies": "http_request_cookies",
                    "http/response/headers": "http_response_headers",
                    "response/status": "response_status",
                    "response/statusCode": "response_statuscode",
                    "response/elapsedTime": "response_elapsedtime",
                    "response/elapsedTimeUnits": "response_elapsedtimeunits"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ],
  "auditService": "AuditService",
  "handler": "ReverseProxyHandler"
}

JmsAuditEventHandler

The Java Message Service (JMS) is a Java API for sending asynchronous messages between clients. It wraps audit events in JMS messages and publishes them in a JMS broker, which then delivers the messages to the appropriate destination.

The JMS API architecture includes a JMS provider and JMS clients, and supports the publish/subscribe messaging pattern. For more information, refer to Basic JMS API Concepts

The JMS audit event handler does not support queries. To support queries, also enable a second handler that supports queries.

The ForgeRock JMS audit event handler supports JMS communication, based on the following components:

  • JMS message broker .jar files, to provide clients with connectivity, message storage, and message delivery functionality.

    Add the .jar files to the configuration as follows:

  • Create the directory $HOME/.openig/extra, where $HOME/.openig is the instance directory, and add .jar files to the directory.

  • JMS messages.

  • Destinations, maintained by a message broker. A destination can be a JMS topic, using publish/subscribe to take the ForgeRock JSON for an audit event, wrap it into a JMS TextMessage, and send it to the broker.

  • JMS clients, to produce and/or receive JMS messages.

Depending on the configuration, some or all of these components are included in JMS audit log messages.

The example in this section is based on Apache ActiveMQ, but you can choose a different JMS message broker.

Declare the configuration in an audit service, as described in AuditService.

Usage

{
  "name": string,
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [
    {
      "class": "org.forgerock.audit.handlers.jms.JmsAuditEventHandler",
      "config": {
        "name": configuration expression<string>,
        "topics": [ configuration expression<string>, ... ],
        "deliveryMode": configuration expression<string>,
        "sessionMode": configuration expression<string>,
        "jndi": {
          "contextProperties": map,
          "topicName": configuration expression<string>,
          "connectionFactoryName": configuration expression<string>
        }
      }
    }]
  }
}

The values in this configuration object can use configuration expressions, as described in Configuration and Runtime Expressions.

Configuration

For a list of properties in the "config" object, refer to JMS Audit Event Handler in IDM’s Integrator’s guide.

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"deliveryMode": configuration expression<string>, required

Delivery mode for messages from a JMS provider. Set to PERSISTENT or NON_PERSISTENT.

"sessionMode": configuration expression<string>, required

Acknowledgement mode in sessions without transactions. Set to AUTO, CLIENT, or DUPS_OK.

"contextProperties":_map, optional_

Settings with which to populate the initial context.

The map values are evaluated as configuration expression<strings>.

The following properties are required when ActiveMQ is used as the message broker:

  • java.naming.factory.initial

    For example, "org.apache.activemq.jndi.ActiveMQInitialContextFactory".

    To substitute a different JNDI message broker, change the JNDI context properties.

  • java.naming.provider.url

    For example, "tcp://127.0.0.1:61616".

    To configure the message broker on a remote system, substitute the associated IP address.

    To set up SSL, set up keystores and truststores, and change the value of the java.naming.provider.url to:

    ssl://127.0.0.1:61617?daemon=true&socket.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA,SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
  • topic.audit

    For example, "audit".

To use the JMS resources provided by your application server, leave this field empty. The values for topicName and connectionFactoryName are then JNDI names that depend on the configuration of your application server.

"topicName": configuration expression<string>, required

JNDI lookup name for the JMS topic.

For ActiveMQ, this property must be consistent with the value of topic.audit in contextProperties.

"connectionFactoryName": configuration expression<string>, required

JNDI lookup name for the JMS connection factory.

Example

In the following example, a JMS audit event handler delivers audit events in batches. The handler is configured to use the ActiveMQ JNDI message broker, on port 61616. For an example of setting up and testing this configuration, refer to Recording Access Audit Events in JMS.

{
  "name": "30-jms",
  "MyCapture" : "all",
  "baseURI": "http://app.example.com:8081",
  "condition" : "${request.uri.path == '/activemq_event_handler'}",
  "heap": [
    {
      "name": "AuditService",
      "type": "AuditService",
      "config": {
        "eventHandlers" : [
          {
            "class" : "org.forgerock.audit.handlers.jms.JmsAuditEventHandler",
            "config" : {
              "name" : "jms",
              "topics": [ "access" ],
              "deliveryMode" : "NON_PERSISTENT",
              "sessionMode" : "AUTO",
              "jndi" : {
                "contextProperties" : {
                  "java.naming.factory.initial" : "org.apache.activemq.jndi.ActiveMQInitialContextFactory",
                  "java.naming.provider.url" : "tcp://am.example.com:61616",
                  "topic.audit" : "audit"
                },
                "topicName" : "audit",
                "connectionFactoryName" : "ConnectionFactory"
              }
            }
          }
        ],
        "config" : { }
      }
    }
  ],
  "auditService": "AuditService",
  "handler" : {
    "type" : "StaticResponseHandler",
    "config" : {
      "status" : 200,
      "headers" : {
        "Content-Type" : [ "text/plain; charset=UTF-8" ]
      },
      "entity" : "Message from audited route"
    }
  }
}

JsonAuditEventHandler

Logs events as JSON objects to a set of JSON files. There is one file for each topic defined in topics, named with the format topic.audit.json.

The JsonAuditEventHandler is the preferred file-based audit event handler.

Declare the configuration in an audit service, as described in AuditService.

Usage

{
  "name": string,
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [
    {
      "class": "org.forgerock.audit.handlers.json.JsonAuditEventHandler",
      "config": {
        "name": configuration expression<string>,
        "topics": [ configuration expression<string>, ... ],
        "logDirectory": configuration expression<string>,
        "elasticsearchCompatible": configuration expression<boolean>,
        "fileRotation": {
          "rotationEnabled": configuration expression<boolean>,
          "maxFileSize": configuration expression<number>,
          "rotationFilePrefix": configuration expression<string>,
          "rotationFileSuffix": configuration expression<string>,
          "rotationInterval": configuration expression<duration>,
          "rotationTimes": [ configuration expression<duration>, ... ]
        },
        "fileRetention": {
          "maxNumberOfHistoryFiles": configuration expression<number>,
          "maxDiskSpaceToUse": configuration expression<number>,
          "minFreeSpaceRequired": configuration expression<number>
        },
        "rotationRetentionCheckInterval": configuration expression<duration>,
        "buffering": {
          "writeInterval": configuration expression<duration>,
          "maxSize": configuration expression<number>
        }
      }
    }]
  }
}

Configuration

"name": configuration expression<string>, required

The event handler name. This property is used only to refer to the event handler, but is not used to name the generated log file.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"logDirectory": configuration expression<string>, required

The file system directory where this event handler writes log files.

When multiple AuditServices are defined in the deployment, prevent them from logging to the same audit logging file by setting different values for logDirectory.

elasticsearchCompatible: configuration expression<boolean>, optional

Set to true to enable compatibility with ElasticSearch JSON format. For more information, refer to the ElasticSearch documentation.

Default: false

"fileRotation": object, optional

File rotation settings for log files.

"rotationEnabled": configuration expression<boolean>, optional

A flag to enable rotation of log files.

Default: false.

"maxFileSize": configuration expression<number>, optional

The maximum file size of an audit log file in bytes. A setting of 0 or less indicates that the policy is disabled.

Default: 0.

"rotationFilePrefix": configuration expression<string>, optional

The prefix to add to a log file on rotation. This has an effect when time-based file rotation is enabled.

"rotationFileSuffix": configuration expression<string>, optional

The suffix to add to a log file on rotation, possibly expressed in SimpleDateFormat.

This has an effect when time-based file rotation is enabled.

Default: -yyyy.MM.dd-HH.mm.ss, where yyyy characters are replaced with the year, MM characters are replaced with the month, dd characters are replaced with the day, HH characters are replaced with the hour (00-23), mm characters are replaced with the minute (00-60), and ss characters are replaced with the second (00-60).

"rotationInterval": configuration expression<duration>, optional

The time interval after which to rotate log files. This duration must not be zero. This has the effect of enabling time-based file rotation.

"rotationTimes": array of configuration expression<durations>, optional

The durations, counting from midnight, after which to rotate files.

The following example schedules rotation six and twelve hours after midnight:

"rotationTimes": [ "6 hours", "12 hours" ]

This has the effect of enabling time-based file rotation.

"fileRetention": object, optional

File retention settings for log files.

"maxNumberOfHistoryFiles": configuration expression<number>, optional

The maximum number of historical audit files that can be stored. If the number exceeds this maximum, older files are deleted. A value of -1 disables purging of old log files.

Default: 0.

"maxDiskSpaceToUse": configuration expression<number>, optional

The maximum disk space in bytes that can be used for audit files. If the audit files use more than this space, older files are deleted. A negative or zero value indicates that this policy is disabled, and historical audit files can use unlimited disk space.

Default: 0

"minFreeSpaceRequired": configuration expression<string>, optional

The minimum free disk space in bytes required on the system that houses the audit files. If the free space drops below this minimum, older files are deleted. A negative or zero value indicates that this policy is disabled, and no minimum space requirements apply.

Default: 0

"rotationRetentionCheckInterval": configuration expression<string>, optional

Interval at which to periodically check file rotation and retention policies. The interval must be a duration, for example, 5 seconds, 5 minutes, or 5 hours.

Default: 5 seconds

"buffering": object, optional

Settings for buffering events and batch writes.

"writeInterval": configuration expression<duration>, optional

The interval at which to send buffered event messages. If buffering is enabled, this interval must be greater than 0.

Default: 1 second

"maxSize": configuration expression<number>, optional

The maximum number of event messages in the queue of buffered event messages.

Default: 10000

Example

For an example of setting up and testing this configuration, see Recording Access Audit Events in JSON.

JsonStdoutAuditEventHandler

Logs events to JSON standard output (stdout).

Declare the configuration in an audit service, as described in AuditService.

Usage

{
  "name": string,
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [
    {
      "class": "org.forgerock.audit.handlers.json.stdout.JsonStdoutAuditEventHandler",
      "config": {
        "name": configuration expression<string>,
        "topics": [ configuration expression<string>, ... ],
        "elasticsearchCompatible": configuration expression<boolean>
      }
    }
  }
}

Configuration

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

elasticsearchCompatible: configuration expression<boolean>, optional

Set to true to enable compatibility with ElasticSearch JSON format. For more information, refer to the ElasticSearch documentation.

Default: false

Example

In the following example, a JsonStdoutAuditEventHandler logs audit events. For an example of setting up and testing this configuration, refer to Recording access audit events to standard output.

{
  "name": "30-jsonstdout",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/jsonstdout-audit')}",
  "heap": [
    {
      "name": "AuditService",
      "type": "AuditService",
      "config": {
        "eventHandlers": [
          {
            "class": "org.forgerock.audit.handlers.json.stdout.JsonStdoutAuditEventHandler",
            "config": {
              "name": "jsonstdout",
              "elasticsearchCompatible": false,
              "topics": [
                "access"
              ]
            }
          }
        ],
        "config": {}
      }
    }
  ],
  "auditService": "AuditService",
  "handler": "ReverseProxyHandler"
}

NoOpAuditService

Provides an empty audit service to the top-level heap and its child routes. Use NoOpAuditService to prevent routes from using the parent audit service, when an AuditService is not explicitly defined.

For information about how to override the default audit service, refer to Audit framework.

Usage

{
  "name": "AuditService",
  "type": "NoOpAuditService"
 }
"auditService": "NoOpAuditService"

SyslogAuditEventHandler

An audit event handler that responds to events by logging messages to the UNIX system log as governed by RFC 5424, The Syslog Protocol.

Declare the configuration in an audit service, as described in AuditService.

Usage

{
  "class": "org.forgerock.audit.handlers.syslog.SyslogAuditEventHandler",
  "config": {
    "name": configuration expression<string>,
    "topics": [ configuration expression<string>, ... ],
    "protocol": configuration expression<string>,
    "host": configuration expression<string>,
    "port": configuration expression<number>,
    "connectTimeout": configuration expression<number>,
    "facility": configuration expression<string>,
    "buffering": {
        "enabled": configuration expression<boolean>,
        "maxSize": configuration expression<number>
    },
    "severityFieldMappings": [
      {
        "topic": configuration expression<string>,
        "field": configuration expression<string>,
        "valueMappings": {
          "field-value": object
        }
      }
    ]
  }
}

The values in this configuration object can use expressions as long as they resolve to the correct types for each field. For details about expressions, refer to Expressions.

Configuration

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"protocol": configuration expression<string>, required

The transport protocol used to send event messages to the Syslog daemon.

Set this to TCP for Transmission Control Protocol, or to UDP for User Datagram Protocol.

"host": configuration expression<string>, required

The hostname of the Syslog daemon to which to send event messages. The hostname must resolve to an IP address.

"port": configuration expression<number>, required

The port of the Syslog daemon to which to send event messages.

The value must be between 0 and 65535.

"connectTimeout": configuration expression<number>, required when using TCP

The number of milliseconds to wait for a connection before timing out.

"facility": configuration expression<enumeration>, required

The Syslog facility to use for event messages. Set to one of the following values:

  • kern: Kernel messages

  • user: User-level messages

  • mail: Mail system

  • daemon: System daemons

  • auth: Security/authorization messages

  • syslog: Messages generated internally by syslogd

  • lpr: Line printer subsystem

  • news: Network news subsystem

  • uucp: UUCP subsystem

  • cron: Clock daemon

  • authpriv: Security/authorization messages

  • ftp: FTP daemon

  • ntp: NTP subsystem

  • logaudit: Log audit

  • logalert: Log alert

  • clockd: Clock daemon

  • local0: Local use 0

  • local1: Local use 1

  • local2: Local use 2

  • local3: Local use 3

  • local4: Local use 4

  • local5: Local use 5

  • local6: Local use 6

  • local7: Local use 7

"buffering": object, optional

Buffering settings for writing to the system log facility. The default is for messages to be written to the log for each event.

"enabled": configuration expression<boolean>, optional

Whether log buffering is enabled.

Default: false.

"maxSize": configuration expression<number>, optional

The maximum number of buffered event messages.

Default: 5000.

"severityFieldMappings": object, optional

Severity field mappings set the correspondence between audit event fields and Syslog severity values.

The severity field mappings object has the following fields:

"topic": configuration expression<string>, required

The audit event topic to which the mapping applies.

Set this to a value configured in topics.

"field": configuration expression<string>, required

The audit event field to which the mapping applies.

Audit event fields use JSON pointer notation, and are taken from the JSON schema for the audit event content.

"valueMappings": object, required

The map of audit event values to Syslog severities, where both the keys and the values are strings.

Syslog severities are one of the following values:

  • emergency: System is unusable.

  • alert: Action must be taken immediately.

  • critical: Critical conditions.

  • error: Error conditions.

  • warning: Warning conditions.

  • notice: Normal but significant condition.

  • informational: Informational messages.

  • debug: Debug-level messages.

Example

The following example configures a Syslog audit event handler that writes to the system log daemon on syslogd.example.com, port 6514 over TCP with a timeout of 30 seconds. The facility is the first one for local use, and response status is mapped to Syslog informational messages:

{
  "class": "org.forgerock.audit.handlers.syslog.SyslogAuditEventHandler",
  "config": {
    "name": "MySyslogAuditEventHandler",
    "topics": ["access"],
    "protocol": "TCP",
    "host": "https://syslogd.example.com",
    "port": 6514,
    "connectTimeout": 30000,
    "facility": "local0",
    "severityFieldMappings": [
      {
        "topic": "access",
        "field": "response/status",
        "valueMappings": {
          "FAILED": "INFORMATIONAL",
          "SUCCESSFUL": "INFORMATIONAL"
        }
      }
    ]
  }
}

SplunkAuditEventHandler (deprecated)

This object is deprecated; use SyslogAuditEventHandler or JsonAuditEventHandler instead. For more information, refer to the Deprecated section of the Release Notes.

The Splunk audit event handler logs IG events to a Splunk system.

For an example of setting up and testing Splunk, see Recording access audit events in Splunk.

Usage

Configure the SplunkAuditEventHandler within an AuditService:

{
  "type": "AuditService",
  "config": {
    "config": {},
    "eventHandlers": [{
      "class": "org.forgerock.audit.handlers.splunk.SplunkAuditEventHandler",
      "config": {
        "name": configuration expression<string>,
        "topics": [ configuration expression<string>, ... ],
        "enabled": configuration expression<boolean>,
        "connection": {
          "useSSL": configuration expression<boolean>,
          "host": configuration expression<string>,
          "port": configuration expression<number>
        },
        "buffering": {
          "maxSize": configuration expression<number>,
          "writeInterval": configuration expression<duration>,
          "maxBatchedEvents": configuration expression<number>
        },
        "authzToken": configuration expression<string>
      }
    }]
  }
}

The SplunkAuditEventHandler relays audit events to Splunk through the HTTP protocol, using a handler defined in a heap. The handler can be of any kind of handler, from a simple ClientHandler to a complex Chain, composed of multiple filters and a final handler or ScriptableHandler.

IG searches first for a handler named SplunkAuditEventHandler. If not found, IG searches for a client handler named AuditClientHandler. If not found, IG uses the route’s default client handler, named ClientHandler.

The following example configures a ClientHandler named SplunkClientHandler:

{
  "name": "SplunkClientHandler",
  "type": "ClientHandler",
  "config": {}
}

The following example configures a ScriptableHandler named AuditClientHandler:

{
  "name": "AuditClientHandler",
  "type": "ScriptableHandler",
  "config": {}
}

Configuration

"name": configuration expression<string>, required

The name of the event handler.

"topics": array of configuration expression<strings>, required

One or more topics that this event handler intercepts. IG can record the following audit event topics:

  • access: Log access audit events. Access audit events occur at the system boundary, and include the arrival of the initial request and departure of the final response.

    To record access audit events, configure AuditService inline in a route, or in the heap.

  • customTopic: Log custom audit events. To create a topic for a custom audit event, include a JSON schema for the topic in your IG configuration.

    To record custom audit events, configure AuditService in the heap, and refer to it from the route or subroutes. For an example of how to set up custom audit events, refer to Record custom audit events.

"enabled": configuration expression<boolean>, required

Specifies whether this audit event handler is enabled.

"connection": object, optional

Connection settings for sending messages to the Splunk system. If this object is not configured, it takes default values for its fields. This object has the following fields:

"useSSL": configuration expression<boolean>, optional

Specifies whether IG should connect to the audit event handler instance over SSL.

Default: false

"host": configuration expression<string>, optional

Hostname or IP address of the Splunk system.

Default: localhost

"port": configuration expression<number>, optional

The dedicated Splunk port for HTTP input.

Before you install Splunk, make sure this port is free. Otherwise, change the port number in Splunk and in the IG routes that use Splunk.

Default: 8088

"buffering": object, optional

Settings for buffering events and batch writes. If this object is not configured, it takes default values for its fields. This object has the following fields:

"maxSize": configuration expression<number>, optional

The maximum number of event messages in the queue of buffered event messages.

Default: 10000

"maxBatchedEvents": configuration expression<number>, optional

The maximum number of event messages in a batch write to this event handler for each writeInterval.

Default: 500

"writeInterval": configuration expression<duration>, optional

The delay after which the writer thread is scheduled to run after encountering an empty event buffer.

Default: 100 ms (units of 'ms' or 's' are recommended)

"authzToken": configuration expression<string>, required

The authorization token associated with the configured HTTP event collector.

Example

In the following example, IG events are logged to a Splunk system.

{
  "name": "30-splunk",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/splunk-audit')}",
  "heap": [
    {
      "name": "AuditService",
      "type": "AuditService",
      "config": {
        "eventHandlers": [
          {
            "class": "org.forgerock.audit.handlers.splunk.SplunkAuditEventHandler",
            "config": {
              "name": "splunk",
              "enabled": true,
              "authzToken": "<splunk-authorization-token>",
              "connection": {
                "host": "localhost",
                "port": 8088,
                "useSSL": false
              },
              "topics": [
                "access"
              ],
              "buffering": {
                "maxSize": 10000,
                "maxBatchedEvents": 500,
                "writeInterval": "100 ms"
              }
            }
          }
        ]
      }
    }
  ],
  "auditService": "AuditService",
  "handler": "ReverseProxyHandler"
}

For an example of setting up and testing this configuration, see Recording Access Audit Events in Splunk.

Monitoring

The following sections describe monitoring endpoints exposed by IG, and the metrics available at the endpoints.

For information about how to set up and maintain monitoring, refer to Monitor services.

Vert.x Metrics

Vert.x metrics for HTTP clients, TCP clients, and servers are available by default at the Prometheus Scrape Endpoint and Common REST Monitoring Endpoint endpoints. Vert.x metrics provide low-level information about requests and responses, such as the number of bytes, duration, the number of concurrent requests. The available metrics are based on those described in Vert.x core tools metrics.

For more information about Vert.x and IG, refer to the vertx object in AdminHttpApplication (admin.json), and Monitoring Vert.x Metrics.

Monitoring types

This section describes the data types used in monitoring:

Counter

Cumulative metric for a numerical value that only increases.

Gauge

Metric for a numerical value that can increase or decrease.

Summary

Metric that samples observations, providing a count of observations, sum total of observed amounts, average rate of events, and moving average rates across a sliding time window.

The Prometheus view does not provide time-based statistics, as rates can be calculated from the time-series data. Instead, the Prometheus view includes summary metrics whose names have the following suffixes or labels:

  • _count: number of events recorded

  • _total: sum of the amounts of events recorded

  • {quantile="0.5"}: 50% at or below this value

  • {quantile="0.75"}: 75% at or below this value

  • {quantile="0.95"}: 95% at or below this value

  • {quantile="0.98"}: 98% at or below this value

  • {quantile="0.99"}: 99% at or below this value

  • {quantile="0.999"}: 99.9% at or below this value

Timer

Metric combining time-series summary statistics.

Common REST views show summaries as JSON objects. JSON summaries have the following fields:

{
 "count": number,           // events recorded for this metric
 "max": number,             // maximum duration recorded
 "mean": number,            // total/count, or 0 if count is 0
 "min": number,             // minimum duration recorded for this metric
 "mean_rate": number,       // average rate
 "p50": number,             // 50% at or below this value
 "p75": number,             // 75% at or below this value
 "p95": number,             // 95% at or below this value
 "p98": number,             // 98% at or below this value
 "p99": number,             // 99% at or below this value
 "p999": number,            // 99.9% at or below this value
 "stddev": number,          // standard deviation of recorded durations
 "m15_rate": number,        // fifteen-minute average rate
 "m5_rate": number,         // five-minute average rate
 "m1_rate": number,         // one-minute average rate
 "duration_units": string,  // time unit used in durations
 "rate_units": string,      // event count unit and time unit used in rate
 "total": number            // sum of the durations of events recorded
}

Monitoring Endpoints

This section describes the monitoring endpoints exposed in IG.

Prometheus Scrape Endpoint

All ForgeRock products automatically expose a monitoring endpoint where Prometheus can scrape metrics, in a standard Prometheus format. For information about configuring Prometheus to scrape metrics, refer to the Prometheus website.

When IG is set up as described in the documentation, the endpoint is http://ig.example.com:8080/openig/metrics/prometheus.

For information about available metrics, refer to:

For an example that queries the Prometheus Scrape Endpoint, refer to Monitor the Prometheus Scrape Endpoint.

Common REST Monitoring Endpoint

All ForgeRock products expose a monitoring endpoint where metrics are exposed as a JSON format monitoring resource.

When IG is set up as described in the documentation, the endpoint is http://ig.example.com:8080/openig/metrics/api?_queryFilter=true.

For information about available metrics, refer to:

For an example that queries the Common REST Monitoring Endpoint, refer to Monitor the Common REST Monitoring Endpoint.

Throttling policies

To protect applications from being overused by clients, use a ThrottlingFilter with one of the following policies to limit how many requests clients can make in a defined time:

MappedThrottlingPolicy

Maps different throttling rates to different groups of requests, according to the evaluation of throttlingRateMapper.

Usage

{
    "name": string,
    "type": "ThrottlingFilter",
    "config": {
        "requestGroupingPolicy": runtime expression<string>,
        "throttlingRatePolicy": {
            "type": "MappedThrottlingPolicy",
            "config": {
                "throttlingRateMapper": runtime expression<string>,
                "throttlingRatesMapping": {
                    "mapping1": {
                        "numberOfRequests": configuration expression<number>,
                        "duration": configuration expression<duration>
                    },
                    "mapping2": {
                        "numberOfRequests": configuration expression<number>,
                        "duration": configuration expression<duration>
                    }
                },
                "defaultRate": {
                    "numberOfRequests": configuration expression<number>,
                    "duration": configuration expression<duration>
                }
            }
        }
    }
}

Properties

"throttlingRateMapper": runtime expression<string>, required

An expression to categorize requests for mapping to a throttling rate in the throttlingRatesMapping.

If this parameter is null or does not match any specified mappings, the default throttling rate is applied.

"throttlingRatesMapping": object, required

A map of throttling rate by request group. Requests are categorized into groups by the evaluation of the expression "throttlingRateMapper".

"mapping1" and "mapping2": string, required

The evaluation of the expression "throttlingRateMapper".

The number of mappings is not limited to two.

"numberOfRequests": configuration expression<integer>, required

The number of requests allowed through the filter in the time specified by "duration".

"duration": configuration expression<duration>, required

A time interval during which the number of requests passing through the filter is counted.

"defaultRate": object, required

The default throttling rate to apply if the evaluation of the expression "throttlingRateMapper" is null or is not mapped to a throttling rate.

"numberOfRequests": configuration expression<integer>, required

The number of requests allowed through the filter in the time specified by "duration".

"duration": configuration expression<duration>, required

A time interval during which the number of requests passing through the filter is counted.

Example of a Mapped Throttling Policy

In the following example, requests from users with different statuses are mapped to different throttling rates. For information about how to set up and test this example, see Configure Mapped Throttling.

{
  "name": "00-throttle-mapped",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/throttle-mapped')}",
  "heap": [
    {
      "name": "SystemAndEnvSecretStore-1",
      "type": "SystemAndEnvSecretStore"
    },
    {
      "name": "AmService-1",
      "type": "AmService",
      "config": {
        "agent": {
          "username": "ig_agent",
          "passwordSecretId": "agent.secret.id"
        },
        "secretsProvider": "SystemAndEnvSecretStore-1",
        "url": "http://am.example.com:8088/openam/"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "name": "OAuth2ResourceServerFilter-1",
          "type": "OAuth2ResourceServerFilter",
          "config": {
            "scopes": [
              "mail",
              "employeenumber"
            ],
            "requireHttps": false,
            "realm": "OpenIG",
            "accessTokenResolver": {
              "name": "token-resolver-1",
              "type": "TokenIntrospectionAccessTokenResolver",
              "config": {
                "amService": "AmService-1",
                "providerHandler": {
                  "type": "Chain",
                  "config": {
                    "filters": [
                      {
                        "type": "HttpBasicAuthenticationClientFilter",
                        "config": {
                          "username": "ig_agent",
                          "passwordSecretId": "agent.secret.id",
                          "secretsProvider": "SystemAndEnvSecretStore-1"
                        }
                      }
                    ],
                    "handler": "ForgeRockClientHandler"
                  }
                }
              }
            }
          }
        },
        {
          "name": "ThrottlingFilter-1",
          "type": "ThrottlingFilter",
          "config": {
            "requestGroupingPolicy": "${contexts.oauth2.accessToken.info.mail}",
            "throttlingRatePolicy": {
              "name": "MappedPolicy",
              "type": "MappedThrottlingPolicy",
              "config": {
                "throttlingRateMapper": "${contexts.oauth2.accessToken.info.status}",
                "throttlingRatesMapping": {
                  "gold": {
                    "numberOfRequests": 6,
                    "duration": "10 s"
                  },
                  "silver": {
                    "numberOfRequests": 3,
                    "duration": "10 s"
                  },
                  "bronze": {
                    "numberOfRequests": 1,
                    "duration": "10 s"
                  }
                },
                "defaultRate": {
                  "numberOfRequests": 1,
                  "duration": "10 s"
                }
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

ScriptableThrottlingPolicy

Uses a script to look up the throttling rates to apply to groups of requests.

The script can store the mapping for the throttling rate in memory, and can use a more complex mapping mechanism than that used in the MappedThrottlingPolicy. For example, the script can map the throttling rate for a range of IP addresses. The script can also query an LDAP directory, an external database, or read the mapping from a file.

For information about script properties, available global objects, and automatically imported classes, refer to Scripts.

Usage

{
  "type": "ThrottlingFilter",
  "config": {
    "requestGroupingPolicy": runtime expression<string>,
    "throttlingRatePolicy": {
      "name": string,
      "type": "ScriptableThrottlingPolicy",
      "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 ScriptableThrottlingPolicy, refer to Scripts.

Example of a scriptable throttling policy

In the following example, the DefaultRateThrottlingPolicy delegates the management of throttling to the scriptable throttling policy. For information about how to set up and test this example, refer to Configure scriptable throttling.

{
  "name": "00-throttle-scriptable",
  "baseURI": "http://app.example.com:8081",
  "condition": "${find(request.uri.path, '^/home/throttle-scriptable')}",
  "heap": [
    {
      "name": "SystemAndEnvSecretStore-1",
      "type": "SystemAndEnvSecretStore"
    },
    {
      "name": "AmService-1",
      "type": "AmService",
      "config": {
        "agent": {
          "username": "ig_agent",
          "passwordSecretId": "agent.secret.id"
        },
        "secretsProvider": "SystemAndEnvSecretStore-1",
        "url": "http://am.example.com:8088/openam/"
      }
    }
  ],
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "name": "OAuth2ResourceServerFilter-1",
          "type": "OAuth2ResourceServerFilter",
          "config": {
            "scopes": [
              "mail",
              "employeenumber"
            ],
            "requireHttps": false,
            "realm": "OpenIG",
            "accessTokenResolver": {
              "name": "token-resolver-1",
              "type": "TokenIntrospectionAccessTokenResolver",
              "config": {
                "amService": "AmService-1",
                "providerHandler": {
                  "type": "Chain",
                  "config": {
                    "filters": [
                      {
                        "type": "HttpBasicAuthenticationClientFilter",
                        "config": {
                          "username": "ig_agent",
                          "passwordSecretId": "agent.secret.id",
                          "secretsProvider": "SystemAndEnvSecretStore-1"
                        }
                      }
                    ],
                    "handler": "ForgeRockClientHandler"
                  }
                }
              }
            }
          }
        },
        {
          "name": "ThrottlingFilter-1",
          "type": "ThrottlingFilter",
          "config": {
            "requestGroupingPolicy": "${contexts.oauth2.accessToken.info.mail}",
            "throttlingRatePolicy": {
              "type": "DefaultRateThrottlingPolicy",
              "config": {
                "delegateThrottlingRatePolicy": {
                  "name": "ScriptedPolicy",
                  "type": "ScriptableThrottlingPolicy",
                  "config": {
                    "type": "application/x-groovy",
                    "source": [
                      "if (contexts.oauth2.accessToken.info.status == status) {",
                      "  return new ThrottlingRate(rate, duration)",
                      "} else {",
                      "  return null",
                      "}"
                    ],
                    "args": {
                      "status": "gold",
                      "rate": 6,
                      "duration": "10 seconds"
                    }
                  }
                },
                "defaultRate": {
                  "numberOfRequests": 1,
                  "duration": "10 s"
                }
              }
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}

DefaultRateThrottlingPolicy

Provides a default throttling rate if the delegating throttling policy returns null.

Usage

{
   "name": string,
   "type": "ThrottlingFilter",
   "config": {
       "requestGroupingPolicy": expression,
       "throttlingRatePolicy": {
           "type": "DefaultRateThrottlingPolicy",
           "config": {
               "delegateThrottlingRatePolicy": ThrottlingRatePolicy reference,
               "defaultRate": {
                   "numberOfRequests": configuration expression<number>,
                   "duration": configuration expression<duration>
               }
           }
       }
   }
}

Properties

"delegateThrottlingRatePolicy": ThrottlingRatePolicy reference, required

The policy to which the default policy delegates the throttling rate. The DefaultRateThrottlingPolicy delegates management of throttling to the policy specified by delegateThrottlingRatePolicy.

If delegateThrottlingRatePolicy returns null, the defaultRate is used.

For information about policies to use, refer to MappedThrottlingPolicy and ScriptableThrottlingPolicy.

"defaultRate": object, required

The default throttling rate to apply if the delegating policy returns null.

"numberOfRequests": configuration expression<integer>, required

The number of requests allowed through the filter in the time specified by "duration".

"duration": configuration expression<duration>, required

A time interval during which the number of requests passing through the filter is counted.

Example

For an example of how this policy is used, refer to Example of a Scriptable Throttling Policy.

Miscellaneous configuration objects

The following objects can be defined in the configuration:

AmService

Holds information about the configuration of an instance of AM. The AmService is available to IG filters that communicate with that instance.

When IG uses an AmService, IG is positioned as the client of the service. By default, IG is subscribed to Websocket notifications from AM, and the WebSocket connection can be secured by ClientTlsOptions.

Usage

{
  "name": string,
   "type": "AmService",
   "config": {
     "agent": object,
     "secretsProvider": SecretsProvider reference,
     "notifications": object,
     "realm": configuration expression<string>,
     "amHandler": Handler reference,
     "sessionCache": object,
     "sessionIdleRefresh": object,
     "sessionProperties": [ configuration expression<string>, ... ],
     "ssoTokenHeader": configuration expression<string>,
     "url": configuration expression<url>,
     "version": configuration expression<string>
   }
}

Properties

"agent": object, required

An IG agent profile. When the agent is authenticated, the token can be used for tasks such as getting the user’s profile, making policy evaluations, and connecting to the AM notification endpoint.

{
  "AmService": {
     "username": configuration expression<string>,
     "passwordSecretId": configuration expression<secret-id>,
     "password": configuration expression<string> //deprecated
   }
}
"username": configuration expression<string>, required

Name of the AM agent profile.

"passwordSecretId": configuration expression<secret-id>, required

The secret ID of the AM agent password. This secret ID must point to a GenericSecret.

"password": configuration expression<string>, required
This property is deprecated and is not considered secure. Use passwordSecretId instead. For more information, refer to the Deprecated section of the Release Notes.

The agent password.

"secretsProvider": SecretsProvider reference, optional

The SecretsProvider object to query for the agent password. For more information, see SecretsProvider.

Default: The route’s default secret service. For more information, see Default secrets object.

"realm": configuration expression<string>, optional

The AM realm in which the IG agent is created.

Default: / (top level realm).

"amHandler": Handler reference, optional

The Handler to use for communicating with AM. In production, use a ClientHandler that is capable of making an HTTPS connection to AM.

AmService does not use amHandler to subscribe to WebSocket notifications from AM. To subscribe to WebSocket notifications from AM, configure a ClientTlsOptions object in the heap, and refer to it from the amHandler object and the notifications subproperty tls .

To facilitate auditing, configure this handler with a ForgeRockClientHandler, which sends a ForgeRock Common Audit transaction ID when it communicates with protected applications.

Alternatively, configure this handler as a chain containing a TransactionIdOutboundFilter, as in the following configuration:

"amHandler": {
  "type": "Chain",
  "config": {
    "handler": "MySecureClientHandler",
    "filters": [ "TransactionIdOutboundFilter" ]
  }
}

Default: ForgeRockClientHandler

See also Handlers and ClientHandler.

"notifications": object, optional

Configure a WebSocket notification service to subscribe to Websocket notifications from AM.