CAIP-169: Simple Credential Interface Provider

Author Oliver Terbu, Mircea Nistor, Bumblefudge
Discussions-To https://github.com/veramolabs/credential-provider-eip/pulls?q=is%3Apr+
Status Draft
Type Standard
Created 2021-08-18
Updated 2022-11-07
Requires 25

Simple Summary

A common interface for decentralized applications and cryptocurrency wallets (or other key management applications described in future CASA namespaces and CAIPs) to communicate about and pass Verifiable Credentials and Verifiable Presentations is needed for the chain-agnostic world to interact with emerging decentralized/portable data applications. Many [elsewhere mandatory] aspects of the verifiable credential and decentralized identifier stacks are left out of scope to be handled in future CAIPs as needed, storage and encryption being two notable examples.

This specification adds new methods to the multi-provider JSON-RPC for storing, creating, selectively disclosing and proving control of offchain- and onchain credentials under a new wallet_creds_ prefix.

Abstract

After a dapp has requested and a wallet has declared basic verifiable credentials capabilities in the CAIP-25 feature-discovery step, dapps can assume the wallet will be able to support all the methods defined below. Note that many of these calls should be routable to services, other software, or even other dapps, without leaking information about the wallet or architecture to the calling dapp.

This CAIP describes a few core RPC methods that combine to act as a wallet-side Credential Provider (CP) to support Verifiable Credentials (VCs) storage, issuance, proof-of-control, and even (with some extensions) selective disclosure or advancing proofing of those credentials.

VCs are self-certifiable attestations from an issuer about the subject of the VC. The holder of a VC can directly consent to disclosing information from those VCs and, in combination with other tokens or cryptographic forms of evidence, substantiate their context or the relationship between holder and subject. See the VC spec for more context. To facilitate developer experience and progress towards end-to-end interoperability, this CAIP limits its scope to a few supported proof types and focuses on a limited subset of today’s VC systems. This CAIP is important for use cases such as privacy-preserving compliance, sign-in, sign-up, and decentralized reputation-based authorization.

Motivation

Web3 applications like DAOs, Defi, NFT market places etc. need verifiable offchain and onchain reputation to enable certain features for their end users. Web3 is missing a coherent method for requesting identity assertions from their users, e.g. for sign-in and sign-up. The majority of Web3 projects are using an approach where they cryptographically bind a signature produced by a single-context (and single-chain) wallet to the identity assertion; in the EVM, for example, these approaches usually rely on either eth.personal.sign or EIP-712. The identity assertion becomes self-certifiable with this approach, but tightly bound to the Ethereum address as the only identifier. To improve privacy it is important to introduce a mechanism that allows people to selectively disclose the linkage between another identifier (such as a chain-agnostic or off-chain DID) and their blockchain account address.

This can be done through VCs and DIDs. This CAIP introduces new JSON-RPC methods that are needed to build decentralized reputation for offchain and onchain uses alike.

The identifiers by which issuers and holders and their key material are dereferenced for verification and binding purposes are out of scope of this specification, but complemented nicely by DID-based approaches such as those established in the EVM space by [EIP-2844][] or the cross-chain blockchain-based approach indexed by the did pkh multicodec. Implementing verifiable credential exchange without DIDs may lead to a closed and limited system with limited interoperability or exportability; systems that can extend and federate over time are encouraged to build in flexibility at both the credential format level as well as the decentralized identifier level.

Specification

Three new JSON-RPC methods are specified under the new wallet_creds_* prefix.

Verifiable Credential Proofs

This section provides guidance on recommended LD-Proof Suites and IANA JWS algorithm support of embedded and external proofs for VCs. The abbreviations for common VC formats in production today are taken from the DIF Claim Format registry of the Presentation Exchange meta-protocol specification governed by the Decentralized Identity Foundation, while the Verifiable Credentials profile defining their proof formats are specified in the VC spec itself.

Embedded Proofs

Credential issuance systems MUST support the following LD-Proof types for embedded proofs (i.e. VC-LDP):

Credential issuance systems are RECOMMENDED to support the following LD-Proof types for wide support of VC formats with embedded proofs (i.e. VC-LDP):

External Proofs

CPs SHOULD support the following IANA JWS algorithms for external proofs (i.e. VC-JWT):

A helpful test suite for conformance-testing VC-JWT signing can be found at JWS-test-suite.

Supported Verifiable Credentials Profile

VCs that can be used with this specification MUST be valid JSON-LD as defined in the VC spec. VCs and VPs MUST use either the proofs recommended by Embedded Proofs or External Proofs above to conform to this specification; implementations are RECOMMENDED to limit themselves to algorithms and key types corresponding to registered claim formats in the DIF Claim Format registry if they are expecting reasonable interoperability in the near term, and to carefully construct their presentation_definition object accordingly.

