Skip to content

Commit

Permalink
docs: add introductory documentation for all crates (#57)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nanderstabel committed Sep 12, 2023
1 parent d24cdc1 commit b743f3c
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 194 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
13 changes: 13 additions & 0 deletions dif-presentation-exchange/README.md
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 5 additions & 0 deletions oid4vc-core/README.md
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions oid4vc-manager/README.md
Original file line number Diff line number Diff line change
@@ -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)
16 changes: 16 additions & 0 deletions oid4vci/README.md
Original file line number Diff line number Diff line change
@@ -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.
15 changes: 15 additions & 0 deletions oid4vp/README.md
Original file line number Diff line number Diff line change
@@ -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.
205 changes: 11 additions & 194 deletions siopv2/README.md
Original file line number Diff line number Diff line change
@@ -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<did_url::DID> {
Ok(did_url::DID::parse("did:mymethod:subject")?)
}

fn key_id(&self) -> Option<String> {
Some("key_id".to_string())
}

async fn sign<'a>(&self, message: &'a str) -> Result<Vec<u8>> {
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<Vec<u8>> {
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<Vec<u8>> {
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.

0 comments on commit b743f3c

Please sign in to comment.