Identity Service — Relying Party Developer Guide

identity_flow_puml_rp_view

1. Introduction: Identity Data

Before we go into the details of the identity flow, we introduce the basic concepts behind the data available through the identity service.

What kind of data is needed depends on your business case. If you need advice, feel free to talk to your contact!

1.1. Verified and Unverified Data

Generally speaking, the Identity Service offers the retrieval of verified and unverified user information. Some data fields (called claims in OpenID Connect) are available both as unverified claims and as verified claims. In one request, all types of claims can be combined. As a rule of thumb, unverified data is generally free, verified data is generally priced according to the price list.

Verified Claims: A selected set of data is available as verified claims. The data comes from the IDP’s KYC processes (for example, during the set-up of a new bank account), maintained according to the respective anti-money laundering laws. The available claims include certain data about the user (name, address, nationalities, and other data) as well as data from the verification process itself, for example, the ID card or passport number, date of issuance, and the issuer.

Unverified claims: This data can be used for all purposes where you would normally accept self-declared data from a user, i.e., to replace form filling. There is no guarantee on the correctness of the data and the IDP may give the user the option to edit the data before it is transmitted to you. For example, if you have a sign up form in a web shop, but would give the user the option to use the data from their online banking, you can use the unverified data provided by the Identity Service to speed up the process. This data includes, for example, name, address, email address, phone number, gender, and salutation.

The following table shows a selection of the most important claims, see Appendix 1 - User Information and Appendix 2 - Verified Claims for claim details, data formats, and the request syntax.

Availability: U = unverified, V = verified, S = special (see notes).

Claim Type* Notes

Pseudonymous Identifier

S

OpenID Connect sub field. Constant identifier, e.g., for login purposes. Unique in the ecosystem when combined with the issuer identifier (iss). IDPs can map this identifier to an onlinebanking user. Not editable by the user. Automatically contained in all responses.

Given/Family Name

U or V

Date and Place of Birth

U or V

Nationalities

U or V

Address

U or V

Gender, Salutation, Title

U

E-mail

U

Phone number

U

Tax ID

S

Not editable by the user.

IBAN

S

User can select one IBAN if multiple are associated with the online banking account. Not editable by the user.

ID document type, issuer, etc.

V

Transaction Identifier

S

For audit purposes. Not editable by the user.

1.2. Userinfo vs. ID Token

OpenID Connect defines two ways for transferring claims to the relying party: Via the ID Token or via the Userinfo endpoint. The ID Token is transmitted directly in the response from the token endpoint (which needs to be called in any case). See Step 22 in the chart above. The userinfo endpoint needs to be called separately, using the access token acquired from the token endpoint. This is shown in the optional Steps 25 and 26 above. Using the claims parameter, you can define at which endpoint you want to retrieve which data, see the next example.

As a relying party, you are free to use either of the methods for both verified and unverified data.

The ID Token is available without having to do another request/response round trip, slightly reducing overall latency. Therefore, the ID Token is generally preferable.

1.3. Availability of Data and Billing

Most claims are "Mandatory to Implement" for IDPs (see details in Appendix 1 - User Information and Appendix 2 - Verified Claims). Nonetheless, due to unavailable data or for technical reasons, some claims can be unavailable in rare cases. In this case, the respective claim is omitted in the response.

It is therefore important to check that all required information for your business case have been returned from the flow.

Claims that are billed (generally, verified data, see your contract for details), are billed each time the claim is transferred from the IDP to you. That is, if you request the same claim both in the ID Token and in the Userinfo endpoint, you will be billed for the claim twice. If you request the data multiple times from the Userinfo endpoint, you will be billed for each request.

You can mark certain claims as "essential" in the request (see example below). If one or more claims marked as essential are not available, the delivery of the other claims will not be billed.

1.4. Requesting Claims

The way claims can be requested follows the convention introduced by the OpenID Connect specification (cf. OpenID Connect Specification). Basically, the claims are added to the respective section (id_token or userinfo, depending on how you request user infos) of the claims. Verified claims are contained in a special structure, verified_claims. For details, see Appendix 2 - Verified Claims.

An example is shown in the following:

Example 3. Requesting Claims using the claims Parameter

The following JSON document shows contents of the claims parameter in the authentication request.

In this example, the phone number, salutation (both unverified), and the IBAN are retrieved in the ID Token. The user identifier (sub) will also be contained in the ID Token.

From the userinfo endpoint, address and the tax ID are retrieved as unverified claims. The name, birthdate, place of birth, and nationalities are requested as verified claims. Name and birthdate are marked as essential - when either of the claims is not available to the IDP, the rest of the claims will be delivered, but not billed.

Please refer to the OpenID Connect Specification for details on the basic syntax and to Appendix 2 - Verified Claims for details on the contents of verified_claims.

