GAIN PoC Interim Report (Spring 2023)

Takahiko Kawasaki
11 min readMay 2



This is a copy (with some editorial adjustments) of the interim report about GAIN PoC I submitted to the GAIN PoC Community Group on March 26, 2023. Please note that while the report was well received by the group, it is not an officially endorsed document.


GAIN (Global Assured Identity Network) is a project to build a high-trust digital identity network over the Internet. The white paper of the project “GAIN DIGITAL TRUST” was co-authored by over 150 professionals in related fields and published on September 13, 2021. The white paper is freely downloadable from the GAIN website.

To research the technical feasibility of GAIN, volunteers formed GAIN PoC Community Group. This document is an interim report on the findings obtained through a year of activities by the community group.

Current Architecture of Ecosystems

The open banking movement started in the United Kingdom has spread to countries around the world. Australian Consumer Data Right (CDR) and Brazilian Open Finance are examples of the movement.

Each country has built its own ecosystem where multiple services and multiple applications connect with each other. Technically, the services and applications have implemented “authorization servers” and “relying parties” respectively whose technical details are defined in RFC 6749 The OAuth 2.0 Authorization Framework and other related standards.

In a typical implementation, a relying party belongs to one authorization server at a time. An authorization server and a relying party that do not have such a relationship cannot communicate with each other. Therefore, if an application wants to communicate with multiple services, the application has to establish a relationship with each service’s authorization server one by one.

To establish the relationship, an application registers itself to each authorization server by using the mechanism called “dynamic client registration”. The mechanism is defined in OpenID Connect Dynamic Client Registration 1.0 and RFC 7591 OAuth 2.0 Dynamic Client Registration Protocol.

An authorization server that supports dynamic client registration provides the dynamic client registration endpoint. The endpoint accepts a dynamic client registration request which contains a set of client metadata. Upon a successful registration, the endpoint returns JSON that contains actually-registered client metadata and a newly-issued client identifier. The application must remember the client identifier for later use.

To prevent unauthorized parties from registering clients, real-world deployments employ some countermeasures. An example is to require that a dynamic client registration request contain a “software statement” which has been issued by a trusted authority. In UK-style ecosystems, a central “directory” serves the role.

The diagram below (excerpted from “Implementer’s note about Open Banking Brasil”) illustrates the flow of issuance and verification of a software statement in Brazilian Open Banking. By verifying the presented software statement, the authorization server can be sure that the dynamic client registration request has come from a legitimate party.

Design Considerations

Decentralized Trust

One of the goals GAIN wants to achieve is to connect existing and future ecosystems with each other to build a cross-border network where applications can communicate with services in different ecosystems.

A straightforward architecture for the goal might be to build a single central directory that governs all applications and all services in the world. However, it is unrealistic because each ecosystem has its own regulatory requirements to meet local needs. Impact on ecosystems, even if any, must be as minimal as possible.

Trust between applications and services in different ecosystems should be able to be established without needing a single central authority.

Globally-Unique Client Identifiers

Client identifiers issued through the dynamic client registration are unique only in the authorization server that has issued them. Even within a single ecosystem, client identifiers issued by different authorization servers may conflict.

Therefore, applications in existing ecosystems have to manage carefully which client identifier has been issued by which authorization server. An application has to switch a client identifier that represents the application itself according to which service it wants to communicate with. This is a burden on the application side.

It is desirable that an application can use a single client identifier regardless of whatever service to communicate with.


For a high-trust digital identity, it should be ensured that user claims (such as family name and date of birth) have been obtained through KYC processes.

Adopted Standards

With the design considerations above, the community group decided to adopt the following specifications for the PoC.

OpenID Connect Federation 1.0

OpenID Connect Federation 1.0 (OIDC Federation) has the following characteristics that are appealing to the PoC.

First, the specification defines a mechanism where an identity provider (authorization server) and a relying party that have no direct relationship trust each other based on “trust chains” and the identity provider accepts OAuth/OIDC requests from the relying party without needing prior registration of the relying party.

