From b743f3ce36257f9900b8441e2c2c10e5fb170ae1 Mon Sep 17 00:00:00 2001 From: Nander Stabel Date: Tue, 12 Sep 2023 11:12:36 +0200 Subject: [PATCH] docs: add introductory documentation for all crates (#57) * docs: add specs README's * fix: remove README.md in link paths * WIP * WIP * add oid4vc-manager and oid4vc-core READMEs * grammarly fixes * several edits --- README.md | 26 ++++ dif-presentation-exchange/README.md | 13 ++ oid4vc-core/README.md | 5 + oid4vc-manager/README.md | 15 ++ oid4vci/README.md | 16 +++ oid4vp/README.md | 15 ++ siopv2/README.md | 205 ++-------------------------- 7 files changed, 101 insertions(+), 194 deletions(-) create mode 100644 README.md create mode 100644 dif-presentation-exchange/README.md create mode 100644 oid4vc-core/README.md create mode 100644 oid4vc-manager/README.md create mode 100644 oid4vci/README.md create mode 100644 oid4vp/README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..b6ce1c0a --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Rust library for OpenID for Verifiable Credentials + +This is a library for the OpenID for Verifiable Credentials (OpenID4VC) specifications family developed by the [OpenID +Digital Credentials Protocols +Working Group](https://openid.net/wg/digital-credentials-protocols/). + +The Digital Credentials Protocols (DCP) Working Group focuses on creating OpenID specifications for a model where +issuers provide digital credentials to holders, allowing holders to present them to verifiers. These digital +credentials contain cryptographically signed statements about the holder, and verifiers can check their authenticity. +The primary goals include enhancing user control and privacy over identity information, making identity verification +more efficient and secure, and establishing a universal approach for identification, authentication, and authorization +in both digital and physical spaces. + +An overview of all the specifications developed by the OpenID Digital Credentials Protocols Working Group can be found [here](https://openid.net/wg/digital-credentials-protocols/specifications/). + +This workspace includes Rust implementations for the following DCP specifications: +* [OID4VCI](oid4vci): OpenID for Verifiable Credential Issuance +* [OID4VP](oid4vp): OpenID for Verifiable Presentations +* [SIOPv2](siopv2): Self-Issued OpenID Provider v2 + +On top of that, this workspace also includes a library for the [DIF Presentation Exchange +2.0.0](https://identity.foundation/presentation-exchange/spec/v2.0.0/): +* [DIF Presentation Exchange](dif-presentation-exchange) + +For an easy-to-use library that combines all the above specifications, please check out: +* [OID4VC-Manager](oid4vc-manager) diff --git a/dif-presentation-exchange/README.md b/dif-presentation-exchange/README.md new file mode 100644 index 00000000..c94f784a --- /dev/null +++ b/dif-presentation-exchange/README.md @@ -0,0 +1,13 @@ +# DIF Presentation Exchange 2.0.0 +This is Rust a library for the [DIF Presentation Exchange +2.0.0](https://identity.foundation/presentation-exchange/spec/v2.0.0/) specification developed by the [Decentralized +Identity Foundation](https://identity.foundation/). + +## Description +This specification addresses the need for a standardized way to demand and submit proofs in identity systems. It introduces a Presentation Definition format for Verifiers to express proof requirements and a Presentation Submission format for Holders to describe proof submissions. + +Key Points: +* The specification is format-agnostic, supporting various Claim formats as long as they can be serialized as JSON. +* It is also transport-envelope agnostic, allowing the conveyance of data via different methods like [OpenID4VP](../oid4vp), OpenID Connect, DIDComm, or Credential Handler API. +* The goal is to promote unified procedures and reduce redundant code. +* The specification does not define transport protocols or specific endpoints but encourages their use in other projects that define such mechanisms. diff --git a/oid4vc-core/README.md b/oid4vc-core/README.md new file mode 100644 index 00000000..752ed587 --- /dev/null +++ b/oid4vc-core/README.md @@ -0,0 +1,5 @@ +# OID4VC Core +The oid4vc-core library is a foundational component used by other OpenID for Verifiable Credentials (OpenID4VC) Rust libraries. It provides essential core functionality and utilities, offering consistency and efficiency in OpenID4VC-related projects. For detailed specifications and implementations, please refer to the following libraries: +* [OID4VCI](oid4vci): OpenID for Verifiable Credential Issuance +* [OID4VP](oid4vp): OpenID for Verifiable Presentations +* [SIOPv2](siopv2): Self-Issued OpenID Provider v2 diff --git a/oid4vc-manager/README.md b/oid4vc-manager/README.md new file mode 100644 index 00000000..32da5e30 --- /dev/null +++ b/oid4vc-manager/README.md @@ -0,0 +1,15 @@ +# OID4VC Manager +The OID4VC-Manager library serves as a versatile toolkit for implementing the OpenID for Verifiable Credentials (OpenID4VC) specifications family. Developed by the OpenID Digital Credentials Protocols Working Group, this library empowers developers to work with cutting-edge standards designed to enhance identity verification, privacy, and control for end-users. + +The OpenID Digital Credentials Protocols Working Group is dedicated to creating OpenID specifications that enable a +robust model where issuers provide digital credentials to holders. These digital credentials contain cryptographically +signed statements about the holder, offering verifiers the ability to verify their authenticity. The overarching goals +include strengthening user control and privacy over identity information, optimizing identity verification for +efficiency and security, and establishing a universal framework for identification, authentication, and authorization in +the digital, as well as in the real world. + +In this library, you'll find Rust implementations for several critical DCP specifications, including: +* [OpenID for Verifiable Credential + Issuance](https://openid.bitbucket.io/connect/openid-4-verifiable-credential-issuance-1_0.html) (OpenID4VCI) +* [OpenID for Verifiable Presentations](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html) (OpenID4VP) +* [Self-Issued OpenID Provider v2](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html) (SIOPv2) diff --git a/oid4vci/README.md b/oid4vci/README.md new file mode 100644 index 00000000..fff8f69d --- /dev/null +++ b/oid4vci/README.md @@ -0,0 +1,16 @@ +# OpenID for Verifiable Credential Issuance +This is a Rust library for the [OpenID for Verifiable Credential Issuance](https://openid.bitbucket.io/connect/openid-4-verifiable-credential-issuance-1_0.html) (OpenID4VCI) specification developed by the [OpenID +Digital Credentials Protocols +Working Group](https://openid.bitbucket.io/connect/openid-4-verifiable-presentations-1_0.html). + +An overview of all the OpenID Digital Credentials Protocols implementation in Rust can be found [here](../README.md). + +## Description +The OpenID for Verifiable Credential Issuance specification outlines an API that serves the purpose of issuing Verifiable Credentials. It is designed to support a range of formats, including W3C formats as well as other Credential formats like ISO.18013-5. + +Verifiable Credentials bear a strong resemblance to identity assertions, akin to ID Tokens in OpenID Connect. They enable a Credential Issuer to assert claims on behalf of an End-User. These Verifiable Credentials adhere to a predefined schema, known as the Credential type, and they may be associated with a specific holder, often through cryptographic holder binding. Importantly, Verifiable Credentials can be securely presented to the RP (Relying Party) without requiring the direct involvement of the Credential Issuer. + +Access to this API is granted through the authorization mechanism provided by OAuth 2.0. In essence, the Wallet employs +OAuth 2.0 to obtain the necessary authorization for receiving Verifiable Credentials. This approach leverages the +well-established security, simplicity, and flexibility of OAuth 2.0. It also allows existing OAuth 2.0 deployments and +OpenID Connect OPs to extend their functionality to become Credential Issuers. diff --git a/oid4vp/README.md b/oid4vp/README.md new file mode 100644 index 00000000..9996e8ae --- /dev/null +++ b/oid4vp/README.md @@ -0,0 +1,15 @@ +# OpenID for Verifiable Presentations +This is a Rust library for the [OpenID for Verifiable Presentations](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html) (OpenID4VP) specification developed by the [OpenID +Digital Credentials Protocols +Working Group](https://openid.bitbucket.io/connect/openid-4-verifiable-presentations-1_0.html). + +An overview of all the OpenID Digital Credentials Protocols implementation in Rust can be found [here](../README.md). + +## Description +The OpenID for Verifiable Presentations specification establishes a protocol that builds upon OAuth 2.0. Its primary purpose is to facilitate the presentation of Verifiable Credentials in the form of Verifiable Presentations. These Verifiable Credentials and Presentations can take various formats, including but not limited to the W3C Verifiable Credentials Data Model, ISO mdoc, and AnonCreds. + +The choice of OAuth 2.0 as the foundational protocol is strategic, as it provides the essential framework necessary to construct a straightforward, secure, and user-friendly layer for presenting Credentials. This layer is built atop OAuth 2.0, leveraging its existing mechanisms. Importantly, this specification enables implementers to seamlessly support the presentation of Credentials and the issuance of Access Tokens. These Access Tokens are crucial for gaining access to APIs based on Verifiable Credentials stored in a Wallet. + +Furthermore, this specification serves the purpose of extending OpenID Connect deployments. By doing so, it empowers these deployments with the capability to transport Verifiable Presentations. The inclusion of Verifiable Presentations enhances the capabilities of OpenID Connect deployments and broadens the scope of their applications. + +It's worth noting that this specification can also be used in conjunction with [SIOPv2](../siopv2) when implementers require OpenID Connect functionalities, such as the issuance of Self-Issued ID Tokens. This flexibility allows for the integration of OpenID Connect features into the Verifiable Credentials ecosystem. diff --git a/siopv2/README.md b/siopv2/README.md index 11eef884..0265b9a1 100644 --- a/siopv2/README.md +++ b/siopv2/README.md @@ -1,199 +1,16 @@ -# openid4vc -This library aims to support all the specifications under the [OpenID for Verifiable Credentials](https://openid.net/openid4vc/) -works. - -OpenID for Verifiable Credentials (OID4VC) consists of the following specifications: -* [OpenID for Verifiable Credential Issuance (OID4VCI)](https://openid.bitbucket.io/connect/openid-4-verifiable-credential-issuance-1_0.html) – Defines an API and corresponding OAuth-based authorization mechanisms for issuance of Verifiable Credentials - -* [OpenID for Verifiable Presentations (OID4VP)](https://openid.bitbucket.io/connect/openid-4-verifiable-presentations-1_0.html) – Defines a mechanism on top of OAuth 2.0 to allow presentation of claims in the form of Verifiable Credentials as part of the protocol flow - -* [Self-Issued OpenID Provider v2 (SIOPv2)](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html) – Enables End-Users to use OpenID Providers (OPs) that they control - -* [OpenID for Verifiable Presentations over BLE](https://openid.bitbucket.io/connect/openid-4-verifiable-presentations-over-ble-1_0.html) – Enables using Bluetooth Low Energy (BLE) to request the presentation of verifiable credentials. It uses the request and response syntax as defined in OID4VP. +# Self-Issued OpenID Provider v2 +This is a Rust library for the [Self-Issued OpenID Provider v2](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html) (SIOPv2) specification developed by the [OpenID +Digital Credentials Protocols +Working Group](https://openid.net/wg/digital-credentials-protocols/). +An overview of all the OpenID Digital Credentials Protocols implementation in Rust can be found [here](../README.md). ## Description +The Self-Issued OpenID Provider v2 (SIOPv2) specification enhances the capabilities of the OpenID Connect framework. OpenID Connect primarily facilitates the sharing of identity information from an OpenID Provider (OP) to a Relying Party (RP) on behalf of an End-User. In this traditional model, RPs trust identity assertions made by the OP, which acts as the issuer of these assertions. -Currently the Implicit Flow is consists of four major parts: - -- A `Provider` that can accept a `AuthorizationRequest` and generate a `AuthorizationResponse` by creating an `IdToken`, adding its key identifier to the header of the `id_token`, signing the `id_token` and wrap it into a `AuthorizationResponse`. It can also send the `AuthorizationResponse` using the `redirect_uri` parameter. -- A `RelyingParty` struct which can validate a `AuthorizationResponse` by validating its `IdToken` using a key identifier (which is extracted from the `id_token`) and its public key. -- The `Subject` trait can be implemented on a custom struct representing the signing logic of a DID method. A `Provider` can ingest an object that implements the `Subject` trait so that during generation of a `AuthorizationResponse` the DID method syntax, key identifier and signing method of the specific `Subject` can be used. -- The `Validator` trait can be implemented on a custom struct representing the validating logic of a DID method. When ingested by a `RelyingParty`, it can resolve the public key that is needed for validating an `IdToken`. - -## Example - -```rust -use anyhow::Result; -use async_trait::async_trait; -use chrono::{Duration, Utc}; -use ed25519_dalek::{Keypair, Signature, Signer}; -use lazy_static::lazy_static; -use siopv2::{ - claims::{ClaimRequests, ClaimValue, IndividualClaimRequest}, - request::ResponseType, - Provider, ClientMetadata, RelyingParty, RequestUrl, AuthorizationResponse, Scope, AuthorizationRequest, StandardClaims, Subject, Validator, -}; -use rand::rngs::OsRng; -use wiremock::{ - http::Method, - matchers::{method, path}, - Mock, MockServer, ResponseTemplate, -}; - -lazy_static! { - pub static ref TEST_KEYPAIR: Keypair = Keypair::generate(&mut OsRng); -} - -// A Subject type that can be ingested by a Provider -#[derive(Default)] -pub struct MySubject; - -impl MySubject { - pub fn new() -> Self { - MySubject {} - } -} - -#[async_trait] -impl Subject for MySubject { - fn did(&self) -> Result { - Ok(did_url::DID::parse("did:mymethod:subject")?) - } - - fn key_id(&self) -> Option { - Some("key_id".to_string()) - } - - async fn sign<'a>(&self, message: &'a str) -> Result> { - let signature: Signature = TEST_KEYPAIR.sign(message.as_bytes()); - Ok(signature.to_bytes().to_vec()) - } -} - -#[async_trait] -impl Validator for MySubject { - async fn public_key<'a>(&self, _kid: &'a str) -> Result> { - Ok(TEST_KEYPAIR.public.to_bytes().to_vec()) - } -} - -// A Validator type that can be ingested by a RelyingParty -#[derive(Default)] -pub struct MyValidator; - -#[async_trait] -impl Validator for MyValidator { - async fn public_key<'a>(&self, _kid: &'a str) -> Result> { - Ok(TEST_KEYPAIR.public.to_bytes().to_vec()) - } -} - -#[tokio::main] -async fn main() { - // Create a new mock server and retreive it's url. - let mock_server = MockServer::start().await; - let server_url = mock_server.uri(); - - // Create a new validator. - let validator = MySubject::default(); - - // Create a new relying party. - let relying_party = RelyingParty::new(validator); - - // Create a new RequestUrl with response mode `post` for cross-device communication. - let request: AuthorizationRequest = RequestUrl::builder() - .response_type(ResponseType::IdToken) - .client_id("did:mymethod:relyingparty".to_string()) - .scope(Scope::openid()) - .redirect_uri(format!("{server_url}/redirect_uri")) - .response_mode("post".to_string()) - .client_metadata( - ClientMetadata::default() - .with_subject_syntax_types_supported(vec!["did:mymethod".to_string()]) - .with_id_token_signing_alg_values_supported(vec!["EdDSA".to_string()]), - ) - .claims(ClaimRequests { - id_token: Some(StandardClaims { - name: Some(IndividualClaimRequest::default()), - ..Default::default() - }), - ..Default::default() - }) - .exp((Utc::now() + Duration::minutes(10)).timestamp()) - .nonce("n-0S6_WzA2Mj".to_string()) - .build() - .and_then(TryInto::try_into) - .unwrap(); - - // Create a new `request_uri` endpoint on the mock server and load it with the JWT encoded `AuthorizationRequest`. - Mock::given(method("GET")) - .and(path("/request_uri")) - .respond_with(ResponseTemplate::new(200).set_body_string(relying_party.encode(&request).await.unwrap())) - .mount(&mock_server) - .await; - - // Create a new `redirect_uri` endpoint on the mock server where the `Provider` will send the `AuthorizationResponse`. - Mock::given(method("POST")) - .and(path("/redirect_uri")) - .respond_with(ResponseTemplate::new(200)) - .mount(&mock_server) - .await; - - // Create a new subject. - let subject = MySubject::default(); - - // Create a new provider. - let provider = Provider::new(subject).await.unwrap(); - - // Create a new RequestUrl which includes a `request_uri` pointing to the mock server's `request_uri` endpoint. - let request_url = RequestUrl::builder() - .request_uri(format!("{server_url}/request_uri")) - .build() - .unwrap(); - - // The Provider obtains the reuquest url either by a deeplink or by scanning a QR code. It then validates the - // request. Since in this case the request is a JWT, the provider will fetch the request by sending a GET - // request to mock server's `request_uri` endpoint. - let request = provider.validate_request(request_url).await.unwrap(); - - // Assert that the request was successfully received by the mock server at the `request_uri` endpoint. - let get_request = mock_server.received_requests().await.unwrap()[0].clone(); - assert_eq!(get_request.method, Method::Get); - assert_eq!(get_request.url.path(), "/request_uri"); - - // Let the provider generate a response based on the validated request. The response is an `IdToken` which is - // encoded as a JWT. - let response = provider - .generate_response( - request, - StandardClaims { - name: Some(ClaimValue("Jane Doe".to_string())), - ..Default::default() - }, - ) - .await - .unwrap(); - - // The provider sends it's response to the mock server's `redirect_uri` endpoint. - provider.send_response(response).await.unwrap(); - - // Assert that the AuthorizationResponse was successfully received by the mock server at the expected endpoint. - let post_request = mock_server.received_requests().await.unwrap()[1].clone(); - assert_eq!(post_request.method, Method::Post); - assert_eq!(post_request.url.path(), "/redirect_uri"); - let response: AuthorizationResponse = serde_urlencoded::from_bytes(post_request.body.as_slice()).unwrap(); +The Self-Issued OP extends this framework by introducing the concept of an OP that is under the control of the End-User. In this scenario, the Self-Issued OP does not assert identity information about the End-User. Instead, it empowers the End-User to become the issuer of their own identity information. This allows end-users to authenticate themselves using Self-Issued ID Tokens signed with keys they control and present self-attested claims directly to RPs. - // The `RelyingParty` then validates the response by decoding the header of the id_token, by fetching the public - // key corresponding to the key identifier and finally decoding the id_token using the public key and by - // validating the signature. - let id_token = relying_party.validate_response(&response).await.unwrap(); - assert_eq!( - id_token.standard_claims(), - &StandardClaims { - name: Some(ClaimValue("Jane Doe".to_string())), - ..Default::default() - } - ); -} -``` +Notably, Self-Issued OPs can also present cryptographically verifiable claims issued by third parties trusted by RPs. +This is made possible by using separate specifications, such as [OpenID for Verifiable Presentations](../oid4vp), or by utilizing Aggregated and Distributed +Claims. This capability streamlines the interaction between end-users and +RPs without requiring RPs to directly communicate with the issuers of said claims.