{
   "id_token":{
      "phone_number": null,
      "salutation": null,
      "https://www.openbanking.verimi.cloud/claims/preferred_iban":null
   },
   "userinfo":{
      "verified_claims": {
         "verification": {
            "trust_framework": null
         },
         "claims": {
            "given_name":{
               "essential": true
            },
            "family_name":{
               "essential": true
            },
            "birthdate":{
               "essential": true
            },
            "place_of_birth":null,
            "nationalities":null
         }
      },
      "address":null,
      "https://www.openbanking.verimi.cloud/claims/tax_id":null
   }
}

2. Issuer URI Check

Before you can start the identity flow, you need to send the user to the account chooser, as described in the base document. You will receive an issuer URI from that process.

After you got back the issuer URI from the Account Chooser you have to check if the IDP (which belongs to the Issuer URI) is valid and active.

This check MUST take place in the backend, not in the user’s browser.

To do this, you have to perform a GET request to the following endpoint with the Issuer URI as a URL query parameter: https://accounts.sandbox.openbanking.verimi.cloud/idp/?iss={issuer_url} for the sandbox or https://accounts.openbanking.verimi.de/idp/?iss={issuer_url} for the production environment.

Make sure to URL-encode the iss parameter properly, as with all URL parameters.
Example 4. Issuer URI Check Call

Request:

GET accounts.sandbox.openbanking.verimi.cloud/idp/?iss=https%3A%2F%2Ftestidp
       .sandbox.yes.com%2Fissuer%2F10000001
Host: accounts.sandbox.openbanking.verimi.cloud

Response:

HTTP/1.1 204

The API returns an HTTP status code and an empty body.

  • If the IDP is found and active, the returned status code is 204 (no content).

  • If the Issuer URI is not a valid URI, the returned status code is 400 (bad request).

  • If the IDP is not found, the returned status code is 404 (not found).

  • If the IDP is found but not active, the returned status code is 423 (locked).

In the case of status code 204 (no content) you can perform the redirect to the IDP, otherwise you have to do an exception handling.

The flow may only be continued with the status code 204. All other codes must be treated as an error and the user has to be informed that she cannot continue with her bank at the moment.

3. OpenID Connect Process

Now your app is prepared to talk to the OP in order to authenticate the user and get access to her personal data (so-called "claims").

The issuer_url, obtained in the previous step, points to a identity service-compliant OpenID Connect OP.

Using OpenID Libraries

Using an existing OpenID library is the best way to implement the following steps. You save a lot of implementation work and get battle-proven, secure code.

Before deciding for a library, we recommend to check for the following features:

  • Does the library support OpenID Connect Discovery?

  • Can the issuer URI be configured during run-time?
    (Some implementations only support one or a number of fixed issuer URIs, while the issuer URI in the identity service is determined dynamically, as described before.)

  • Does the library support TLS Client Authentication using a self-signed certificate at the Token Endpoint as defined in RFC8705?

  • And, if you want to retrieve verified claims in a conveniant way: Does the library support OpenID Connect for Identity Assurance? (Most libraries will not support this yet - don’t worry, it’s not hard to implement.)

The list of OpenID-certified client libraries is a good starting point to find suitable implementations.

3.1. OpenID Connect Configuration

Each identity service-compliant OP provides an OpenID Provider Configuration accessible via a GET request to {issuer_url}/.well-known/openid-configuration. Your app uses this configuration to determine the different endpoint URLs and further metadata that will be used in the course of the OpenID Connect process.

The OpenID configuration is a JSON document which contains (amongst others) the following attributes:

  • issuer REQUIRED: the OpenID Connect issuer URL of this OP.

This value MUST exactly match the issuer_url.
  • jwks_uri REQUIRED: The URI to the public keys (JWK Set) needed to validate the signature of ID tokens issued by this OP.

  • authorization_endpoint REQUIRED: the URL the Authentication Request is sent to

  • token_endpoint REQUIRED: the URL of the token endpoint that is later in the protocol used to exchange the authorization code for tokens and identity claims

  • userinfo_endpoint REQUIRED: the URL to get identity claims from if the UserInfo Endpoint is used.

  • claims_supported REQUIRED: the list of claims supported by this OP. For a list of claims see Appendix 1 - User Information and Appendix 2 - Verified Claims.

  • acr_values_supported REQUIRED: this claim publishes all Authentication Context Class References supported by the OP For a list of acr values see acr values.

  • claims_in_verified_claims_supported REQUIRED: JSON array containing all claims supported within the verified claims.

  • id_documents_supported and id_documents_verification_methods_supported REQUIRED: JSON arrays containing all id document identifiers and verification method identifiers supported within the verified claims.

Example 5. Retrieving the OpenID Configuration

Request:

