For identity providers such as the Internet Identity, the principal under which a user is known to a dapp is not only unique to that dapp but its value is also unpredictable. While this separation provides several security and privacy benefits, it makes it hard for dapps to share information about their users with one another, such as user attributes, since the same user will be known under a different identity for each dapp, as indicated in the figure below. Hence, the goal of this project is to provide means for third-party dapps (relying parties) to handle attributes issued by other dapps (issuers) in a privacy preserving manner.
In order to solve this problem, there are a few parameters that need to be specified in the architecture.
- Who can issue credentials
- Trusted identity providers: In some architectures such as Concordium's blockchain [Concordium], trusted identity providers are responsible for issuing and managing attributes to users.
- Any entity or user: In other cases, such as in the W3C's verifiable credential standard [VC-DATA-MODEL], any entity is allowed to be an issuer. In this case, it is up to relying party dapps to decide which issuers they are willing to trust during the verification process.
- Who decides which issuers to trust
- Off-chain: In some architectures, such as Concordium's blockchain [Concordium], there is a particular entity such as the Foundation who is responsible for managing the registration of identity providers
- RP - relying party: In the W3C's verifiable credential standard [VC-DATA-MODEL], the relying party is the one that decides which issuers can be trusted.
- NNS / SNS: Another possibility is for Decentralized Autonomous Organizations (DAOs), such as the NNS or an SNS, to decide which issuers to trust.
- Who pays for the service
- Self-sovereign identity: In this setting, the owner of identity would be responsible for paying for the service being provided by the issuer. This option potentially provides better privacy since the issuer in principle would not be aware of which relying party is verifying the user attributes.
- Relying party - RP: In this setting, the relying party in charge of verifying a user's attribute would be responsible for paying for the service being provided by the issuer. This option is hard to implement securely because the identity provider needs to guarantee that the relying party gets charged correctly by the issuer without compromising the unlinkability among the principals in the RP and issuer dapps.
- Who defines the semantics for attributes
- Application: In this setting, the specification of attributes would be done at the application level and independently of the identity provider, which would only help pass this information between the RP and issuer dapps.
- Identity provider: In this case, the semantics of attributes would be defined by the identity provider and applications would have to adhere to it.
- Who specifies the policy
- Each dapp: this is the most general setting and would allow different dapps to specify their own policies.
- Replica / subnet: this option is more restrictive but possibly simpler to implement.
- How to handle revocation of credentials
- Query-based revocation: In this setting, RP dapps need to query the issuer dapp to check the status of a credential. If this query relies solely on the principal id at the issuer dapp, then this query would need support from the identity provider. Although query-based revocation provides up-to-date status information, it can potentially leak the user access pattern to the issuer.
- Whitelist-based revocation: In this setting, the issuer would maintain a public list with the current set of valid credentials. If the credential is associated with the principal at the issuer dapp, the RP dapp would need help from the identity provider to check this information. This solution has the disadvantage of unnecessarily leaking the list of valid credentials.
- Blacklist-based revocation: In this setting, the issuer would maintain a public list with the current set of revoked credentials. As for whitelists, the RP dapp would need help from the identity provider to check this information if credentials are associated with principals at the issuer dapp.
- Handling credentials from multiple issuers
- Certain RP dapps may require the verification of credentials issued by multiple dapps and we need to consider how these credentials can be safely combined to provide a verifiable presentation which does not break the unlikability of principals.
Given the different options listed above, we propose the following design choices which are more consistent with the decentralized philosophy of the Internet Computer:
- Allow any entity to issue credentials
- Let relying party dapps decide which issuers to trust
- Let applications define the semantics for attributes
- Support for revocation lists and the handling of multiple credentials
- Support for both self-sovereign identities and relying parties to pay for the service
In order to meet these requirements, we propose to first provide a solution focused on self-sovereign identities without any payment support and then to add payment support at a second step so that relying parties can pay for the issuance of credentials.
In order to provide attribute support in a privacy-preserving manner, our proposed solution is for the identity provider to securely link user principals without revealing both principals to issuers and relying parties, so that attributes can be mapped from one principal to another, as indicated in the figure below.
Let PIssuer and PRP be the identities under which a user is known to the issuing and relying party dapp canisters. In order to securely link these principals, our proposal is to let the identity provider create a joint identifier PNew to be shared between these dapps and to provide separate signatures securely linking PNew to PIssuer and PRP respectively.
In order to preserve user privacy, the value of PNew needs to be unpredictable. One way of achieving this is to choose a random new value for every session in which the relying party dapp needs to obtain attributes from an issuing dapp. However, for simplicity and efficiency reasons, we recommend to set the value of PNew as a (pseudorandom) deterministic functions (PRFs) [PRF] of the user anchors and the frontend origins at the issuing and relying party dapps.
Following the intuition above, we now propose a specific flow focused on self-sovereign identities, which does not provide payment support.
This proposal has the following features:
- It provides user privacy via the establishment of a new joint identifier computed as a function of the issuer and the relying party frontend origins and the identities under which the user is known to these dapps. This is represented by steps (7) and (8).
- It allows relying parties and identity providers to agree on the user attributes that need to be included in the user credential via a presentation exchange. This protocol exchange can be based on the Presentation Exchange Specification [DIF-Presentation-Exchange] by the Decentralized Identity Foundation (DIF). This is represented by steps (3) and (12).
- It allows issuers to specify the inputs that are required from a subject to process a request for credential issuance via the use of credential manifests [DIF-Credential-Manifests]. This is represented by steps (4) and (5).
- Identity providers can use the credential manifest information to submit the credential application for the user. This is represented by step (11).
- If the issuer accepted the credential application by the user, it issues a credential using the new joint identifier for the user, as indicated in step (14). The credential format can be based on the verifiable credentials data model [VC-DATA-MODEL].
- It allows users to use different anchors with respect to the issuer and relying party dapps, as indicated in step (7).
- Sign up / login
- User logins with the relying party (RP) or creates an account
- RP frontend checks whether user attributes have been verified
- Generate key pair (RPSK,RPPK)
- RP frontend opens the Identity Provider (IdP) frontend on a separate window, sending:
- Presentation request (see [DIF-Presentation-Exchange])
- RPPK
- Issuing dapp
- RP dapp
- IdP frontend requests credential manifest from the issuer backend
- Data format can be based on DIF's credential manifest [DIF-Credential-Manifest]
- This step may not be needed if the IdP has previously obtained the manifest.
- Issuer backend replies with the credential manifest
- This step may not be needed if the IdP has previously obtained the manifest.
- User logins with anchorRP and anchorIssuer
- User is presented with an authorization request based on the presentation request from the RP and the credential manifest from the issuer
- User authorizes delegations to IdP1 (anchorRP) and IdP2 (anchorIssuer)
- IdP frontend requests from backend a session to generate a credential, including
- anchorRP
- anchorIssuer
- Issuing dapp frontend origin
- RP dapp frontend origin
- IdP backend returns the following to the IdP frontend:
- A signed pair (PNew, PIssuer)🔒
- A signed pair (PNew, PRP)🔒
- PNew = PRFseed(anchorRP,anchorIssuer,RPorig,ISorig)
- where PRFseed is a pseudorandom function with secret key seed [PRF]
- IdP frontend opens the issuer frontend on a separate window, requesting session key
- Issuer frontend generates session key and sends it to the IdP frontend
- Generate key pair (ISSK,ISPK)
- Send (ISPK + request reference)
- IdP frontend requests credential for PIssuer under PNew, including
- Credential application [DIF-Credential-Manifests]
- A signed pair (PNew, PIssuer)🔒
- IdP2 delegation to PIssuer
- Request reference
- Issuer frontend contacts its backend to verify attributes and request the credential
- This may require interaction with the user to verify the user's attributes
- The frontend sends both PIssuer and PNew to the backend
- If the user passes the verification, the backend issues a credential for PNew
- Issuer backend returns a signed credential for PNew
- Issuer frontend sends credential to the IdP frontend, including:
- Credential for PNew
- Request reference
- IdP frontend forwards the credential to the RP frontend, including:
- A signed pair (PNew, PRP)🔒
- IdP1 delegation to PRP
- Credential for PNew
- RP frontend interacts with its backend to update the user status
To be done at a later time.