OpenID Connect for Identity Assurance, explained by an implementer
Introduction
OpenID Connect for Identity Assurance 1.0 (OIDC4IDA or IDA) is a technical specification that the eKYC-IDA Working Group of OpenID Foundation has developed. It uses OAuth 2.0 and OpenID Connect (OIDC) as its base and defines a JSON structure that conveys verified claims of a natural person.
“Claim” here is a technical term that means a user attribute such as given name, birthday, address, and so on.
“Verified” here means that the authenticity of the claim has been verified with evidence such as passport, driver’s license, and so on.
In the Internet, there are many web services that users can sign up. They often require users to register user attributes, but the attributes are only self-asserted by users. Such unverified attributes cannot be used in legal contexts. Here OIDC4IDA comes in.
History
Implementer’s Draft 1 — The initial version of the specification was published in November, 2019 (announcement). The version is called Implementer’s Draft 1 (ID1).
Implementer’s Draft 2 — The second version was published in May, 2020 (announcement). The version is called Implementer’s Draft 2 (ID2).
Implementer’s Draft 3 — The third version was published in November, 2021 (annoucement). The version is called Implementer’s Draft 3 (ID3). As of this writing (in May, 2022), ID3 is the lastest version among officially-published drafts.
Next Draft — The past Implementer’s Drafts repeated to introduce breaking changes. And again, it is certain that the next version will contain breaking changes because breaking changes have already been merged into the master branch of the eKYC-IDA Git repository (e.g. PR 87). Considering the amount of breaking changes and addition of new properties, it is highly likely that the Implementer’s Draft 4 will be published before the future final version.
This article is written based on the latest specification in the eKYC-IDA Git repository as the author of this article (me) attends weekly meetings of the eKYC-IDA WG and can share information about the latest status of the specification with you readers.
verified_claims
The specification defines a JSON structure that conveys verified claims. It is intended that the JSON structure is embedded in other JSON structures such as payloads of ID Token (OIDC Core, Section 2) and responses from UserInfo Endpoint (OIDC Core, Section 5.3).
When the JSON structure appears in other JSON structures, it is labeled with "verified_claims"
. The following figure illustrates how it is embedded in the payload of an ID Token.
The JSON schema file, verified_claims.json
, describes the structure of "verified_claims"
. The file is maintained in the schema
directory of the eKYC-IDA Git repository.
verification and claims
The "verified_claims"
JSON object contains "verification"
and "claims"
as top-level properties.
The "verification"
JSON object describes pieces of information about the verification process such as “based on what regulation?”, “with what evidence?”, “when?” and “by whom?”
The "claims"
JSON object contains pairs of name and value of verified claims.
verified_claims request
To request an authorization server to embed "verified_claims"
in ID Token and/or UserInfo responses, client applications use the claims
request parameter of an authorization request that is defined in the Section 5.5 of OpenID Connect Core 1.0.
The format of the claims
request parameter is JSON. The JSON contains either or both of "id_token"
and "userinfo"
as top-level properties. A client application lists names of claims it requests to be embedded in ID Token in the "id_token"
JSON object and likewise lists names of claims it requests to be embedded in UserInfo responses in the "userinfo"
JSON object. This rule is written in the OIDC Core specification.
When a client application wants to get verified claims, it includes "verified_claims"
in the "id_token"
JSON object and/or the "userinfo"
JSON object like the figure below shows.
The JSON schema file, verified_claims_request.json
, describes the structure of "verified_claims"
request. The file is maintained in the schema
directory of the eKYC-IDA Git repository.
Data Minimization
The specification requires that servers not return data that are not explicitly requested. This policy is called data minimization. Therefore, for a simple verified_claims
request like below:
the server returns only "trust_framework"
and "given_name"
as follows.
If a client application wants more information, it must construct a complex verified_claims
request. The following is an example value of the claims
parameter that includes a complex verified_claims
request (excerpted from the specification).
Filtering
Constraints by value, values, max_age
When a claim in a verified_claims
request has a JSON object that contains "value"
, "values"
or "max_age"
and the claim is under verified_claims/verification
(i.e. not under verified_claims/claims
), the JSON object is used as a filtering condition.
"value"
— The actual value of the claim must match the value specified by"value"
."values"
— The actual value of the claim must match one or more elements in the"values"
array."max_age"
— The elapsed time since the date time that the actual value of the claim expresses must not exceed the number of seconds specified by"max_age"
.
<"value"
example> The example below requests verified claims that have been verified by the rules of the trust framework uk_tfida
. If the server does not have verified claims that satisfy the condition, "verified_claims"
is not returned.
<"values"
example> The example below requests verified claims that have been verified by the rules of either the trust framework nist_800_63A
or the trust framework uk_tfida
.
<"max_age"
example> The example below requests that the elapsed time since the identity verification process took place not exceed 30 days (= 2,592,000 seconds). If the server does not have verified claims that were verified within the last 30 days, "verified_claims"
is not returned.
Logical OR by Array
The “Requesting Verification Data” section of the specification contains interesting requirements for the evidence
array as excerpted below.
A single entry in the
evidence
array represents a filter over elements of a certain evidence type. The RP therefore MUST specify this type by including thetype
field including a suitablevalue
sub-element value. Thevalues
sub-element MUST NOT be used for theevidence/type
field.If multiple entries are present in
evidence
, these filters are linked by a logical OR.
As a result, the following request will result in that all available evidence whose type is either "document"
or "electronic_signature"
are included in the resultant "verified_claims"
.
This special rule should apply to other properties of array type such as check_details
. However, there is a special rule for assurance_details
as excerpted from the specification below.
assurance_details
is an array representing how theevidence
andcheck_details
meets the requirements of thetrust_framework
. RP SHOULD only request this where they need to know this information. Whereassurance_details
have been requested by an RP the OP MUST return theassurance_details
element along with all sub-elements that it has. If an RP wants to filter what types ofevidence
andcheck_methods
they MUST use those methods to do so, e.g. requesting anassurance_type
should have no filtering effect.
That is, all available sub-elements of assurance_details
are returned when the property is requested. Data minimization and logical-or filtering don’t apply.
Example of Data Minimization and Filtering
Suppose the server holds a dataset that is equivalent to the content of the JSON below.
If the following verified_claims
request is made against the dataset,
the server should generate the following "verified_claims"
.
Points to note are as follows:
- The dataset on the server side contains two elements in the
"evidence"
array, but the"evidence"
array in the generated"verified_claims"
contains only one element. It is because the constraint,check_details/*/organization == "OpenBankingTPP"
, filtered out the unmatched element. - The generated
"verified_claims"
does not contain the"family_name"
claim. It is because the actual value of the"family_name"
claim in the dataset on the server side is not"Unknown"
. When the"value"
,"values"
and"max_age"
constraints are not satisfied underverified_claims/verification
, the entire or partial dataset containing the unmatched property is omitted. On the other hand, underverified_claims/claims
, unmatched claims are just omitted without affecting other parts. - Many properties are omitted from the generated
"verified_claims"
for the data minimization policy. For example,"address"
contains only"locality"
. Other properties such as"postal_code"
,"country"
and"street_address"
are omitted.
Attachments
“Attachments” is a relatively big feature among others that were added by the third Implementer’s Draft. The feature enables to attach media that are related to the identity verification process. For example, scans of signed forms, photocopies of evidence, and so on.
Attachments can be embedded directly in the "attachments"
array like below (embedded_attachments.json
; copy from the eKYC-IDA Git repository).
Or, in the case where contents of attachments are hosted on a remote server, only their URLs can be included in the "attachments"
array with an optional access token like below (external_attachments.json
; copy from the eKYC-IDA Git repository).
Transformed Claims
Transformed Claims (TC) is not a part of the OIDC4IDA specification but a part of “OpenID Connect Advanced Syntax for Claims (ASC) 1.0” that is one of the specifications discussed in the eKYC-IDA WG.
Introduction
The feature of Transformed Claims enables to transform values of claims by applying transformation functions.
For example, by applying the years_ago
transformation function to the birthdate
claim, the age of the user can be computed and embedded in ID Tokens and/or UserInfo responses. Furthermore, if the gte
transformation function (gte
means “greater than or equal to”) with an argument 18
is applied to the result of the years_ago
transformation function, a boolean value can be obtained that indicates whether the user is above 18 or not. This example can be used in scenarios where age verification is required but personal information such as birthday should not be disclosed.
A reason to pay attention to the TC specification is that age verification is one of key factors in a scenario that is described in the whitepaper of GAIN (Global Assured Identity Network), which is a project to build a global high-trust digital identity network over the Internet.
Transformed Claim Definition
A transformed claim consists of the following components.
- Name of the transformed claim
- Claim referenced as input
- Transformation functions (which may require arguments) applied to the input
In the case of example illustrated in the figure of “Concept of Transformed Claims”, the name of the transformed claim is age_18_or_over
, the referenced claim is birthdate
, and the transformation functions applied are years_ago
and gte
(with 18
as an argument).
A transformed claim is defined as a property in a JSON object. The key of the property is the name of the transformed claim and the value of the property is a JSON object which contains a claim
property and a fn
property. The claim
property is a referenced claim and the fn
property is a list of transformation functions.
For example, the age_18_or_over
transformed claim can be defined as follows.
The value of the fn
property is an array. Each element of the array represents a transformation function with or without arguments. When a transformation function takes no argument, only the name of the transformation function is put in the fn
array (e.g. "years_ago"
). On the other hand, when a transformation function takes arguments, the name of the transformation function and the arguments are packed into an array and the array is put in the fn
array (e.g. ["gte", 18]
).
Places for Transformed Claim Definitions
There are two places to put definitions of transformed claims in. One is the claims
request parameter (OIDC Core, Section 5.5) of an authorization request. The other is the discovery document (OIDC Discovery, Section 4) of the authorization server.
§ transformed_claims
The specification defines transformed_claims
as a new property that can appear in the claims
request parameter. A client application can put definitions of transformed claims there.
The following is an example of the content of the claims
request parameter. It contains "transformed_claims"
which contains the definition of age_18_or_over
transformed claim.
One more point to note is that the name of the defined transformed claim is referenced in "claims"
. When a transformed claim defined in "transformed_claims"
is referenced, a colon (:
) is prefixed like ":age_18_or_over"
.
§ transformed_claims_predefined
The specification defines transformed_claims_predefined
as a new server metadata that may be included in the discovery document. An authorization server can put definitions of transformed claims there.
The following is an example of the transformed_claims_predefined
server metadata.
Client applications can use transformed claims predefined by the authorization server in the claims
request parameter without redefining them. The following is an example of the claims
request parameter that references a predefined transformed claim by prefixing two colons (::
) to the name.
Chain of Transformation Functions
The fn
property in a definition of transformed claim is a list of transformation functions. The first transformation function in the list will receive a known claim as input. The second and the subsequent transformation functions will receive the execution result of their immediately preceding transformation function. The execution result of the last transformation function will be used as the value of the transformed claim.
For example, the years_ago
transformation function in the example shown previously receives the value of the birthdate
claim as input and may generate 30
for instance as an execution result. Then, the gte
transformation function receives 30
as input and generates true
as an execution result. The true
generated by gte
becomes the value of the age_18_or_over
transformed claim.
Predefined Transformation Functions
The following transformation functions are predefined in the specification. See the ASC specification for details.
years_ago
— computes the number of elapsed years since the inputeq
— true if the input is equal to the argumentgt
— true if the input is greater than the argumentlt
— true if the input is less than the argumentgte
— true if the input is greater than or equal to the argumentlte
— true if the input is less than or equal to the argumenthash
— computes a hash value of the inputany
— true if any of elements in the input array is trueall
— true if all of elements in the input array are truenone
— true if none of elements in the input array are trueget
— get the value of a specified property from the input JSON objectmatch
— true if the input matches the regular expression specified by the argument
Demo of Transformed Claims
The author of this article (me) gave a demo of Transformed Claims in a session of OAuth Security Workshop on December 1, 2021. The recorded video is available on YouTube. The demo starts from 28:32.
Implementation
Implementation of Data Minimization and Filtering
As soon as you start to implement the OIDC4IDA specification without compromise, you will realize that it is difficult to implement the logic of the data minimization policy and the filtering rules.
In OIDC Core, all claims are flatly listed as top-level properties in the payload of ID Tokens and UserInfo responses (except the address
claim; OIDC Core, Section 5.1.1). However, the structure of "verified_claims"
request is too complex.
For discouraged developers, I have published an implementation of the logic as open source here:
The DatasetExtractor
class is a part of the authlete-java-common library. The library is for Authlete, but the logic implemented in the class is independent of Authlete APIs. Therefore, you can port the logic to your implementation.
Implementation of Transformed Claims
AFAIK, Authlete 2.3 is the only working implementation of Transformed Claims in the world as of this writing (in May, 2022). The feature of Transformed Claims is implemented in Authlete Server, which is not open source. Please contact Authlete if you want to try Transformed Claims.
Implementation of Authorization Server
java-oauth-server is an open-source sample implementation of authorization server. It uses Authlete as a backend system that interprets OAuth/OIDC requests, generates & manages access tokens, and prepares OAuth/OIDC responses on behalf of a frontend authorization server.
If java-oauth-server is configured to use Authlete 2.3 that supports the latest IDA specification and Transformed Claims, you can try the specification explained in this article.
Below is a sample authorization request for java-oauth-server.
http://localhost:8080/api/authorization?client_id=7681191256&redirect_uri=http://localhost:4000/api/mock/redirection/5383012317&response_type=id_token&scope=openid+email&state=q4sa5o7g6y&nonce=n-0S6_WzA2Mj&claims={"id_token":{"verified_claims":{"verification":{"trust_framework":null,"assurance_process":{"assurance_details":[{"assurance_type":{"value":"verification"},"assurance_classification":null,"evidence_ref":{"txn":null}}]},"verification_process":null,"evidence":[{"type":{"value":"document"},"check_details":[{"check_method":{"value":"pvp"},"organization":null,"txn":null}],"time":null}]},"claims":{"given_name":null,"family_name":null,"address":{"street_address":null,"locality":null,"country":null},"::age_100_or_over":null,":age_18_or_over":null}}},"transformed_claims":{"age_18_or_over":{"claim":"birthdate","fn":["years_ago",["gte",18]]}}}
The JSON below is a formatted version of the content of the claims
request parameter for readability.
java-oauth-server will return an authorization page like below as a response to the authorization request.
An account for testing the latest IDA specification is inga
(Login ID = inga
, Password = inga
). Verified claims of the account are loaded from document_800_63A.json
and document_UKTDIF.json
(that were copied from the examples/response
directory in the eKYC-IDA Git repository).
If you input inga
& inga
to the Login ID & Password fields and press the “Authorize” button, the web browser will be redirected to the redirection endpoint hosted on java-oauth-server.
The JavaScript at the redirection endpoint displays information about the parameters the endpoint received. The page will look like below.
The payload part of the issued ID Token is as follows. You can confirm that data minimization and filtering worked and the transformed claims are contained in verified_claims/claims
.
Finally
Because of complexity and instability, it is hard to keep pace with evolution of the OIDC4IDA specification. However, by using Authlete as a backend system of your OAuth/OIDC server, you can delegate the hard task to domain experts in Authlete, Inc.
Please contact Authlete if you need a high-quality and leading-edge implementation of OAuth, OpenID Connect, Financial-grade API, Identity Assurance and other related standard specifications.