Trust of the trust chains is assured by “trust anchors” and “intermediate authorities” that are independent of identity providers and relying parties. Trust chains of OIDC Federation are similar to certificate chains of Public Key Infrastructure. Trust anchors and intermediate authorities are conceptually equivalent to root certificate authority (Root CA) and intermediate certificate authority (Intermediate CA).

Second, an application can consistently use the same client identifier in every communication with different services. The client identifier is a globally-unique URL. The URL is determined not by an identity provider but by an entity that manages the relying party. OIDC Federation client identifiers have something in common with “Decentralized Identifiers” in that identifiers are determined by entities being identified.

OpenID Connect for Identity Assurance 1.0

Common social media out there may hold user claims (e.g. family name and date of birth), but the values of the claims are often just self-asserted ones. Therefore, they cannot be used in legal contexts. For example, a self-asserted date of birth cannot be used for the purpose of age verification to buy liquor, which is one of the use cases written in the GAIN white paper.

OpenID Connect for Identity Assurance 1.0 (OIDC4IDA) defines a mechanism to transmit user claims (e.g. family name and date of birth) that have been verified by official evidence such as passport and driver’s license. Identity providers that support OIDC4IDA can embed verified user claims in ID Tokens and responses from the userinfo endpoint.

Technically, information related to verified user claims is all put under “verified_claims”. Therefore, a relying party that receives an ID Token or a userinfo response can distinguish verified user claims from other normal (often just self-asserted) user claims.

The figure below excerpted from the web page of the eKYC-IDA Working Group illustrates how the content of verified_claims is structured.

Authorization Flow

The following diagram summarizes the authorization flow used in the PoC.

Technical points to note are as follows.

  1. The authorization flow starts from a PAR request. The client identifier contained in the request is a globally-unique URL.
  2. The PAR request contains a claims request parameter. The value of the parameter contains "id_token":{"verified_claims":...} to request the authorization server to embed verified user claims in the ID Token which will be issued from the token endpoint.
  3. The payload of the ID Token issued from the token endpoint contains verified_claims.

Authorization Flow Example

This section describes an example of authorization flow to show actual requests and responses.


Common variables used in the examples are defined as follows.

An important point in the PoC is that the client identifier (the value of CLIENT_ID) is a globally-unique URL. Actual files pointed to by the relative paths in the above list (i.e. the values of AUTH_PRI, MTLS_PRI and MTLS_CER) are in the GAIN PoC Git repository.

PAR Request

Prepare a client assertion for the private_key_jwt client authentication (RFC 7523). The generate-client-assertion.rb script in the command line below is in the GAIN PoC Git repository.

ASSERTION=`bin/generate-client-assertion.rb --aud=$ISSUER --key=$AUTH_PRI --sub=$CLIENT_ID`

Send a PAR request to the PAR endpoint. Newlines in the command line below are for display purposes only. An actual request should not contain newlines.

-d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
-d client_assertion=$ASSERTION
-d client_id=$CLIENT_ID
-d response_type=code
-d scope=openid
-d redirect_uri=$REDIRECT_URI
--data-urlencode claims='{
"fn":[ "years_ago", ["gte",18] ]

The PAR endpoint returns a response like below.

"expires_in": 90,

The value of the request_uri parameter in the PAR response is used in the following authorization request.

Authorization Request

Send an authorization request to the authorization endpoint via a web browser.${CLIENT_ID}&request_uri=${REQUEST_URI}

The authorization endpoint returns an authorization page. Input inga and inga as login ID and password (the login credentials are just for demo), and then press the “Authorize” button. If the login form needs to be displayed again, append &prompt=login at the end of the authorization request.

Token Request

Send a token request to the token endpoint. Newlines in the command line below are for display purposes only. An actual request should not contain newlines. Note that in the example the client certificate is included in the request by using the--key option and the --cert option for certificate binding (RFC 8705).

--key $MTLS_PRI
--cert $MTLS_CER
-d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
-d client_assertion=$ASSERTION
-d grant_type=authorization_code
-d redirect_uri=$REDIRECT_URI