GET testidp.sandbox.openbanking.verimi.cloud/issuer/10000001/.well-known/openid-configuration
Accept: application/json
Host: testidp.sandbox.openbanking.verimi.cloud

Response (abbreviated):

HTTP/1.1 200
Content-type: application/json;charset=UTF-8
Content-length: 7258

{
   "authorization_endpoint":"https://...",
   "token_endpoint":"https://...",
   "registration_endpoint":"https://...",
   "issuer":"https://testidp.sandbox.openbanking.verimi.cloud/issuer/10000001",
   ...
}

3.2. Authentication Request

Now that you know the authorization endpoint of the IDP, you can start the authentication flow by redirecting the user agent (HTTP status code 302) to the authorization_endpoint.

When creating the authentication request, you have to decide on which user data you want to request via claims, as explained above.

3.2.1. Parameters

As usual, all parameters MUST be properly encoded. Please ensure that your library also properly encodes a + sign (especially if you have a base64-encoded value for nonce or state) and { and } (for example, in claims). The latter two are sometimes not properly encoded by libraries, see this discussion.

The authentication request supports the following parameters

  • response_type REQUIRED: always set to code in the identity service scheme.

  • client_id REQUIRED: the client_id of your app. Please take care to use the correct client id for the intended environment here (sandbox/production).

  • redirect_uri REQUIRED: the user agent is sent to this destination after the completion of the authentication process. This must exactly match one of the Redirect URIs you registered with the identity service.

  • claims OPTIONAL: JSON object according to the OpenID Specification defining the identity claims your app wants to obtain for a user, as described above.

  • scope REQUIRED: MUST always be openid to turn on OpenID Connect.

  • state OPTIONAL: a cryptographic random value, freshly chosen by the client that must be used to detect CSRF attacks. Usually created by an OAuth library.

  • nonce REQUIRED*: a cryptographic random value, freshly chosen by the client to link the OpenID Connect authentication request to subsequent steps in the message flow and to detect CSRF attacks. Usually created by an OpenID Connect library.

  • purpose OPTIONAL: see below

  • acr_values OPTIONAL: see below

* Instead of nonce, you can instead use PKCE (parameters code_challenge and code_verifier) as well, as both provide similar levels or protection. The use of PKCE is described in the signing service developer guide.
Your app can only use claims that are registered for it.
The parameter response_mode is not supported by the identity service IDPs and can lead to errors when used.

3.2.2. Request-specific Purpose

A dedicated purpose has to be set for every transfer of user data. The purpose text is shown in the IDP’s user interface to give the user context on what they are about to do.

For convenience, a default purpose is set on client registration. To set a transaction specific purpose, use the additional purpose parameter like this: purpose={Purpose}.

Some authorization servers filter out special characters in parameters of the authorization request (most likely as an attempt to prevent cross-site scripting). If possible, avoid using the characters <>(){}'\ and HTML tags.

The purpose cannot be shorter than 3 characters and may not be longer than 300 characters. If these rules are violated, the authorization request will fail, i.e., the authorization response redirection URL (HTTP status code 302) will carry the parameters error=invalid_request and error_description=invalid_purpose_length.

Example 6. Request-specific Purpose, Error Message
https://{Redirect URI}?state=-ZBPQz_Rj5DA8c9X7Y9wzgiMsJYdtYoRpwOB0qdeyBQ
&error=invalid_request&error_description=invalid_purpose_length

3.2.3. Authentication Policy

OPs can authenticate the user using two different authentication levels. You request an authorization level using the acr_values parameter.

The following two authentication levels are available:

  1. https://www.openbanking.verimi.cloud/acrs/online_banking (default): Single factor authentication using the primary online banking credentials, e.g., a code or a password. The user either enters her username or the username was automatically determined based on data from previous logins.

  2. https://www.openbanking.verimi.cloud/acrs/online_banking_sca: Two factor authentication (strong customer authentication) utilizing online banking credentials and a second factor or TAN approach. The user either enters her username or the username was automatically determined based on data from previous logins.

The acr values supported can be found in the issuer’s OIDC configuration’s value acr_values_supported.

In the JSON you can see - in the acr property - which acr level the authentication was done with.

The server can use a lower acr value than the one requested. Always check the acr claim in the response for the acr value actually used by the server.

3.2.4. Implementation Notes