Store

Stores the given VC in the CP.

Method:

wallet_creds_store

Params:
  • vc - A Verifiable Credential.
Returns:
  • error - OPTIONAL. If vc was malformed or does not comply with the Verifiable Credentials Profile defined in this specification. Note that some wallets will call wallet_creds_verify locally or remotely and pass back an error message received thereby, depending on security context.
    • 400 - invalid parameters
    • 500 - processing or internal error
    • 501 - invalid cryptographic primitives (see wallet_creds_metadata)

Verify

Verifies the proof section of a single verifiable credential after dereferencing its issuer property for key material. Note that in an application<>wallet connection, the application calls the wallet for the wallet to either perform verification locally or remotely; in either case, the application will await asynchronously for a success or error code, regardless of how the wallet verifies the passed credential. Wallets that cannot return appropriate error codes back MUST NOT authorize apps to call this method as undefined behavior may occur.

Method:

wallet_creds_verify

Params:
  • vc - A Verifiable Credential.
Returns:
  • error - OPTIONAL. If vc was malformed or does not comply with the Verifiable Credentials Profile defined in this specification.

Issue

Called by the wallet to the application, providing the parameters needed for a credential issuance and expecting back a verifiable credential OR an error. The parameters are formated as a credential_application object as specified in the Credential Manifest specification.

Method:

wallet_creds_issue

Params:
  • credential_application - REQUIRED. This can vary from the full contents of the payload of the to-be-issued credential to a mere consent event per use-case, but in either case MUST be formated as a valid credential_application object as specified in the Credential Manifest specification.
  • preferred_proofs - OPTIONAL. An ordered array (from most to least preferred) of preferred proof formats and types for the VC to be issued. Each array item is an object with two properties, format and type. format indicates the preferred proof type, which is either jwt for (External Proofs) or ldp for (Embedded Proofs). The type refers to proof type of the VC (see Verifiable Credentials Proofs for a list of valid combinations). If the wallet does not support any of the preferred proofs, the wallet can select a format and type from the list defined in Verifiable Credentials Proofs as a fallback.
Returns:
  • vc - OPTIONAL. Present if the call was successful. A Verifiable Credential that was issued to the CP by the application.
  • error - OPTIONAL. If payload was malformed, or does not comply with the Verifiable Credentials Profile defined in this specification.
    • 400 - invalid credential_application or payload construction
    • 500 - processing or internal error

Present

The application calls the wallet to request verifiable claims from the CP. For the query, we will use the DIF Presentation Exchange data model. Optionally, holder binding can also be requested.

Method:

wallet_creds_present

Params:
  • presentation_definition - A presentation_definition object as defined in the Presentation Exchange specification; among other parameters such as claim format, this can also include constraints about selective disclosure, LD framing, and optional holder binding requirements.
  • domain - OPTIONAL. If holder binding was requested, this parameter is mandatory.
  • challenge - OPTIONAL. If holder binding was requested, this parameter is mandatory.
Returns:
  • vp - OPTIONAL. Present if the call was successful. It contains a Verifiable Presentation (VP) structured as a JSON object that contains the requested VCs from the CP.
  • error - OPTIONAL. Present if presentation_definition was malformed, does not comply with the Verifiable Credentials Profile defined in this specification.

