1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//! DID resolution and production: the [`DidResolver`] and [`DidProducer`] traits a DID method
//! implements, the [`Resolver`] registry that routes a DID to the resolver of its method, an
//! optional TTL [`DocumentCache`], and DID URL dereferencing.
//!
//! The module ships no DID method. Each method is a type implementing [`DidResolver`] and/or
//! [`DidProducer`], registered with [`ResolverBuilder::with`]; adding one needs no change here.
//!
//! # Resolution
//!
//! [`Resolver::resolve`] implements the DID Resolution algorithm around the method's resolver:
//! it reports [`ResolutionError::MethodNotSupported`] for a method nobody registered, turns a
//! result whose metadata reports an error into `Err`, refuses a document whose `id` is not the
//! DID being resolved (nor its `canonicalId`), and serves repeated resolutions from the cache
//! when one is configured. [`Resolver::resolve_document`] is the shortcut to the document.
//!
//! # Dereferencing
//!
//! [`Resolver::dereference`] resolves the DID of a DID URL and then selects the resource the URL
//! names: the document itself, or the verification method or service whose `id` is the URL
//! ([`Dereferenced`]). The `versionId` and `versionTime` DID parameters are passed to the
//! method's resolver as resolution options; a path, any other query parameter and the
//! `service`/`relativeRef` parameters are method-specific and reported as
//! [`DereferenceError::MethodSpecific`]. [`Resolver::resolve_public_key`] goes one step further
//! and returns the [`Jwk`](crate::jose::Jwk) of a verification method, optionally checked to be
//! usable for a verification relationship, decoding `publicKeyMultibase` material as a Multikey,
//! which is what a JWS verifier needs.
//!
//! # Examples
//!
//! A method is a type implementing [`DidResolver`]; here one that serves documents from memory.
//!
//! ```
//! use std::collections::HashMap;
//!
//! use identity_kit::did::{
//! Did, DidDocument, DidUrl, ResolutionError, ResolutionOptions, ResolutionResult,
//! };
//! use identity_kit::resolver::{Dereferenced, DidResolver, Resolver};
//!
//! struct Static(HashMap<Did, DidDocument>);
//!
//! #[async_trait::async_trait]
//! impl DidResolver for Static {
//! fn method(&self) -> &'static str {
//! "example"
//! }
//!
//! async fn resolve(
//! &self,
//! did: &Did,
//! _: &ResolutionOptions,
//! ) -> Result<ResolutionResult, ResolutionError> {
//! self.0
//! .get(did)
//! .cloned()
//! .map(ResolutionResult::new)
//! .ok_or(ResolutionError::NotFound)
//! }
//! }
//!
//! # tokio::runtime::Builder::new_current_thread().build()?.block_on(async {
//! let document: DidDocument = serde_json::from_str(r##"{
//! "id": "did:example:123",
//! "verificationMethod": [{
//! "id": "did:example:123#key-1",
//! "type": "JsonWebKey2020",
//! "controller": "did:example:123",
//! "publicKeyJwk": {
//! "kty": "OKP", "crv": "Ed25519", "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
//! }
//! }],
//! "authentication": ["#key-1"]
//! }"##)?;
//! let did = document.id.clone();
//! let resolver = Resolver::builder()
//! .with(Static(HashMap::from([(did.clone(), document)])))
//! .cache(std::time::Duration::from_secs(60))
//! .build();
//!
//! assert_eq!(resolver.resolve_document(&did).await?.id, did);
//!
//! let key = DidUrl::parse("did:example:123#key-1")?;
//! let jwk = resolver.resolve_public_key(&key, None).await?;
//! assert_eq!(jwk.crv(), Some("Ed25519"));
//! assert!(matches!(resolver.dereference(&key).await?, Dereferenced::VerificationMethod(_)));
//!
//! let unknown = Did::parse("did:other:123")?;
//! assert_eq!(
//! resolver.resolve(&unknown).await.unwrap_err(),
//! ResolutionError::MethodNotSupported
//! );
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! # })?;
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
use Arc;
use crate;
pub use DocumentCache;
pub use ;
pub use ;
pub use ;
/// Resolves the DIDs of one method (DID Resolution "DID Resolution Algorithm").
///
/// A resolver is registered with a [`Resolver`] under [`method`](Self::method) and receives
/// only DIDs of that method. It is `Send + Sync` and resolution is `async` because most methods
/// fetch the document over the network or from a registry.
///
/// A failed resolution may be reported either as `Err`, or as an `Ok` result whose resolution
/// metadata carries the error, which is the shape a method that builds a full
/// [`ResolutionResult`] (a client of a remote resolver, say) produces anyway. The [`Resolver`]
/// normalizes both to `Err`.
forward_did_resolver!;