Example 7. Redirection to the Authorization Endpoint
HTTP/1.1 302 Found
Location: https://testidp.sandbox.openbanking.verimi.cloud/services/authz/10000001?cl
             ient_id=sandbox.yes.com%3Ae85ff3bc-96f8-4ae7-b6b1-894d8dde9e
             be&scope=openid&response_type=code&redirect_uri=http%3A%2F%2
             Flocalhost%3A3000%2Fyes%2Foidccb&nonce=FMIGY3-9VrVDzKLATMJx0
             -V1F4gV3fDx6y110UzQJpk&acr_values=https%3A%2F%2Fwww.yes.com%
             2Facrs%2Fonline_banking_sca&claims=%7B%22id_token%22%3A%7B%2
             2given_name%22%3Anull%2C%22family_name%22%3Anull%2C%22verifi
             ed_claims%22%3A%7B%22verification%22%3A%7B%22trust_framework
             %22%3Anull%7D%2C%22claims%22%3A%7B%22birthdate%22%3Anull%7D%
             7D%7D%2C%22userinfo%22%3A%7B%22salutation%22%3Anull%2C%22tit
             le%22%3Anull%2C%22verified_claims%22%3A%7B%22verification%22
             %3A%7B%22trust_framework%22%3Anull%7D%2C%22claims%22%3A%7B%2
             2place_of_birth%22%3Anull%2C%22nationalities%22%3Anull%7D%7D
             %7D%7D&state=V1F4gV3fDx6y110UzQJpk

Using a nicer formatting, the request to https://testidp.sandbox.openbanking.verimi.cloud/services/authz/10000001 contains the following request parameters:

?client_id=sandbox.yes.com:e85ff3bc-96f8-4ae7-b6b1-894d8dde9ebe
&scope=openid
&response_type=code
&redirect_uri=http://rpbackend.acme.com/yes/oidccb
&state=V1F4gV3fDx6y110UzQJpk
&nonce=FMIGY3-9VrVDzKLATMJx0
&acr_values=https://www.openbanking.verimi.cloud/acrs/online_banking_sca
&claims={
   "id_token":{
      "given_name":null,
      "family_name":null,
      "verified_claims":{
         "verification":{
            "trust_framework":null
         },
         "claims":{
            "birthdate":null
         }
      }
   },
   "userinfo":{
      "salutation":null,
      "title":null,
      "verified_claims":{
         "verification":{
            "trust_framework":null
         },
         "claims":{
            "place_of_birth":null,
            "nationalities":null
         }
      }
   }
}
In order to prevent CSRF attacks, both nonce and state (if used) MUST be associated with the user agent where the request originated. This binding MUST be checked after the RP received the Authentication Response and Token Response.
The authorization endpoint URI may contain parameters which have to be preserved when using the URI. Please make sure that your code or the library used supports parameters in endpoint URIs so that you don’t run into problems because of parameters being cut off or a duplicate ? being used resulting in an invalid URI.

Screen control is with the OP now which will guide your user through login and consent. The OP requires information about your app in the course of this flow. You therefore have to provide a privacy policy and may provide an optional terms of service document and label upon registration.

The way the OP authenticates the user and asks her to consent at the discretion of the OP.

3.3. Authentication Response

After successful authentication, authorization, and consent, the OP will redirect (HTTP status code 302) your user to the {redirect_uri} given in the Authentication Request including the following request parameters:

  • code: the authorization code you need to get the ID and access token

  • iss: the issuer URL of the OP that created this response. You app MUST check that this value is equal to the issuer URL used in the previous steps. This is a countermeasure against mix-up attacks.

The check and the token endpoint request MUST be implemented in the backend logic of the application as this does not expose the results to client side attacks and allows to use client secrets to authenticate the client.
Example 8. Authentication Response
GET /yes/oidccb?code=rDx7qadXAgCrkTGxF7WjrA.gs8gNEgMhH6Ww-VBZbz04w&
        iss=https://testidp.sandbox.openbanking.verimi.cloud/issuer/10000001&state=V1F
        4gV3fDx6y110UzQJpk HTTP/1.1
Host: rpbackend.acme.com

3.4. Authentication Error Response

Errors according to OAuth 2.0 Authorization Error Response, OAuth 2.0 Error Response, or OIDC 1.0 Authentication Error Response may occur and must be handled. In case of an error the parameter error will deliver an error code with optional details in the parameter error_description.

There is a identity service specific error code account_selection_requested which is returned by the OP if the user clicks 'Select another bank' during the online banking login and shall cause a forced bank selection in the account chooser.

3.5. Token Request

If your app received a successful authentication response, your backend at {redirect_uri} needs to exchange the authorization code for tokens at the token_endpoint . The token request is a POST request with content type application/x-www-form-urlencoded and the following parameters:

  • grant_type REQUIRED: must be set to authorization_code

  • code REQUIRED: authorization code returned in the authorization response

  • client_id REQUIRED: your client_id

  • redirect_uri REQUIRED: same redirect_uri as used in the authorization request. This is a security countermeasure against client impersonation.