Example:

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://identity.foundation/presentation-exchange/submission/v1"
  ],
  "type": ["VerifiablePresentation", "PresentationSubmission"],
  "holder": "did:example:123",
  "presentation_submission": {
    "id": "1d257c50-454f-4c96-a273-c5368e01fe63",
    "definition_id": "32f54163-7166-48f1-93d8-ff217bdb0654",
    "descriptor_map": [
      {
        "id": "vaccination_input",
        "format": "ldp_vp",
        "path": "$.verifiableCredential[0]"
      }
    ]
  },
  "verifiableCredential": [
    {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/vaccination/v1",
        "https://w3id.org/security/bbs/v1"
      ],
      "id": "urn:uvci:af5vshde843jf831j128fj",
      "type": ["VaccinationCertificate", "VerifiableCredential"],
      "description": "COVID-19 Vaccination Certificate",
      "name": "COVID-19 Vaccination Certificate",
      "expirationDate": "2029-12-03T12:19:52Z",
      "issuanceDate": "2019-12-03T12:19:52Z",
      "issuer": "did:example:456",
      "credentialSubject": {
        "id": "urn:bnid:_:c14n2",
        "type": "VaccinationEvent",
        "batchNumber": "1183738569",
        "countryOfVaccination": "NZ"
      },
      "proof": {
        "type": "BbsBlsSignatureProof2020",
        "created": "2021-02-18T23:04:28Z",
        "nonce": "JNGovx4GGoi341v/YCTcZq7aLWtBtz8UhoxEeCxZFevEGzfh94WUSg8Ly/q+2jLqzzY=",
        "proofPurpose": "assertionMethod",
        "proofValue": "AB0GQA//jbDwMgaIIJeqP3fRyMYi6WDGhk0JlGJc/sk4ycuYGmyN7CbO4bA7yhIW/YQbHEkOgeMy0QM+usBgZad8x5FRePxfo4v1dSzAbJwWjx87G9F1lAIRgijlD4sYni1LhSo6svptDUmIrCAOwS2raV3G02mVejbwltMOo4+cyKcGlj9CzfjCgCuS1SqAxveDiMKGAAAAdJJF1pO6hBUGkebu/SMmiFafVdLvFgpMFUFEHTvElUQhwNSp6vxJp6Rs7pOVc9zHqAAAAAI7TJuDCf7ramzTo+syb7Njf6ExD11UKNcChaeblzegRBIkg3HoWgwR0hhd4z4D5/obSjGPKpGuD+1DoyTZhC/wqOjUZ03J1EtryZrC+y1DD14b4+khQVLgOBJ9+uvshrGDbu8+7anGezOa+qWT0FopAAAAEG6p07ghODpi8DVeDQyPwMY/iu2Lh7x3JShWniQrewY2GbsACBYOPlkNNm/qSExPRMe2X7UPpdsxpUDwqbObye4EXfAabgKd9gCmj2PNdvcOQAi5rIuJSGa4Vj7AtKoW/2vpmboPoOu4IEM1YviupomCKOzhjEuOof2/y5Adfb8JUVidWqf9Ye/HtxnzTu0HbaXL7jbwsMNn5wYfZuzpmVQgEXss2KePMSkHcfScAQNglnI90YgugHGuU+/DQcfMoA0+JviFcJy13yERAueVuzrDemzc+wJaEuNDn8UiTjAdVhLcgnHqUai+4F6ONbCfH2B3ohB3hSiGB6C7hDnEyXFOO9BijCTHrxPv3yKWNkks+3JfY28m+3NO0e2tlyH71yDX0+F6U388/bvWod/u5s3MpaCibTZEYoAc4sm4jW03HFYMmvYBuWOY6rGGOgIrXxQjx98D0macJJR7Hkh7KJhMkwvtyI4MaTPJsdJGfv8I+RFROxtRM7RcFpa4J5wF/wQnpyorqchwo6xAOKYFqCqKvI9B6Y7Da7/0iOiWsjs8a4zDiYynfYavnz6SdxCMpHLgplEQlnntqCb8C3qly2s5Ko3PGWu4M8Dlfcn4TT8YenkJDJicA91nlLaE8TJbBgsvgyT+zlTsRSXlFzQc+3KfWoODKZIZqTBaRZMft3S/",
        "verificationMethod": "did:example:123#key-1"
      }
    }
  ],
  "proof": {
    "type": "Ed25519Signature2018",
    "verificationMethod": "did:example:123#key-0",
    "created": "2021-05-14T20:16:29.565377",
    "proofPurpose": "authentication",
    "challenge": "3fa85f64-5717-4562-b3fc-2c963f66afa7",
    "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..7M9LwdJR1_SQayHIWVHF5eSSRhbVsrjQHKUrfRhRRrlbuKlggm8mm_4EI_kTPeBpalQWiGiyCb_0OWFPtn2wAQ"
  }
}

Wallet Metadata

Called by the application to fetch a configuration object describing signing and verification capabilities of the wallet. This method is an optional way for CAIP-169 supporting wallets to signal signing and verifying capabilities in addition to those necessary for the blockchain/VM-specific accounts and methods already exposed; it is required for interoperability with OIDC-based protocols, and its absence can be interpreted as an absence of interoperability with protocols requiring it.

The formatting and values of the metadata object are borrowed from the [OIDC4VP][] specification, which in references the DIF Claim Format registry for the names of objects and IANA JOSE Registry for the exact, case-sensitive abbreviations contained therein. Note that no other values from a full OAuth2 Authorization Server metadata need to be present, and they will be ignored if included.

NOTE: alg value none SHOULD NOT be accepted.

Method:

wallet_creds_metadata

Params:
  • URL_accepted - OPTIONAL. Boolean, default to false if not present. If true, metadata object MAY be passed as an HTTPS URL OR as an object; otherwise, MUST be passed as a JSON object.
Returns:
  • metadata_object - OPTIONAL. See [OIDC4VP][] section “Authorization Server Metadata” for properties.
  • error - OPTIONAL.
    • 400 - invalid request
    • 500 - error forming response from selected credentials
    • 501 - invalid cryptographic primitives (see wallet_creds_metadata)

Example

