Processors
Processors transform values returned from PingOne Authorize attributes and services.
Use processors to manipulate and transform data, including extracting details from structured data, or converting data to different formats.
Add processors directly to a resolver when you define attributes and services, or define them on the Processors tab as named processors to make them reusable.
You can copy a processor defined on the Processors tab for reuse by selecting Make Copy from the hamburger menu of that processor. If you copy a processor with children, only the parent is duplicated. |
You can use the following types of processors:
-
Collection Filter
-
Collection Transform
-
JSON Path
-
X Path
-
SpEL
-
Named
Set up a chain of one or more processors to transform an attribute value each time it is obtained from a resolver. The input to the first processor in the chain is the value that comes from the resolver. The input to subsequent processors is the previous processor in the chain. You can drag collapsed processors to rearrange their order.
Processors have a type that indicates what the output data type should be after applying the expression. In attribute comparisons, data type mismatches are a common source of errors. For more information about debugging these kinds of problems, see Examining recent decisions. |
Collection filter
When the data being processed has a value type of Collection, you can set a filter to examine each item in the collection and keep only the items that satisfy some condition. A collection filter uses a value processor to yield a true
or false
evaluation for each item in the collection. When true
, the original item goes in the resulting collection. When false
, it’s omitted.
To prevent errors, make sure that the data has a value type of Collection when you use a collection filter. For example, a common error in a chain of processors is defining data that is a JSON array as JSON in the previous processor. |
Each item in the collection can optionally be preprocessed by one or more value processors before applying the condition. For example, suppose you received a collection of JSON objects from a service invocation and you want to filter the items by the score
field. The input data might look like the following:
[ { "name": "Alice", "role": "Sender", "score": 72 }, { "name": "Bob", "role": "Receiver", "score": 36 }, { "name": "Carol", "role": "Observer", "score": 47 }, { "name": "Dave", "role": "Attacker", "score": 99 } ]
A collection filter processor could achieve this by using a JSON Path preprocessor to extract the score
:
$.score
The following SpEL condition yields a true or false decision for each item:
#this.value > 50
Each list item is in turn passed through the preprocessor and the condition. The first item has score 72, which is greater than 50 so the condition yields true and the item is retained for the result collection. The second and third items have scores less than 50, so the condition yields false
and these items are omitted. The final item also has a score higher than 50 and is retained.
The result of the collection filter is:
[ { "name": "Alice", "role": "Sender", "score": 72 }, { "name": "Dave", "role": "Attacker", "score": 99 } ]
The values produced by the preprocessing and condition are only used to determine inclusion. The final result of a collection filter consists of those original collection items that satisfied the predicate after preprocessing.
If the condition or preprocessing produces an error for any item in the input collection (for example, if a score
field is missing or not a number in the source data), the whole collection filter is considered to have failed.
Collection transform
When the data being processed has a value type of Collection, you can set a transform to apply a processor or a sequence of processors to each item in the collection.
Assume that you have the following input collection:
[ { "name": "Alice", "role": "Sender", "score": 72 }, { "name": "Bob", "role": "Receiver", "score": 36 }, { "name": "Carol", "role": "Observer", "score": 47 }, { "name": "Dave", "role": "Attacker", "score": 99 } ]
The following JSON Path processor extracts the name
field for each item:
$.name
This SpEL processor converts each name
to upper case:
#string.upperCase(#this.value)
The resulting collection consists of just the extracted names converted to upper case, preserving the order of the original collection:
[ "ALICE", "BOB", "CAROL", "DAVE" ]
If the item processor produces an error for any item, the overall collection transform processor produces an error.
JSON Path
With JSON Path, you can extract data from JSON objects. For example, assume you have a service that resolves to the following JSON:
{
"name": "Joe Bloggs",
"requestedItems": [
{
"id": "b5f963fa-111e-49ff-994b-b89a20a2c1d5",
"price": 125.00
},
{
"id": "84e204dd-44f5-4a84-8e58-972c2a9c80b4",
"price": 299.99
}
]
}
To extract the price
fields of all requested items, we set the Value Processor to JSON Path with the expression $.requestedItems[*].price
.
For another example, assume that you want to extract errors with a status of 403 from the following API response:
{
"errors": [
{
"status": "403",
"source": {
"pointer": "/data/attributes/statements"
},
"detail": "Error 403 - Forbidden."
},
{
"status": "403",
"source": {
"pointer": "/resources/lightwave"
},
"detail": "You don't have permission to access this resource."
},
{
"status": "422",
"source": {
"pointer": "/data/attributes/volume"
},
"detail": "Volume does not, in fact, go to 11."
},
{
"status": "500",
"source": {
"pointer": "/data/attributes/reputation"
},
"title": "The backend responded with an error",
"detail": "Reputation service not responding after three requests."
}
]
}
Set the Value Processor to JSON Path with the expression $.errors[?(@.status == '403')]
.
The resulting collection consists of the extracted errors:
[ { "status": "403", "source": { "pointer": "/data/attributes/statements" }, "detail": "Error 403 - Forbidden." }, { "status": "403", "source": { "pointer": "/resources/lightwave" }, "detail": "You don't have permission to access this resource." }, ]
For more information about JSON Path expressions, see https://github.com/json-path/JsonPath.
X Path
XPath is the XML-equivalent for JSON Path and follows a very similar syntax. For more information about XPath expressions, see the XPath tutorial on w3schools.com.
PingOne Authorize policies only support the use of XPath 1.0. Functions added in later versions are not available. |
SpEL
You can perform more complicated data processing with PingOne Expression Language, a customized derivation of the Spring Expression Language (SpEL). Expressions are applied directly to the resolved value.
For example, assume you want to search for a substring that matches the following regular expression:
\[[0-9]*\.[0-9]\]
Set the processor to SpEL and set the expression to the following:
matches(\[[0-9]*\.[0-9]\])
Interpolate attribute values directly into the SpEL expression using curly brackets, which can be useful if you want to combine multiple attribute values into a single value:
{{Customer.Age}} - {{State.Drinking Age}} >= 0
You can concatenate interpolated attributes with strings in SpEL expressions. In the following example, a SpEL expression is used to dynamically concatenate a string with a user’s account number to create a transaction verification message:
"Account " + {{Customer.AccountNumber}} + " has been charged."
Be careful not to wrap an interpolated attribute with quotes. |
PingOne’s expression language differs from SpEL as follows:
-
Some SpEL features are disabled or restricted. For example,
T(xyz)
syntax for invoking Java static functions is not supported. For more information, see Disabled and restricted SpEL features. -
References to the value being processed by the expression must use
#root.value
instead of#root
. For more information, see Variables. -
Instead of invoking Java methods for handling data values, you must use the custom library functions provided by PingOne’s expression language.
Learn more about SpEL in the official Spring Framework documentation.
Named
Named processors allow you to extract processor logic into a reusable component, which helps abstract some of the complexity when you define an attribute or a service. Also, it reduces repetition and allows commonly used logic to be updated in a single place.
Define named processors outside of an attribute on the Processors tab in the Trust Framework. You can also create inline value processors for attributes and services that co-exist with named processors.