Your RP backend has to perform client authentication with the OP via mutual TLS (aka. TLS client authentication): Your RP has to be configured so that it uses the self-signed certificate with which you registered your RP for the TLS handshake with the OP.
Example 9. Token Request
POST testidp.sandbox.openbanking.verimi.cloud/issuer/10000001/token
Accept: application/json
Accept-encoding: gzip, deflate
Content-type: application/x-www-form-urlencoded
Content-length: 261
Host: testidp.sandbox.openbanking.verimi.cloud

grant_type=authorization_code&code=rDx7qadXAgCrkTGxF7WjrA.gs8gNEgMhH6W
w-VBZbz04w&redirect_uri=http%3A%2F%2Frpbackend.acme.com%2Fyes%2Foidccb
&client_id=sandbox.yes.com%3Ae85ff3bc-96f8-4ae7-b6b1-894d8dde9ebe

3.6. Token Response

Nearly there! The IDP will respond with a JSON object, i.e., the response will contain the header Content-Type: application/json;charset=UTF-8.

The JSON object has the following attributes (and may have others)

  • access_token OPTIONAL: the access token (not needed in the identity service)

  • token_type REQUIRED: always set to bearer

  • expires_in RECOMMENDED: seconds until expiration

  • id_token REQUIRED: the ID Token, a JWT signed by the OP

Example 10. Token Response
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8

{
   "access_token":"2ZUIENkskjfiejkpAA",
   "token_type":"bearer",
   "expires_in":3600,
   "scope":"openid",
   "id_token":"eyKRJKLFJLIjlkdjkjhdkjhdlkl3k5lkjl..."
}

ID Token Contents.*

{
   "sub": "f647f683-e46d-43bd-bc76-526d93429b86",
   "aud": "sandbox.yes.com:e85ff3bc-96f8-4ae7-b6b1-894d8dde9ebe",
   "iss": "https://testidp.sandbox.openbanking.verimi.cloud/issuer/10000001",
   "exp": 1599642067,
   "iat": 1599641167,
   "nonce": "FMIGY3-9VrVDzKLATMJx0",
   "given_name": "Given001",
   "family_name": "Family001",
   "verified_claims": {
      "verification": {
         "trust_framework": "de_aml"
      },
      "claims": {
         "birthdate": "1950-01-01"
      }
   }
}

The ID Token is a JWT signed by the OP with the RSA SHA-256 algorithm and a private key belonging to one of the public keys (or certificates) in the JWKS available via the jwks_uri provided in the OpenID Connect Configuration. The ID token payload contains the following attributes (and may contain others):

  • iss REQUIRED: MUST be validated to be equal to the Issuer URI

  • aud REQUIRED: MUST be validated to be equal to your client_id

  • sub REQUIRED: the user ID (unique only in the scope of the issuer iss which is important if you store user IDs)

  • nonce REQUIRED: MUST be checked to be equal to the nonce in the authorization request

  • exp REQUIRED: (int) token expiration, token MUST NOT be accepted after exp

  • iat REQUIRED: (int) token issued at (time)

The ID token will contain further identity claims as requested in the authentication request using the claims parameter.

3.6.1. Handling Returned Data

It is important to know what to expect from the returned data and how to handle it: You must first check that the response is correct and complete before using the user data in your application.

Follow these steps to ensure that the returned data is trustworthy:

  1. Check that the ID token is a valid JWT.

  2. Check that the iss value matches the issuer URL returned from the account chooser.

  3. Check that aud matches your client ID.

  4. Check the signature of the JWT using the keys provided in the OpenID Connect Configuration document retrieved earlier.

  5. Check that the algorithm for the signature is RS256.

  6. Check that nonce matches the nonce selected earlier in the process.

  7. Check that the current time is between iat and exp.

These steps should be performed by an OpenID Connect library. If any check fails, the process must be aborted.

Skipping any of the steps of the validation of the ID token will lead to security vulnerabilities in your application.

Now, check that the contents of the response match your expectations:

  1. If a two-factor authentication is important to your application, you will have used the acr_values parameter in the authentication request (see Authentication Policy for details). Now, ensure that the acr claim in the ID token reflects this value.

  2. Check that all requested claims are contained in the response and that the contents match your expectations. In some circumstances, data delivered by the IDP may be incomplete. It is your responsibility to act accordingly, e.g., to ask the user to fill in missing data or to inform the user that the process cannot be completed. See also Availability of Data and Billing.

Your application may now use the user ID and other identity claims, e.g., to log the user in.

You MUST build the identifier used to look up the user profile locally by using the iss and the sub as composite key (e.g., by concatenating using a separator character), since the sub is guaranteed to be unique within the scope of a particular IDP only.

3.7. Token Error Response

Errors according to OAuth 2.0 Error Response, or OIDC 1.0 Token Error Response may occur and must be handled. In case of an error the returned JSON object will normally contain an error attribute.

3.8. UserInfo Request/Response (optional)

