Skip to content

Commit

Permalink
did:jwk resolution service
Browse files Browse the repository at this point in the history
  • Loading branch information
UMR1352 committed Jul 25, 2024
1 parent 6f874df commit f1756c0
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
13 changes: 13 additions & 0 deletions bindings/grpc/proto/utils.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,16 @@ service Signing {
rpc sign(DataSigningRequest) returns (DataSigningResponse);
}

message DidJwkResolutionRequest {
// did:jwk string
string did = 1;
}

message DidJwkResolutionResponse {
// JSON DID Document
string doc = 1;
}

service DidJwk {
rpc resolve(DidJwkResolutionRequest) returns (DidJwkResolutionResponse);
}
2 changes: 1 addition & 1 deletion bindings/grpc/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn routes(client: &Client, stronghold: &StrongholdStorage) -> Routes {
routes.add_service(domain_linkage::service(client));
routes.add_service(document::service(client, stronghold));
routes.add_service(status_list_2021::service());
routes.add_service(utils::service(stronghold));
utils::init_services(&mut routes, stronghold);
routes.add_service(presentation::service(client));

routes.routes()
Expand Down
66 changes: 64 additions & 2 deletions bindings/grpc/src/services/utils.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use _utils::did_jwk_server::DidJwk as DidJwkSvc;
use _utils::did_jwk_server::DidJwkServer;
use _utils::signing_server::Signing as SigningSvc;
use _utils::signing_server::SigningServer;
use _utils::DataSigningRequest;
use _utils::DataSigningResponse;
use _utils::DidJwkResolutionRequest;
use _utils::DidJwkResolutionResponse;
use anyhow::Context;
use identity_iota::core::ToJson;
use identity_iota::did::CoreDID;
use identity_iota::document::DocumentBuilder;
use identity_iota::storage::JwkStorage;
use identity_iota::storage::KeyId;
use identity_iota::storage::KeyStorageError;
use identity_iota::verification::jwk::Jwk;
use identity_iota::verification::jwu::decode_b64_json;
use identity_iota::verification::VerificationMethod;
use identity_stronghold::StrongholdStorage;
use tonic::transport::server::RoutesBuilder;
use tonic::Request;
use tonic::Response;
use tonic::Status;
Expand Down Expand Up @@ -62,6 +74,56 @@ impl SigningSvc for SigningService {
}
}

pub fn service(stronghold: &StrongholdStorage) -> SigningServer<SigningService> {
SigningServer::new(SigningService::new(stronghold))
pub fn init_services(routes: &mut RoutesBuilder, stronghold: &StrongholdStorage) {
routes.add_service(SigningServer::new(SigningService::new(stronghold)));
routes.add_service(DidJwkServer::new(DidJwkService {}));
}

#[derive(Debug)]
pub struct DidJwkService {}

#[tonic::async_trait]
impl DidJwkSvc for DidJwkService {
#[tracing::instrument(
name = "utils/resolve_did_jwk",
skip_all,
fields(request = ?req.get_ref())
ret,
err,
)]
async fn resolve(&self, req: Request<DidJwkResolutionRequest>) -> Result<Response<DidJwkResolutionResponse>, Status> {
let DidJwkResolutionRequest { did } = req.into_inner();
let jwk = parse_did_jwk(&did).map_err(|e| Status::invalid_argument(e.to_string()))?;
let did = CoreDID::parse(did).expect("valid did:jwk");
let verification_method =
VerificationMethod::new_from_jwk(did.clone(), jwk, Some("0")).map_err(|e| Status::internal(e.to_string()))?;
let verification_method_id = verification_method.id().clone();
let doc = DocumentBuilder::default()
.id(did)
.verification_method(verification_method)
.assertion_method(verification_method_id.clone())
.authentication(verification_method_id.clone())
.capability_invocation(verification_method_id.clone())
.capability_delegation(verification_method_id.clone())
.key_agreement(verification_method_id)
.build()
.map_err(|e| Status::internal(e.to_string()))?;

Ok(Response::new(DidJwkResolutionResponse {
doc: doc.to_json().map_err(|e| Status::internal(e.to_string()))?,
}))
}
}

fn parse_did_jwk(did: &str) -> anyhow::Result<Jwk> {
let did_parts: [&str; 3] = did
.split(':')
.collect::<Vec<_>>()
.try_into()
.map_err(|_| anyhow::anyhow!("invalid did:jwk \"{did}\""))?;

match did_parts {
["did", "jwk", data] => decode_b64_json(data).context("failed to deserialize JWK"),
_ => anyhow::bail!("invalid did:jwk string \"{did}\""),
}
}

0 comments on commit f1756c0

Please sign in to comment.