{
  "vp_formats_supported": {
    "jwt_vc": {
      "alg_values_supported": [
        "ES256K",
        "ES384"
     ]
    },
    "jwt_vp": {
      "alg_values_supported": [
        "ES256K",
        "EdDSA"
     ]
    }
  }
}

Rationale

The VC Data Model defines a Verifiable Presentation but does not provide detail on how to express the constraints that a relying party can impose on a presentation. The Presentation Exchange Data Model defines a definition and submission format for among other things, verifiable presentations.

The Universal Wallet Interop Spec describes how to use concrete protocols such as Wallet Connect and WACI Presentation Exchange with DID Comm Messaging.

In cases where a holder is directly connected to a verifier over a secure transport, encryption and messaging related standards such as DIDComm are not required, however interoperable data models for expressing presentation requirements and submissions are still needed to support interoperability with existing standards.

This proposal defines a set of API extensions that would enable web3 wallet providers to offer wallet and credential interactions to web origins that already support web3 wallet providers.

This functionality is similar to the interfaces supported by the credential handler api, which does not support the Presentation Exchange Data Model specification but does offer more flexible support for Linked Data verifiable credential formats and a rich interface for wallet selection via the Credential Handler API (CHAPI). Interoperability with other set of interfaces may require extensions or breaking changes to this specification, and is out of scope for now.

Backwards Compatibility

TBD

Test Cases

See:

Known Implementations

  • TBD
  • TBD
  • TBD

Security Considerations

User consent must be obtained prior to accessing wallet APIs. One way of achieving this is with a strong UX around CAIP-25 authorization to ensure meaningful user consent to access levels per account, per method/wallet capability (including those specified in this specification), and per additional resource.

The relying party MUST ensure that: the challenge required by the verifiable presentation is sufficiently random; that it is used only once, tracked against some form of session object (see CAIP-170 and CAIP-171), etc; or that it is some form of expiring verifiable credential encoded as a string. Man-in-the-middle protection and other security assumptions fall on the relying party (i.e. the calling application) to secure.

Appropriate domain-binding for web/http-based dapp-wallet connections is assumed and out of scope for this specification. Other CAIPs may be forthcoming for hardening this assumption, or may rely on the domain-binding enforced by a preceding [CAIP-122][] flow.

Similarly, holder binding (e.g. binding the current wallet controller to the wallet controller at time of credential issuance) is out of scope of this specification but assumed by it. Where no holder binding beyond wallet control is enforced, the submission details can be tampered with and should be considered unsecured. Some useful forms of holder binding can be provided by: wallet-level strong authentication; supplemental liveness or multi-factor authentication mechanisms; complex holder-binding mechanisms registered as extensions to the [VC Extension Registry][]; future CAIPs; etc.

Specifications (Dependencies)

  • VC spec - Core data model for verifiable credentials
  • DID EIP - Prior art for handling basic DID functions as methods in the standard ethereum provider; these are not required for VC functionality per se but can greatly extend the verification model for issuers and holders of VCs alike, enable on-chain VC verification, etc.
  • Data Integrity spec - Formerly referred to as “Linked Data Proofs,” this specification for embedding proofs in structured data objects like JSON-LD documents and verifiable credentials specifies the handling of distinct credentials that flatten an open-world/RDF-style graph to be signed and verified.
  • Presentation Exchange - DIF-incubated high-level VC protocol (optimized for handling both JWT-VCs and JWTs at scale)
  • Credential Manifest - DIF-incubated high-level VC issuance protocol
  • DIF Claim Format registry - A registry of formats supported by Presentation Exchange

Specifications (Optional Dependencies and Prior Art)

  • VC API - W3C-CCG-incubated VC protocol (optimized for LinkedData VCs and the Credential Handler API)
  • DIDComm - DIF-incubated messaging layer, which includes sub-protocols for VCs extending the earlier “Present Proof” protocols incubated in Hyperledger Aries community.
  • [OIDC4VP][] - A specification written at and governed by the OIDF that describes VC issuance from OIDC servers and conceives of self-custody cryptographic wallets as “Authorization Servers” in OIDC terminology.

Prior Art and Reference Implementations

  • JWS-test-suite - A self-serve, open-source conformance test suite for VC-JWT implementations
  • Veramo Project - EVM-friendly but multi-chain sample libraries for issuing, signing, holding, verifying and presenting verifiable credentials
  • Walt.id prototype - note that WC Chat API is used as a shim for the interface defined above; otherwise, a helpful prototype for illustrating a lightweight flow

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Oliver Terbu, Mircea Nistor, Bumblefudge, "CAIP-169: Simple Credential Interface Provider [DRAFT]," Chain Agnostic Improvement Proposals, no. 169, August 2021. [Online serial]. Available: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-169.md