Obtaining user data from the ID token provided in the Token Response is the quickest way. Alternatively, the data can be retrieved from the IDP’s UserInfo Endpoint.

To access the UserInfo Endpoint you will send a GET request to the address extracted during the OpenID Connect Configuration adding the access token as a Bearer authorization header:

  • URL: {userinfo_endpoint}

  • Request Header: Authorization: Bearer {access_token}

Remember to make the TLS handshake with your self-signed certificate and to add your client_id as a request parameter as explained in the token request section (Client authentication).

The return value is a JSON object, i.e., a response with a header Content-Type: application/json;charset=UTF-8.

The JSON object contains at least the attribute

  • sub REQUIRED: user ID which MUST be verified by the RP to match the one from the ID token

and the claims as requested in the authentication request.

Example 11. UserInfo Response (Body)
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8

{
   "sub":"c7734893464991805caeda94c39414a163f5907caeadd61823b1feb386dcb198",
   "https://www.openbanking.verimi.cloud/claims/place_of_birth":{
      "locality":"Rösrath"
   },
   "birthdate":"1980-01-01",
   "address":{
      "country":"DE",
      "street_address":"Lüghauser Str. 16",
      "formatted":"Lüghauser Str. 16\n51503 Rösrath\nDEUTSCHLAND",
      "locality":"Rösrath",
      "postal_code":"51503"
   },
   "phone_number":"+4915245678900",
   "given_name":"Yasmin",
   "family_name":"Verimi",
   "email":"yasmin@verimi.de"
}

Appendix 1 - User Information

The identity service IDP MUST allow RPs to request user information (claims) belonging to the user’s online banking account.

With version 2.x of this developer guide, some claim names have changed. For new implementations, please only use the new names for the claims as shown in the following.

The RP requests the claims using the claims request parameter in the Authentication Request. The RP can select whether the claims are provided via the ID Token or at the UserInfo Endpoint. The ID Token is easier to implement and faster and therefore the preferred way.

The following claims are supported:

Claim Type Description MTI

email

string

see OpenID Connect, section 5.1

yes

phone_number

string

based on OpenID Connect, section 5.1, representation of the phone number according to E.164 in the format

"+" + <CC> + <NDC> + <SN>

regular expression: ^\+[[:digit:]]{2,15}$

Example: +441134960000

It is recommended to provide the RP with the preferred mobile phone number of the user.

yes

given_name

string

see OpenID Connect, section 5.1

yes

family_name

string

see OpenID Connect, section 5.1

yes

gender

string

The gender selected by this person, male, female, or intersex. It might be set to a custom value.

see OpenID Connect, section 5.1

no

salutation

string

end-user’s salutation, e.g., Mr.

see OpenID Connect for Identity Assurance

no

title

string

end-user’s title, e.g., Dr.

see OpenID Connect for Identity Assurance

no

place_of_birth

JSON object

end-user’s place of birth as defined in OpenID Connect for Identity Assurance

The sub-field country is optional.

yes

birthdate

string

ISO 8601:2004 YYYY-MM-DD format, e.g., 2000-01-01

yes

nationalities

string array

ICAO 2-letter codes, e.g., DE

see OpenID Connect for Identity Assurance

yes

address

JSON object

see OpenID Connect, section 5.1.1

The elements street_address, locality, and postal_code are required.

yes

https://www.openbanking.verimi.cloud/claims/ tax_id

string

tax identification number

no

https://www.openbanking.verimi.cloud/claims/ preferred_iban

string

IBAN of the debit account the users wants to use for transactions. How this account is determined (if there are more than a single account associated with the user’s online banking account) is at the discretion of the identity service IDP. The IDP might ask the user within the flow but should utilize sensible default and preferences in order to make the user experience as frictionless as possible.

no

txn

string

see OpenID Connect for Identity Assurance. Note: This claim is available independent of verified claims.

yes

Address

The address claim consists of the following fields:

  • locality: city or other locality

  • postal_code: Zip code or similar postal code component

  • country: represented using ISO 3166-1 Alpha-2, e.g., DE

  • street_address: street name and number or post office box

  • formatted: formatted address

Place of Birth

The place of birth consists of the following fields:

  • country: represented using ISO 3166-1 Alpha-2, e.g., DE

  • locality: city or other locality

Appendix 2 - Verified Claims

The identity service IDPs MUST support the attestation of verified claims. This attestation consists of

  • the verified data (claims) about the online banking user’s identity,

  • data about the verification process used to bind a person’s identity to a certain online banking account, and

  • data about the actual authentication process used to ensure the binding between user account and the actual user.

The latter data are carried using the acr value as described in Authentication Policy. The verified claims and the data about the verification process are represented as a structure within a special claim, verified_claims.

Requesting Verified Claims

