From bddbe253bd4448e1fe0f69ff2bec9ff590650f50 Mon Sep 17 00:00:00 2001 From: Adam Mika <88001738+amika-sq@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:30:34 -0700 Subject: [PATCH] Resolve did:web (#24) --- crates/dids/Cargo.toml | 1 + crates/dids/src/method/mod.rs | 1 + crates/dids/src/method/web.rs | 82 +++++++++++++++++++++++++++++++++++ crates/dids/src/resolver.rs | 12 +++++ 4 files changed, 96 insertions(+) create mode 100644 crates/dids/src/method/web.rs diff --git a/crates/dids/Cargo.toml b/crates/dids/Cargo.toml index e1882373..df0166f2 100644 --- a/crates/dids/Cargo.toml +++ b/crates/dids/Cargo.toml @@ -10,6 +10,7 @@ license-file.workspace = true async-trait = "0.1.74" crypto = { path = "../crypto" } did-jwk = "0.1.1" +did-web = "0.2.2" serde = { workspace = true } serde_json = { workspace = true } ssi-dids = "0.1.1" diff --git a/crates/dids/src/method/mod.rs b/crates/dids/src/method/mod.rs index c5a77253..acaabd41 100644 --- a/crates/dids/src/method/mod.rs +++ b/crates/dids/src/method/mod.rs @@ -1,4 +1,5 @@ pub mod jwk; +pub mod web; use crate::did::Did; use crate::resolver::DidResolutionResult; diff --git a/crates/dids/src/method/web.rs b/crates/dids/src/method/web.rs new file mode 100644 index 00000000..55aee2b2 --- /dev/null +++ b/crates/dids/src/method/web.rs @@ -0,0 +1,82 @@ +use crate::did::Did; +use crate::method::{DidMethod, DidMethodError, DidResolutionResult}; +use async_trait::async_trait; +use crypto::key_manager::KeyManager; +use did_web::DIDWeb as SpruceDidWebMethod; +use ssi_dids::did_resolve::{DIDResolver, ResolutionInputMetadata}; +use std::sync::Arc; + +/// Concrete implementation for a did:web DID +pub struct DidWeb { + uri: String, + key_manager: Arc, +} + +impl Did for DidWeb { + fn uri(&self) -> &str { + &self.uri + } + + fn key_manager(&self) -> &Arc { + &self.key_manager + } +} + +/// Options that can be used to create a did:web DID. +/// This is currently a unit struct because did:web does not support key creation. +pub struct DidWebCreateOptions; + +#[async_trait] +impl DidMethod for DidWeb { + const NAME: &'static str = "web"; + + fn create( + _key_manager: Arc, + _options: DidWebCreateOptions, + ) -> Result { + Err(DidMethodError::DidCreationFailure( + "create operation not supported for did:web".to_string(), + )) + } + + async fn resolve_uri(did_uri: &str) -> DidResolutionResult { + let input_metadata = ResolutionInputMetadata::default(); + let (did_resolution_metadata, did_document, did_document_metadata) = + SpruceDidWebMethod.resolve(did_uri, &input_metadata).await; + + DidResolutionResult { + did_resolution_metadata, + did_document, + did_document_metadata, + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_fails() { + let key_manager = Arc::new(crypto::key_manager::LocalKeyManager::new_in_memory()); + let result = DidWeb::create(key_manager, DidWebCreateOptions); + assert!(result.is_err()); + } + + #[tokio::test] + async fn resolution_success() { + let did_uri = "did:web:tbd.website"; + let result = DidWeb::resolve_uri(did_uri).await; + assert!(result.did_resolution_metadata.error.is_none()); + + let did_document = result.did_document.expect("did_document not found"); + assert_eq!(did_document.id, did_uri); + } + + #[tokio::test] + async fn resolution_failure() { + let result = DidWeb::resolve_uri("did:web:does-not-exist").await; + assert!(result.did_resolution_metadata.error.is_some()); + } +} diff --git a/crates/dids/src/resolver.rs b/crates/dids/src/resolver.rs index 16d82b85..4ed21361 100644 --- a/crates/dids/src/resolver.rs +++ b/crates/dids/src/resolver.rs @@ -1,4 +1,5 @@ use crate::method::jwk::DidJwk; +use crate::method::web::DidWeb; use crate::method::DidMethod; use serde::{Deserialize, Serialize}; use ssi_dids::did_resolve::{ @@ -18,6 +19,7 @@ impl DidResolver { match method_name { DidJwk::NAME => DidJwk::resolve_uri(did_uri).await, + DidWeb::NAME => DidWeb::resolve_uri(did_uri).await, _ => return DidResolutionResult::from_error(ERROR_METHOD_NOT_SUPPORTED), } } @@ -87,6 +89,16 @@ mod tests { assert_eq!(did_document.id, did_uri); } + #[tokio::test] + async fn resolve_did_web() { + let did_uri = "did:web:tbd.website"; + let result = DidResolver::resolve_uri(did_uri).await; + assert!(result.did_resolution_metadata.error.is_none()); + + let did_document = result.did_document.unwrap(); + assert_eq!(did_document.id, did_uri); + } + #[tokio::test] async fn resolve_invalid_did() { let did_uri = "did:jwk";