Skip to content

Commit

Permalink
refactor TangleLabs OIDC service
Browse files Browse the repository at this point in the history
  • Loading branch information
eike-hass committed Apr 17, 2024
1 parent 1463ffc commit c66f58a
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 87 deletions.
8 changes: 5 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ services:
# - redis
# - identity
environment:
ISSUERS_BANK_DID: did:iota:snd:0x1d78531b739a3aef0e90523213f28e869423a6d6253ea0fcbd7db2714e9606bf
ISSUERS_BANK_FRAGMENT: xwhWgiK3plOzbQESCONMneeFx4ps24rzbtC1jXEb42o
ISSUERS_BANK_DID: did:iota:snd:0x2cfb60f00089a91a96fa8fcee5e2bda15f51b0b062762ad9ca846bba536f8818
ISSUERS_BANK_FRAGMENT: S3zEW4inNy8FYZEMVTEthdzqqSBq1WglM2k75xKHzy0
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=Host(`backend.localhost`)"
Expand All @@ -60,6 +60,8 @@ services:
build:
context: ./
dockerfile: ./oid4vc/TangleLabs/Dockerfile
environment:
SIGNER_KEYID: pK0JAYw5RFFKqorBn0x4w98zl2UBfRys
expose:
- '50051'
volumes:
Expand Down Expand Up @@ -120,7 +122,7 @@ services:
image: iotaledger/identity-grpc:alpha
environment:
- API_ENDPOINT=http://host.docker.internal
- STRONGHOLD_PWD=nEyWjBDO3sQSDnXuwij3KIJREHnWhtIu
- STRONGHOLD_PWD=nhNc9yAjbCuh6YQxKlceLAUrWCwAYLvu
- SNAPSHOT_PATH=/stronghold.hodl
volumes:
- "./data/stronghold.hodl:/stronghold.hodl"
Expand Down
2 changes: 1 addition & 1 deletion oid4vc/TangleLabs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"type": "module",
"scripts": {
"start": "tsc --noEmit && node --loader ts-node/esm index.ts",
"start": "tsc --noEmit && node --loader ts-node/esm --experimental-specifier-resolution=node src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
Expand Down
98 changes: 17 additions & 81 deletions oid4vc/TangleLabs/index.ts → oid4vc/TangleLabs/src/grpcService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,27 @@ import { loadSync } from "@grpc/proto-loader";
import {
AuthResponse,
RelyingParty,
SigningAlgs,
SiopRequestResult,
bytesToString,
} from "@tanglelabs/oid4vc";
import * as KeyDIDResolver from "key-did-resolver";
import { Resolver } from "did-resolver";
import { PresentationDefinitionV2 } from "@sphereon/pex-models";

import { fileURLToPath } from 'url';
import { dirname } from 'path';

import express from "express";
import asyncHandler from "express-async-handler";

//@ts-ignore
import { driver } from "@digitalbazaar/did-method-key";
//@ts-ignore
import { Ed25519VerificationKey2020 } from "@digitalbazaar/ed25519-verification-key-2020";


import { Signer } from 'did-jwt';

const remoteSigner: Signer = async (data) => {
console.log(data);
return "test";
};

(async () => {

const __filename = fileURLToPath(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const protoPath = path.join(
__dirname,
"..",
"..",
"proto/oid4vc/siopv2.proto"
);
const packageDefinition = loadSync(protoPath);
const protoPackage = grpc.loadPackageDefinition(packageDefinition);

const didKeyDriver = driver();
const protoPath = path.join(
__dirname,
"..",
"..",
"..",
"proto/oid4vc/siopv2.proto"
);
const packageDefinition = loadSync(protoPath);
const protoPackage = grpc.loadPackageDefinition(packageDefinition);

didKeyDriver.use({
multibaseMultikeyHeader: "z6Mk",
fromMultibase: Ed25519VerificationKey2020.from,
});

const verificationKeyPair = await Ed25519VerificationKey2020.generate();

console.log(bytesToString(verificationKeyPair._publicKeyBuffer));
console.log(bytesToString(verificationKeyPair._privateKeyBuffer));

const keyDidResolver = KeyDIDResolver.getResolver();
let resolver = new Resolver(keyDidResolver);

const rp = new RelyingParty({
clientId: "did:iota:0x",
clientMetadata: {
subjectSyntaxTypesSupported: [
"did:iota"
],
idTokenSigningAlgValuesSupported: [
SigningAlgs.EdDSA
],
},
did: "did:iota:0x",
kid: "did:iota:0x#my_key",
signer: remoteSigner,
redirectUri: "http://192.168.0.234:8080/api/auth",
resolver: resolver,
});
export const createService = async (rp: RelyingParty) => {

async function createRequest(
call: grpc.ServerUnaryCall<
Expand Down Expand Up @@ -151,26 +100,13 @@ const __dirname = dirname(__filename);
gRPCServer.bindAsync(
"0.0.0.0:50051",
grpc.ServerCredentials.createInsecure(),
() => {
gRPCServer.start();
(err, port) => {
if(err){
throw err;
}
console.log(`gRPC server listening on port ${port}`);
}
);


const app = express();
app.use(express.json());
app.route("/api/health").get(
asyncHandler(async (req, res) => {
res.status(200).send();
})
);
app.route("/api/auth").post(
asyncHandler(async (req, res) => {
console.log(req);
await rp.verifyAuthResponse(req.body);
res.status(204).send();
})
);
const server = app.listen(3333, "0.0.0.0");

})();
};
26 changes: 26 additions & 0 deletions oid4vc/TangleLabs/src/httpServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import express from "express";
import asyncHandler from "express-async-handler";

export const createServer = (rp) => {

const app = express();
app.use(express.json());
app.route("/api/health").get(
asyncHandler(async (req, res) => {
res.status(200).send();
})
);
app.route("/api/auth").post(
asyncHandler(async (req, res) => {
console.log(req);
await rp.verifyAuthResponse(req.body);
res.status(204).send();
})
);

const port = 3333;
const server = app.listen(port, "0.0.0.0", () => {
console.log(`HTTP server listening on port ${port}`);
});

};
56 changes: 56 additions & 0 deletions oid4vc/TangleLabs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
RelyingParty,
SigningAlgs,
bytesToString,
} from "@tanglelabs/oid4vc";
import * as KeyDIDResolver from "key-did-resolver";
import { Resolver } from "did-resolver";

//@ts-ignore
import { driver } from "@digitalbazaar/did-method-key";
//@ts-ignore
import { Ed25519VerificationKey2020 } from "@digitalbazaar/ed25519-verification-key-2020";


import { remoteSigner } from "./remoteSigner";
import { createService } from "./grpcService";
import { createServer } from "./httpServer";

(async () => {

const didKeyDriver = driver();

didKeyDriver.use({
multibaseMultikeyHeader: "z6Mk",
fromMultibase: Ed25519VerificationKey2020.from,
});

const verificationKeyPair = await Ed25519VerificationKey2020.generate();

console.log(bytesToString(verificationKeyPair._publicKeyBuffer));
console.log(bytesToString(verificationKeyPair._privateKeyBuffer));

const keyDidResolver = KeyDIDResolver.getResolver();
let resolver = new Resolver(keyDidResolver);

const rp = new RelyingParty({
clientId: "did:iota:0x",
clientMetadata: {
subjectSyntaxTypesSupported: [
"did:iota"
],
idTokenSigningAlgValuesSupported: [
SigningAlgs.EdDSA
],
},
did: "did:iota:0x",
kid: "did:iota:0x#my_key",
signer: remoteSigner(process.env.SIGNER_KEYID),
redirectUri: "http://192.168.0.234:8080/api/auth",
resolver: resolver,
});

createService(rp);
createServer(rp);

})();
43 changes: 43 additions & 0 deletions oid4vc/TangleLabs/src/remoteSigner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import path from "path";
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import * as grpc from "@grpc/grpc-js";
import { loadSync } from "@grpc/proto-loader";
import { Signer } from 'did-jwt';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const identityProtoPath = path.join(
__dirname,
"..",
"..",
"..",
"proto/identity/utils.proto"
);

const identityPackageDefinition = loadSync(identityProtoPath);
const identityPackage = grpc.loadPackageDefinition(identityPackageDefinition).utils;

export const remoteSigner: (keyId: string) => Signer = (keyId) => async (data) => {

//@ts-ignore
const identityClient = new identityPackage.Signing(
'identity:50051', grpc.credentials.createInsecure()
);

console.debug(data);

const response = await new Promise((resolve, reject) => identityClient.sign({
keyId,
data: Array.from(Buffer.from(data)),
}, (err, response) => {
if (err) {
console.error(err);
}
resolve(response);
}));
console.log(response)
return response as string;

};
22 changes: 22 additions & 0 deletions proto/identity/utils.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";
package utils;

message DataSigningRequest {
// Raw data that will be signed.
bytes data = 1;
// Signing key's ID.
string key_id = 2;
}

message DataSigningResponse {
// Raw data signature.
bytes signature = 1;
}

// Service that handles signing operations on raw data.
service Signing {
rpc sign(DataSigningRequest) returns (DataSigningResponse);
}
11 changes: 9 additions & 2 deletions tooling/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use identity_iota::iota::IotaIdentityClientExt;
use identity_iota::iota::NetworkName;
use identity_iota::resolver::Resolver;
use identity_iota::storage::JwkDocumentExt;
use identity_iota::storage::KeyId;
use identity_iota::storage::MethodDigest;
use identity_stronghold::ED25519_KEY_TYPE;

use rand::distributions::{Alphanumeric, DistString};
Expand All @@ -23,6 +25,8 @@ use iota_sdk::client::Client;
use iota_sdk::client::Password;
use iota_sdk::types::block::address::Address;
use iota_sdk::types::block::output::AliasOutput;
use identity_iota::storage::KeyIdStorage;


// The API endpoint of an IOTA node, e.g. Hornet.
const API_ENDPOINT: &str = "http://localhost";
Expand Down Expand Up @@ -68,7 +72,7 @@ async fn main() -> anyhow::Result<()> {
Ok(())
}

async fn create_issuer(stronghold_storage: &StrongholdStorage, client: &Client) -> anyhow::Result<(String, String, Address)> {
async fn create_issuer(stronghold_storage: &StrongholdStorage, client: &Client) -> anyhow::Result<(String, KeyId, String, Address)> {
// Create a DID document.
let address: Address = get_address_with_funds(
&client,
Expand Down Expand Up @@ -97,6 +101,9 @@ async fn create_issuer(stronghold_storage: &StrongholdStorage, client: &Client)
)
.await?;

let method = document.resolve_method(&fragment, Some(MethodScope::VerificationMethod)).ok_or(anyhow::anyhow!("no go"))?;
let key_id = storage.key_id_storage().get_key_id(&MethodDigest::new(method)?).await?;

// Construct an Alias Output containing the DID document, with the wallet address
// set as both the state controller and governor.
let alias_output: AliasOutput = client.new_did_output(address, document, None).await?;
Expand Down Expand Up @@ -129,5 +136,5 @@ async fn create_issuer(stronghold_storage: &StrongholdStorage, client: &Client)
String::from_utf8_lossy(decoded_jws.claims.as_ref()),
"test_data"
);
Ok((document.id().to_string(), fragment, address))
Ok((document.id().to_string(), key_id, fragment, address))
}

0 comments on commit c66f58a

Please sign in to comment.