auths_infra_http/
identity_resolver.rs1use auths_core::ports::network::{IdentityResolver, ResolutionError, ResolvedIdentity};
2use auths_verifier::core::Ed25519PublicKey;
3use serde::Deserialize;
4use std::future::Future;
5
6use crate::default_http_client;
7use crate::request::{build_get_request, execute_request, parse_response_json};
8
9#[derive(Debug, Deserialize)]
10struct ResolvedIdentityResponse {
11 did: String,
12 public_key: Vec<u8>,
13 method: String,
14 #[serde(default)]
15 sequence: u64,
16 #[serde(default)]
17 can_rotate: bool,
18}
19
20pub struct HttpIdentityResolver {
33 base_url: String,
34 client: reqwest::Client,
35}
36
37impl HttpIdentityResolver {
38 pub fn new(base_url: impl Into<String>) -> Self {
39 Self {
40 base_url: base_url.into().trim_end_matches('/').to_string(),
41 client: default_http_client(),
42 }
43 }
44}
45
46impl IdentityResolver for HttpIdentityResolver {
47 fn resolve_identity(
48 &self,
49 did: &str,
50 ) -> impl Future<Output = Result<ResolvedIdentity, ResolutionError>> + Send {
51 let url = format!("{}/resolve/{}", self.base_url, did);
52 let request = build_get_request(&self.client, &url);
53 let did_owned = did.to_string();
54
55 async move {
56 let response = execute_request(request, &url)
57 .await
58 .map_err(ResolutionError::Network)?;
59
60 let status = response.status().as_u16();
61 if status == 404 {
62 return Err(ResolutionError::DidNotFound { did: did_owned });
63 }
64
65 let parsed: ResolvedIdentityResponse = parse_response_json(response, &did_owned)
66 .await
67 .map_err(ResolutionError::Network)?;
68
69 let public_key = Ed25519PublicKey::try_from_slice(&parsed.public_key).map_err(|e| {
70 ResolutionError::InvalidDid {
71 did: parsed.did.clone(),
72 reason: format!("invalid public key: {e}"),
73 }
74 })?;
75
76 match parsed.method.as_str() {
77 "key" => Ok(ResolvedIdentity::Key {
78 did: parsed.did,
79 public_key,
80 }),
81 "keri" => Ok(ResolvedIdentity::Keri {
82 did: parsed.did,
83 public_key,
84 sequence: parsed.sequence,
85 can_rotate: parsed.can_rotate,
86 }),
87 other => Err(ResolutionError::InvalidDid {
88 did: did_owned,
89 reason: format!("unsupported method: {other}"),
90 }),
91 }
92 }
93 }
94}