The token endpoint returns a response like below. New lines and white spaces in the values of access_token and id_token are for display purposes only. Actual values do not contain them.


The payload of the ID Token in the example contains information equivalent to the following JSON. Points to note are that verified_claims is embedded (OIDC4IDA) and that the globally-unique URL is listed in the aud claim (OIDC Federation).

"iss": "",
"sub": "1004",
"aud": [
"exp": 1670608912,
"iat": 1670608612,
"auth_time": 1670607135,
"verified_claims": {
"verification": {
"trust_framework": "nist_800_63A"
"claims": {
"given_name": "Inga",
"family_name": "Silverstone",
"birthdate": "1991-11-06",
"::age_100_or_over": false,
":age_18_or_over": true

Trust Chain Resolution

When a client identifier in an authorization request is unknown but it is an HTTP-accessible URL, an authorization server that supports the OIDC Federation specification tries to construct a trust chain from the URL and determine whether the client identifier is acceptable or not. If the client identifier is acceptable, the authorization server registers the relying party automatically and continues to handle the authorization request. This process is called “automatic client registration”, which is different from “dynamic client registration” defined in OpenID Connect Dynamic Client Registration 1.0 and RFC 7591.

The procedure of automatic client registration is divided into the following steps.

  1. Resolve trust chains of the relying party and select one from among them.
  2. Apply the metadata policy of the selected trust chain if available.
  3. Authenticate the authorization request.
  4. Validate the client metadata.
  5. Register the relying party with the client metadata.

The first step is called “trust chain resolution”. It is the core of the decentralized trust.

Trust Chain Resolution Example

The diagram below (excerpted from “OpenID Connect Federation 1.0” on Authlete website) depicts the flow of trust chain resolution.

This section does not explain details of the specification but just shows actual messages exchanged between entities for trust chain resolution using as an example.

Relying Party’s Entity Configuration

The first step is to fetch the “entity configuration” of the relying party. The entity configuration is downloadable from the URL that is constructed by concatenating the client identifier and the fixed string "/.well-known/openid-federation".


An entity configuration is a kind of JWT. The following is an example response from the URL.


In the payload of the entity configuration, the following claim is contained.

"authority_hints": [

The authority_hints claim is a list of direct superior authorities (trust anchors and/or intermediate authorities) that may issue an “entity statement” for the relying party. In this example, the authority_hints claim contains one element.

Although the name of the element implies that it is a trust anchor, it is unknown whether it is a trust anchor or an intermediate authority at this timing. In either case, it is a direct superior authority of the relying party.

Superior Authority’s Entity Configuration

To request the superior authority to issue an entity statement for the relying party, it is necessary to know the URL of the Web API that can issue the entity statement. The Web API is called “fetch endpoint”.

Because the URL of the fetch endpoint is written in the entity configuration of the superior authority, the entity configuration needs to be downloaded.


The following is an example response of the superior authority’s entity configuration.


In the payload of the entity configuration, the following claim is contained.

"metadata": {
"federation_entity": {
"federation_list_endpoint": "",
"federation_fetch_endpoint": ""

The value of the federation_fetch_endpoint property is the URL of the fetch endpoint.

Entity Statement for Relying Party Issued By Superior Authority

The fetch endpoint issues an entity statement for an entity specified by the sub request parameter if the endpoint recognizes the specified entity.


The following is an example response from the fetch endpoint.


Trust Chain Verification

Because the entity configuration of the superior authority ( does not contain the authority_hints claim, the superior authority is a trust anchor. Therefore, the process of trust chain resolution terminates there.

As a result, the trust chain that consists of only two JWTs has been constructed. The first JWT is the entity configuration of the relying party and the last one is the entity statement issued from the fetch endpoint of the trust anchor.

If the authorization server knows the trust anchor as a trusted one and signatures of all the JWTs that have appeared in the process of trust chain resolution are verified, the trust chain is regarded as valid.

Note that public keys for signature verification are included in entity statements issued by direct superior authorities. The relationship is complex as the diagram below illustrates.



Takahiko Kawasaki

Co-founder and representative director of Authlete, Inc., working as a software engineer since 1997.