OpenID Connect request mapping Open Banking intent ID
When a third-party application wants to initiate a transaction that requires user authorization (for example, payment transfer), it uses an API that is provided by the financial institution or bank to register the details of the transaction. For example, it registers the amount of the transaction and the type of currency. This process is sometimes referred to as "lodging an intent". The API responds with an intent identifier, also called a Consent ID in UK Open Banking specifications. The application initiates an OAuth authorization code flow to get user authorization that is recorded as a user consent.
- Extract the intent ID from the request.
- Obtain the intent context information, usually by calling the bank's API.
- Choose how to represent the authorization in the
id_token
as a claim or scope value.
Available input objects
Because this custom rule is run after authentication but before authorization, the information that is available does not include all possible domain objects. They are limited to the following types.
- HTTP request context
- When a user logs in to Verify, the incoming HTTP
request context can be accessed in the request-mapping rule. All OAuth request parameters, such as
claims
andscope
, are available in thisrequestContext
. The general structure and use ofrequestContext
is described in the "HTTP Request Context" section of the Attribute functions.For simplicity of access, certain values are precomputed in therequestContext
. Theclaims
request parameter is generally represented as a JSON like the following example.{ "id_token": { "claim_name": { "essential": false, "value": "some_value" } }, "userinfo": { "claim_name": { "essential": false, "value": "some_value" } } }
This JSON can be cumbersome to access and so the key that is used in the
requestContext
is in the formatclaims_claimType_claimName
. TheclaimType
is eitheruserinfo
oridtoken
. Note the missing underscore. Thus, with the previous example, theclaim_name
value can be obtained by usingrequestContext.getValue('claims_idtoken_claim_name')
.Similarly,
scope
is computed and split by a space to build a string array. - Identity source credential
-
When a user logs in to Verify, the identity source credential attributes are added into the login session and can be accessed in the request-mapping rule.
Theidsuser
domain object is available as a map with a string key and a string array value. For example,
For more information, see Attribute functions.{ "realmName": ["cloudIdentityRealm"], "displayName": ["Jessica J. Hill"], "phone": ["+12324321234"] }
- Other functions and operators
-
Standard operators and functions are available in the mapping rule. The HTTP client is also available to make outbound requests. Other supported functions include hashing and timestamps. See the relevant sections in the Attribute functions.
Return object
Because this custom rule must be interpreted to build an authorization context, the return value of this rule must be a JSON object that must include the following mandatory properties:
Property | Type | Required? | Description |
---|---|---|---|
type |
String | Yes | The type indicates the type of transaction that is being performed. For example, a payment
initiation. This is represented in Verify as a Data Privacy Purpose. The purpose ID that is provided
or generated by the system is the value of type . |
intentID |
String | Yes | The intent ID must be supplied. It is usually computed from the
requestContext . |
claims |
JSON object. JSON property value can be of any type. | No | Typically, on user authorization, the ID token that is generated contains some indication
that the user authorized the transaction that is identified by the intent ID. The
claims is a JSON object or map, where the key is the claim name and the value can
be any JSON-compatible structure, such as string, integer, another object, array, or other
structures. Multiple claims can also be specified. |
scope |
String | No | If the request is authorized, this value is added to the granted scopes. |
Any additional attributes, such as the amount or currency is treated as custom attributes. They can be shown in the user consent page by using the corresponding template macros that are described later.
UK Open Banking example
- A payment initiation service provider (PISP) that resides on the third-party provider and initiates the payment transaction.
- An account Information service provider (ASPSP) authorization server. In this scenario, the ASPSP is Verify.
- An ASPSP resource server that hosts the payment initiation API.
- Extract the intent ID.
- Retrieve information about this transaction from the resource server.
- Extracting the intent ID from the request
- This example follows the UK Open Banking standard of sending the intent ID through the
claims
. The incoming authorization request contains theopenbanking_intent_id
in the claims.
The claims are extracted and made available in the request context. The code that is used to retrieve the value is{ "id_token": { "openbanking_intent_id": { "value": "b508f9df-799b-4120-a13e-5d09f2931fa6", "essential": true } } }
requestContext.getValue('claims_idtoken_openbanking_intent_id')
- Retrieve transaction information
- Transaction information is stored in the Account Servicing Payment Service Provider (ASPSP)
resource server, which is where the consent or intent ID was generated. Use the HTTP client to make
a request to the resource server. The following request is an
example.
hc.getAsJSON("https://resource.myaspsp.com/internal/intents/" + context.intentID
- Map transaction to a privacy purpose and claims
- To capture Open Banking payment initiation and account access consents, relevant privacy
purposes must be created. For example, a
payment_initiation
privacy purpose must be created for any payment initiation consent requests. This purpose is then mapped to thetype
property in the return object.Additionally, for UK Open Banking, anopenbanking_intent_id
claim needs to be created. The remaining information about the transaction can also be added to the return object.{ "type": "payment_initiation", "intentID": "b508f9df-799b-4120-a13e-5d09f2931fa6", "currency": "USD", "amount": "1200.35", "merchant": "Merchant A", "claims": { "openbanking_intent_id": "b508f9df-799b-4120-a13e-5d09f2931fa6" } }
- Sample mapping rule
-
statements: - if: match: "!has(requestContext.claims_idtoken_openbanking_intent_id)" return: null - context: "intentID := requestContext.getValue('claims_idtoken_openbanking_intent_id')" - context: 'intentContext := hc.getAsJSON("https://resource.myaspsp.com/internal/intents/" + context.intentID, { "Authorization": "apikey supersecretapikey" })' - return: >- { "type": context.intentContext.type, "intentID": context.intentID, "currency": context.intentContext.instructedAmount.currency, "amount": context.intentContext.instructedAmount.amount, "merchant": context.intentContext.creditorName, "claims": { "openbanking_intent_id": context.intentID } }
Customizing the consent page
Because the consent user experience for transaction authorization differs from standard OAuth and Open ID Connect scope consent, a custom section can be created in the consent page template, see Modify single sign-on for OpenID pages.
[RPT purpose_payment_initiation]
<input type="hidden" name="@PRIVACY_SCOPE_PNAME_REPEAT@"
value="@PRIVACY_SCOPE_REPEAT@" privacy-readonly="true" />
<input type="hidden" id="@PRIVACY_SCOPE_PNAME_REPEAT@_state" name="@PRIVACY_SCOPE_PSTATE_REPEAT@"
value="CONSENT_ALLOW" privacy-required="@PRIVACY_SCOPE_REQUIRED_REPEAT@" />
<div id="@PRIVACY_SCOPE_PNAME_REPEAT@_widget" class="bx--form-item" style="width:350px;"></div>
<div class="bx--grid" style="padding-left:0">
<div class="bx--row" style="padding-bottom:6px;">
<div class="bx--col-sm-1">Amount</div>
<div class="bx--col">@PRIVACY_SCOPE_CUSTOM_currency@ @PRIVACY_SCOPE_CUSTOM_amount@</div>
</div>
<div class="bx--row" style="padding-bottom:6px;">
<div class="bx--col-sm-1">Merchant</div>
<div class="bx--col">@PRIVACY_SCOPE_CUSTOM_merchant@</div>
</div>
<div class="bx--row" style="padding-bottom:6px;">
<div class="bx--col-sm-1">Reference</div>
<div class="bx--col">@PRIVACY_SCOPE_ATTRVALUE_REPEAT@</div>
</div>
</div>
[ERPT purpose_payment_initiation]
Notice the following aspects.- A new repeatable section that is used for a specific Data Privacy purpose. The name that is used
follows the format
purpose_{purposeID}
. ThepurposeID
is the Data Privacy purpose ID. This purpose ID can be system-generated or user-provided. - Two HTML Form fields are essential and are named
@PRIVACY_SCOPE_PNAME_REPEAT@
and@PRIVACY_SCOPE_PNAME_REPEAT@_state
. The first field contains the Verify identifier for the consent record. The second field contains the state of consent. - Custom attributes that are returned by the advanced rule can be referenced by using the macro
@PRIVACY_SCOPE_CUSTOM_{attributeName}@
. For example,@PRIVACY_SCOPE_CUSTOM_currency@
is replaced by the currency value that is returned in the intent advanced rule.