Requests to OPs MUST follow OpenID Connect for Identity Assurance and use the identifier defined in OpenID Connect for Identity Assurance Identifiers. Please refer to these documents for full details. The most important features are shown in the following.

Let’s start with an example request and response that shows how the verified_claims claim can be requested alongside unverified claims:

Example 12. Simple Verified Claims Request and Responses

Request. In this example, different sets of data are requested in the ID token and from the userinfo endpoint:

{
   "id_token":{ (1)
      "given_name":null,
      "family_name":null,
      "verified_claims":{
         "verification":{
            "trust_framework":null (2)
         },
         "claims":{
            "birthdate":null (3)
         }
      }
   },
   "userinfo":{ (4)
      "salutation":null,
      "title":null,
      "verified_claims":{
         "verification":{
            "trust_framework":null
         },
         "claims":{
            "place_of_birth":null, (5)
            "nationalities":null
         }
      }
   }
}
1 In the ID token, the given name and family name are requested without further verification.
2 The trust framework must always be requested if verified claims are requested. de_aml, identifying the Germany Anti-Money Laundering Law, is currently the only supported trust framework.
3 In the ID token, the birthdate is requested as a verified claim.
4 From the userinfo endpoint, the salutation and title are requested unverified.
5 Place of birth and the nationalities are requested as verified claims.

ID Token. This is an example for the ID token that would be produced from the request above.

{
   "sub": "f647f683-e46d-43bd-bc76-526d93429b86",
   "aud": "sandbox.yes.com:7011b6c1-d4f3-4ee3-865b-50af0475755f",
   "iss": "https://testidp.sandbox.openbanking.verimi.cloud/issuer/10000001",
   "exp": 1599642067,
   "iat": 1599641167,
   "nonce": "42",
   "given_name": "Given001",
   "family_name": "Family001",
   "verified_claims": {
      "verification": {
         "trust_framework": "de_aml"
      },
      "claims": {
         "birthdate": "1950-01-01"
      }
   }
}

Userinfo. At the userinfo endpoint, the following data might be returned (here taken from the Test IDP with user test001, see for Test IDP and test user details):

{
   "sub": "f647f683-e46d-43bd-bc76-526d93429b86",
   "salutation": "Herr",
   "title": "Dr.",
   "verified_claims": {
      "verification": {
         "trust_framework": "de_aml"
      },
      "claims": {
         "place_of_birth": {
            "locality": "Berlin",
            "country": "DE"
         },
         "nationalities": [
            "DE"
         ]
      }
   }
}
Since the same request syntax can be used within userinfo and id_token in the claims parameter, the outer layer of the claims parameter is omitted in the following examples. We will only show the verified_claims claim.

The following example shows the core of a verified_claims structure that you can build upon to create your own request:

Example 13. Request Syntax for Verified Claims

Note: Outer level of claims structure omitted for presentation.

{
   "verified_claims":{ (1)
      "verification":{ (1)
         "trust_framework": …,  (4)
         "time": …, (5)
         "verification_process": …, (6)
         "evidence":[  (7)
            {
               "type":{ (8)
                  "value": …
               },
               "method": …, (3)
               "document":{ (2)
                  "type": …, (4)
                  "issuer":{  (2)
                     "country": …, (3)
                     "name": …, (6)
                     "… any other keys …": … (6)
                  },
                  "… any other keys …": … (6)
               }
               "… any other keys …": … (6)
            }
         ]
      },
      "claims":{ (1)
         "given_name": …, (3)
         "family_name": …, (3)
         "birthdate": …, (3)
         "place_of_birth": …, (3)
         "nationalities": …, (3)
         "address": … (3)
      }
   },
   … (claims)
}
1 This key MUST NOT be omitted and MUST contain an object with at least one key (verified_claims MUST contain verification and claims).
2 This key MAY be omitted completely. Otherwise, its value MUST be an object.
3 This claim MAY be requested using null or an object. The object MAY contain the keys essential and either value or values. Other keys are not permitted in the object.
4 This key MUST be requested (unless the parent element is omitted) using null or an object. The object MAY contain the keys value or values. Other keys are not permitted in the object.
5 time MAY be omitted. Otherwise, its value MUST be either null or an object with the max_age key and/or the essential key. Other keys are not permitted in the object.
6 This key MAY be requested using null or an object. The object MAY contain the key essential. Other keys are not permitted in the object.
7 evidence MUST either be omitted or MUST contain an array with exactly one object.
8 evidence/type MUST be requested (if evidence is not omitted) using a concrete value. Other keys are not permitted in the object.

value, values, essential, max_age are used as defined in OpenID Connect for Identity Assurance. If a key is omitted in the request, the response will not contain the respective key.

The IDP will also omit certain parts of the response if user data is not available or does not match the requirements in request - this is explained in more detail in Data Handling by the IDP.
Only "leaf" claims can be marked essential. Object/array claims (place_of_birth, nationalities, address) are considered leaf claims and can only be essential as a whole (or not).

OPs will reject requests not complying with this syntax.

Example 14. Minimal Request Example

Request. Note: Outer level of claims structure omitted for presentation.

{
   "verified_claims":{
      "verification":{
         "trust_framework": null
      },
      "claims":{
         "family_name": null
      }
   }
}
Example 15. More Complete Request Example

Request. Note: Outer level of claims structure omitted for presentation.

{
   "verified_claims":{
      "verification":{
         "trust_framework": {
            "value": "de_aml"
         },
         "time": {
            "max_age": 864000000
         },
         "evidence":[
            {
               "type": {
                  "value": "id_document"
               },
               "method": null,
               "document":{
                  "type": null,
                  "issuer":{
                     "country": {
                        "essential": true
                     },
                     "name": null
                  }
               }
            }
         ]
      },
      "claims":{
         "given_name": {
            "essential": true
         },
         "family_name": {
            "essential": true
         },
         "birthdate": {
            "essential": true
         }
      }
   },
   "txn": null
}

Response. Example ID token response from the Test IDP with user test006 (see for Test IDP and test user details):

{
   "sub": "524aeddd-7922-4c36-b496-217f32c45a14",
   "aud": "sandbox.yes.com:7011b6c1-d4f3-4ee3-865b-50af0475755f",
   "verified_claims": {
      "claims": {
         "birthdate": "1975-06-06",
         "given_name": "Given006",
         "family_name": "Family006"
      },
      "verification": {
         "trust_framework": "de_aml",
         "time": "2019-01-02T06:06:06.060+01",
         "evidence": [
            {
               "method": "sripp",
               "document": {
                  "type": "idcard",
                  "issuer": {
                     "country": "DE",
                     "name": "Stadt Köln"
                  }
               },
               "type": "id_document"
            }
         ]
      }
   },
   "iss": "https://testidp.sandbox.openbanking.verimi.cloud/issuer/10000001",
   "txn": "34b65a01-921f-4c44-914a-7208d45f646e",
   "exp": 1599643443,
   "iat": 1599642543,
   "nonce": "42"
}
Never include data in value or values that could identify a user (personally identifiable information), as the contents of value and values end up in the billing system.

Data Handling by the IDP

The IDP will check if the data available for the online banking user is sufficient to fulfill the requirements encoded in your request. Depending on the available data, the IDP will either send a full response or omit certain elements from the response:

  • If a requirement (using value, values, or max_age) within verified_claims/verification cannot be fulfilled by the IDP, the IDP will omit the whole verified_claims element from the response.

  • The essential designation does not influence whether claims or verification elements are delivered or not. For example, if a verification element marked as essential (but not restricted using value/values/max_age) is not available, the IDP omits the particular element from the response as usual, but does not omit the verified_claims element as it would do with a value restriction.

  • If a particular claim within verified_claims/claims cannot be deliviered by the IDP, for example if the data is not available, or if requirements are expressed that cannot be fulfilled by the IDP, the IDP will not deliver the respective claim. If the resulting verified_claims/claims set is empty, the IDP will omit verified_claims from the response, according to OpenID Connect for Identity Assurance.

  • If an IDP is unable to map the available identity document for its user to one of the types listed below or to map the verification method to one of the verification methods listed below, the IDP will omit the verified_claims element from the response.

Common cases where data is not available to the IDP include the verification method (method) and the country of the issuer.

IDP Support

The identity service IDPs must support the following features for verified claims:

  • The following Claims must be supported: given_name, family_name, birthdate, place_of_birth, nationalities, address.

  • The trust_framework identifier de_aml must be supported and is the currently only supported trust framework in the ecosystem.

  • The evidence type id_document must be supported and is the currently only supported type of evidence.

  • The identity service IDPs map the identity document used to verify the bank customer’s identity to the the following id_document types:

    • idcard

    • passport

    • de_idcard_foreigners

    • de_emergency_idcard

    • de_erp

    • de_erp_replacement_idcard

    • de_idcard_refugees

    • de_idcard_apatrids

    • de_certificate_of_suspension_of_deportation

    • de_permission_to_reside

    • de_replacement_idcard

  • The identity service IDPs map the verification methods used to verify the bank customer’s identity to the the following verification methods:

    • pipp

    • sripp

  • Constraints on verification data described in the request syntax above are supported at the following verification data elements:

    • trust_framework

    • time

    • evidence/type

    • evidence/method

    • evidence/document/type

    • evidence/document/issuer/country

See OpenID Connect for Identity Assurance Identifiers for details on the various identifiers used here!

The identity service IDPs advertise their capabilities with respect to verified claims in the standard openid-configuration as defined in OpenID Connect for Identity Assurance.