From 705232bf306d2ab7c1c29ad96e716ad4e3557161 Mon Sep 17 00:00:00 2001
From: Berend Sliedrecht <61358536+berendsliedrecht@users.noreply.github.com>
Date: Tue, 23 Jul 2024 13:42:41 +0200
Subject: [PATCH 001/172] updated test issuer and rp to support x509 (#2)
* updated test issuer and rp to support x509
---
README.md | 3 +-
agent/.env.development | 4 +-
agent/package.json | 16 +-
agent/src/agent.ts | 112 +-
agent/src/constants.ts | 33 +-
agent/src/did/cheqd.ts | 45 -
agent/src/did/createKeys.ts | 17 -
agent/src/did/index.ts | 7 -
agent/src/did/indy.ts | 26 -
agent/src/did/jwk.ts | 16 -
agent/src/did/key.ts | 17 -
agent/src/did/setup.ts | 48 -
agent/src/did/util.ts | 17 -
agent/src/did/web.ts | 47 -
agent/src/endpoints.ts | 456 +-
agent/src/issuer.ts | 260 +-
agent/src/issuerMetadata.ts | 125 +-
agent/src/keyMethods/createKeys.ts | 12 +
.../keyMethods/createSelfSignedCertificate.ts | 13 +
agent/src/keyMethods/index.ts | 1 +
agent/src/keyMethods/setup.ts | 46 +
agent/src/server.ts | 50 +-
agent/src/session.ts | 2 +-
agent/src/verifier.ts | 14 +-
app/app/layout.tsx | 18 +-
app/app/page.tsx | 4 +-
app/components.json | 2 +-
app/components/IssueTab.tsx | 152 +-
app/components/ReceiveTab.tsx | 44 +-
app/components/VerifyTab.tsx | 158 +-
app/components/highLight.tsx | 27 +-
app/components/main.tsx | 18 +-
app/components/ui/alert.tsx | 67 +-
app/components/ui/button.tsx | 49 +-
app/components/ui/card.tsx | 110 +-
app/components/ui/input.tsx | 37 +-
app/components/ui/label.tsx | 23 +-
app/components/ui/select.tsx | 53 +-
app/components/ui/tabs.tsx | 14 +-
app/components/ui/tooltip.tsx | 22 +-
app/components/ui/typography.tsx | 28 +-
app/lib/api.ts | 79 +-
app/lib/constants.ts | 3 +-
app/lib/hooks.ts | 26 +-
app/lib/utils.ts | 4 +-
app/next.config.js | 6 +-
app/tailwind.config.ts | 33 +-
biome.json | 49 +
docker-compose.yml | 13 +-
package.json | 9 +-
pnpm-lock.yaml | 14644 +++++++++-------
yarn.lock | 4 -
52 files changed, 8768 insertions(+), 8315 deletions(-)
delete mode 100644 agent/src/did/cheqd.ts
delete mode 100644 agent/src/did/createKeys.ts
delete mode 100644 agent/src/did/index.ts
delete mode 100644 agent/src/did/indy.ts
delete mode 100644 agent/src/did/jwk.ts
delete mode 100644 agent/src/did/key.ts
delete mode 100644 agent/src/did/setup.ts
delete mode 100644 agent/src/did/util.ts
delete mode 100644 agent/src/did/web.ts
create mode 100644 agent/src/keyMethods/createKeys.ts
create mode 100644 agent/src/keyMethods/createSelfSignedCertificate.ts
create mode 100644 agent/src/keyMethods/index.ts
create mode 100644 agent/src/keyMethods/setup.ts
create mode 100644 biome.json
delete mode 100644 yarn.lock
diff --git a/README.md b/README.md
index f924605..4a4af31 100644
--- a/README.md
+++ b/README.md
@@ -57,8 +57,7 @@ cp .env.example .env
| `AGENT_WALLET_KEY` | Used in the backend application for the agent. Should be secure and kept private. |
> [!IMPORTANT]
-> The issuer will use `did:web` for issuing credentials, but this requires `https` to be used. When developing locally it is recommend
-> to use `ngrok` (`npx ngrok http 3001`) and use that url as the `AGENT_HOST` variable. Make sure to also set the `NEXT_PUBLIC_API_URL` variable in the app to the ngrok.
+> You can use `ngrok` (`npx ngrok http 3001`) and use that url as the `AGENT_HOST` variable. Make sure to also set the `NEXT_PUBLIC_API_URL` variable in the app to the ngrok.
>
> We may add issuance using did:key in development if the host url does not start with `https`.
diff --git a/agent/.env.development b/agent/.env.development
index 5b8c777..1cc0fc8 100644
--- a/agent/.env.development
+++ b/agent/.env.development
@@ -1,5 +1,3 @@
AGENT_WALLET_KEY=secret-wallet-key
-DID_INDY_INDICIO_TESTNET_PUBLIC_DID_SEED=2543786a945a27258087ccfe95ff62df
-CHEQD_TESTNET_COSMOS_PAYER_SEED=robust across amount corn curve panther opera wish toe ring bleak empower wreck party abstract glad average muffin picnic jar squeeze annual long aunt
ED25519_SEED=5473a3e4c5ae3fd5fb3ad089563596e3
-P256_SEED=e5f18b10cd15cdb76818bc6ae8b71eb475e6eac76875ed085d3962239bbcf42f
\ No newline at end of file
+P256_SEED=e5f18b10cd15cdb76818bc6ae8b71eb475e6eac76875ed085d3962239bbcf42f
diff --git a/agent/package.json b/agent/package.json
index 3c83a47..9ab2169 100644
--- a/agent/package.json
+++ b/agent/package.json
@@ -1,15 +1,13 @@
{
"name": "agent",
"dependencies": {
- "@credo-ts/askar": "^0.5.1",
- "@credo-ts/cheqd": "^0.5.1",
- "@credo-ts/core": "^0.5.1",
- "@credo-ts/indy-vdr": "^0.5.1",
- "@credo-ts/node": "^0.5.1",
- "@credo-ts/openid4vc": "^0.5.1",
- "@hyperledger/aries-askar-nodejs": "^0.2.0",
- "@hyperledger/indy-vdr-nodejs": "^0.2.0",
+ "@credo-ts/askar": "^0.5.9",
+ "@credo-ts/core": "^0.5.9",
+ "@credo-ts/node": "^0.5.9",
+ "@credo-ts/openid4vc": "^0.5.9",
+ "@hyperledger/aries-askar-nodejs": "^0.2.3",
"cors": "^2.8.5",
+ "dotenv": "^16.4.5",
"express": "^4.18.2",
"zod": "^3.22.4"
},
@@ -17,7 +15,7 @@
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"tsx": "^4.7.0",
- "typescript": "^5.3.3"
+ "typescript": "~5.3.3"
},
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/agent/src/agent.ts b/agent/src/agent.ts
index 783cd68..e3ef394 100644
--- a/agent/src/agent.ts
+++ b/agent/src/agent.ts
@@ -1,111 +1,36 @@
-import {
- Agent,
- ConsoleLogger,
- DidsModule,
- JwkDidRegistrar,
- JwkDidResolver,
- KeyDidRegistrar,
- KeyDidResolver,
- LogLevel,
- WebDidResolver,
- joinUriParts,
-} from "@credo-ts/core";
-import { agentDependencies } from "@credo-ts/node";
-import { AskarModule } from "@credo-ts/askar";
-import {
- CheqdModule,
- CheqdDidRegistrar,
- CheqdDidResolver,
-} from "@credo-ts/cheqd";
-import {
- IndyVdrIndyDidRegistrar,
- IndyVdrIndyDidResolver,
- IndyVdrModule,
-} from "@credo-ts/indy-vdr";
-import { indyVdr } from "@hyperledger/indy-vdr-nodejs";
-import { ariesAskar } from "@hyperledger/aries-askar-nodejs";
-import {
- OpenId4VcHolderModule,
- OpenId4VcIssuerModule,
- OpenId4VcVerifierModule,
-} from "@credo-ts/openid4vc";
-import {
- AGENT_HOST,
- AGENT_WALLET_KEY,
- CHEQD_TESTNET_COSMOS_PAYER_SEED,
-} from "./constants";
-import { Router } from "express";
-import { credentialRequestToCredentialMapper } from "./issuer";
+import { AskarModule } from '@credo-ts/askar'
+import { Agent, ConsoleLogger, LogLevel, X509Module, joinUriParts } from '@credo-ts/core'
+import { agentDependencies } from '@credo-ts/node'
+import { OpenId4VcHolderModule, OpenId4VcIssuerModule, OpenId4VcVerifierModule } from '@credo-ts/openid4vc'
+import { ariesAskar } from '@hyperledger/aries-askar-nodejs'
+import { Router } from 'express'
+import { AGENT_HOST, AGENT_WALLET_KEY } from './constants'
+import { credentialRequestToCredentialMapper } from './issuer'
-process.on("unhandledRejection", (reason) => {
- console.log("Unhandled rejection", reason);
-});
+process.on('unhandledRejection', (reason) => {
+ console.error('Unhandled rejection', reason)
+})
-export const openId4VciRouter = Router();
-export const openId4VpRouter = Router();
+export const openId4VciRouter = Router()
+export const openId4VpRouter = Router()
export const agent = new Agent({
dependencies: agentDependencies,
config: {
- label: "OpenID4VC Playground",
+ label: 'OpenID4VC Playground',
logger: new ConsoleLogger(LogLevel.trace),
// TODO: add postgres storage
walletConfig: {
- id: "openid4vc-playground",
+ id: 'openid4vc-playground',
key: AGENT_WALLET_KEY,
},
},
modules: {
- cheqd: new CheqdModule({
- networks: [
- {
- network: "testnet",
- cosmosPayerSeed: CHEQD_TESTNET_COSMOS_PAYER_SEED,
- },
- ],
- }),
- indyVdr: new IndyVdrModule({
- indyVdr,
- networks: [
- {
- genesisTransactions: `{"reqSignature":{},"txn":{"data":{"data":{"alias":"OpsNode","blskey":"4i39oJqm7fVX33gnYEbFdGurMtwYQJgDEYfXdYykpbJMWogByocaXxKbuXdrg3k9LP33Tamq64gUwnm4oA7FkxqJ5h4WfKH6qyVLvmBu5HgeV8Rm1GJ33mKX6LWPbm1XE9TfzpQXJegKyxHQN9ABquyBVAsfC6NSM4J5t1QGraJBfZi","blskey_pop":"Qq3CzhSfugsCJotxSCRAnPjmNDJidDz7Ra8e4xvLTEzQ5w3ppGray9KynbGPH8T7XnUTU1ioZadTbjXaRY26xd4hQ3DxAyR4GqBymBn3UBomLRJHmj7ukcdJf9WE6tu1Fp1EhxmyaMqHv13KkDrDfCthgd2JjAWvSgMGWwAAzXEow5","client_ip":"13.58.197.208","client_port":"9702","node_ip":"3.135.134.42","node_port":"9701","services":["VALIDATOR"]},"dest":"EVwxHoKXUy2rnRzVdVKnJGWFviamxMwLvUso7KMjjQNH"},"metadata":{"from":"Pms5AZzgPWHSj6nNmJDfmo"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"77ad6682f320be9969f70a37d712344afed8e3fba8d43fa5602c81b578d26088"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"cynjanode","blskey":"32DLSweyJRxVMcVKGjUeNkVF1fwyFfRcFqGU9x7qL2ox2STpF6VxZkbxoLkGMPnt3gywRaY6jAjqgC8XMkf3webMJ4SEViPtBKZJjCCFTf4tGXfEsMwinummaPja85GgTALf7DddCNyCojmkXWHpgjrLx3626Z2MiNxVbaMapG2taFX","blskey_pop":"RQRU8GVYSYZeu9dfH6myhzZ2qfxeVpCL3bTzgto1bRbx3QCt3mFFQQBVbgrqui2JpXhcWXxoDzp1WyYbSZwYqYQbRmvK7PPG82VAvVagv1n83Qa3cdyGwCevZdEzxuETiiXBRWSPfb4JibAXPKkLZHyQHWCEHcAEVeXtx7FRS1wjTd","client_ip":"3.17.103.221","client_port":"9702","node_ip":"3.17.215.226","node_port":"9701","services":["VALIDATOR"]},"dest":"iTq944JTtwHnst7rucfsRA4m26x9i6zCKKohETBCiWu"},"metadata":{"from":"QC174PGaL4zA9YHYqofPH2"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"ce7361e44ec10a275899ece1574f6e38f2f3c7530c179fa07a2924e55775759b"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"GlobaliD","blskey":"4Behdr1KJfLTAPNospghtL7iWdCHca6MZDxAtzYNXq35QCUr4aqpLu6p4Sgu9wNbTACB3DbwmVgE2L7hX6UsasuvZautqUpf4nC5viFpH7X6mHyqLreBJTBH52tSwifQhRjuFAySbbfyRK3wb6R2Emxun9GY7MFNuy792LXYg4C6sRJ","blskey_pop":"RKYDRy8oTxKnyAV3HocapavH2jkw3PVe54JcEekxXz813DFbEy87N3i3BNqwHB7MH93qhtTRb7EZMaEiYhm92uaLKyubUMo5Rqjve2jbEdYEYVRmgNJWpxFKCmUBa5JwBWYuGunLMZZUTU3qjbdDXkJ9UNMQxDULCPU5gzLTy1B5kb","client_ip":"13.56.175.126","client_port":"9702","node_ip":"50.18.84.131","node_port":"9701","services":["VALIDATOR"]},"dest":"2ErWxamsNGBfhkFnwYgs4UW4aApct1kHUvu7jbkA1xX4"},"metadata":{"from":"4H8us7B1paLW9teANv8nam"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"0c3b33b77e0419d6883be35d14b389c3936712c38a469ac5320a3cae68be1293"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"IdRamp","blskey":"LoYzqUMPDZEfRshwGSzkgATxcM5FAS1LYx896zHnMfXP7duDsCQ6CBG2akBkZzgH3tBMvnjhs2z7PFc2gFeaKUF9fKDHhtbVqPofxH3ebcRfA959qU9mgvmkUwMUgwd21puRU6BebUwBiYxMxcE5ChReBnAkdAv19gVorm3prBMk94","blskey_pop":"R1DjpsG7UxgwstuF7WDUL17a9Qq64vCozwJZ88bTrSDPwC1cdRn3WmhqJw5LpEhFQJosDSVVT6tS8dAZrrssRv2YsELbfGEJ7ZGjhNjZHwhqg4qeustZ7PZZE3Vr1ALSHY4Aa6KpNzGodxu1XymYZWXAFokPAs3Kho8mKcJwLCHn3h","client_ip":"207.126.128.12","client_port":"9702","node_ip":"207.126.129.12","node_port":"9701","services":["VALIDATOR"]},"dest":"5Zj5Aec6Kt9ki1runrXu87wZ522mnm3zwmaoHLUcHLx9"},"metadata":{"from":"AFLDFPoJuDQUHqnfmg8U7i"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"c9df105558333ac8016610d9da5aad1e9a5dd50b9d9cc5684e94f439fa10f836"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"idlab-node01","blskey":"2fjJVi33U1tCTjW77cJaf1NLz7EzWkVNzR9BEQpVVK64MJpRKNUzt6k7Td2U8yqU5hGyAFH5N7ZymSB55TnpC3rJYLVTcGXZeXpmrQx3mwnXNyfTDnxfTpdQ1KMoFeZoDPZ8acfaH8GWeW2jL1qREE52tetBf4tXTeshmWzGkEN7r4y","blskey_pop":"RSjiM6dYUmN2rv2ca7dUCmEKrivq12rhxhXUKHdmSwUxbCmcijsgoERjYG7MqxhKLjSAJ5715K23fVEc6uK1kTenKmYCcCts8MLMAQG8Upb22nfgHJ3py8RwRoACeAjFF3myAMNRJJPhUdv96drJdwkGRv7f6JjvoB5KWVQYTNgheP","client_ip":"205.159.92.17","client_port":"9702","node_ip":"205.159.92.16","node_port":"9701","services":["VALIDATOR"]},"dest":"8czYgwmLDazVrBHuo53Tyx7Tw8ZhvnoC2BfhQGir4r8F"},"metadata":{"from":"PN8wFxLKjdkwyxoEEXwyz2"},"type":"0"},"txnMetadata":{"seqNo":5,"txnId":"9237eca7d2a203f6e1779f63064d2f22cf28e1bcd4e6fe5d791b15e82969acdc"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"lorica-identity-node1","blskey":"wUh24sVCQ8PHDgSb343g2eLxjD5vwxsrETfuV2sbwMNnYon9nhbaK5jcWTekvXtyiwxHxuiCCoZwKS97MQEAeC2oLbbMeKjYm212QwSnm7aKLEqTStXht35VqZvZLT7Q3mPQRYLjMGixdn4ocNHrBTMwPUQYycEqwaHWgE1ncDueXY","blskey_pop":"R2sMwF7UW6AaD4ALa1uB1YVPuP6JsdJ7LsUoViM9oySFqFt34C1x1tdHDysS9wwruzaaEFui6xNPqJ8eu3UBqcFKkoWhdsMqCALwe63ytxPwvtLtCffJLhHAcgrPC7DorXYdqhdG2cevdqc5oqFEAaKoFDBf12p5SsbbM4PYWCmVCb","client_ip":"35.225.220.151","client_port":"9702","node_ip":"35.224.26.110","node_port":"9701","services":["VALIDATOR"]},"dest":"k74ZsZuUaJEcB8RRxMwkCwdE5g1r9yzA3nx41qvYqYf"},"metadata":{"from":"Ex6hzsJFYzNJ7kzbfncNeU"},"type":"0"},"txnMetadata":{"seqNo":6,"txnId":"6880673ce4ae4a2352f103d2a6ae20469dd070f2027283a1da5e62a64a59d688"},"ver":"1"}
-{"reqSignature":{},"txn":{"data":{"data":{"alias":"cysecure-itn","blskey":"GdCvMLkkBYevRFi93b6qaj9G2u1W6Vnbg8QhRD1chhrWR8vRE8x9x7KXVeUBPFf6yW5qq2JCfA2frc8SGni2RwjtTagezfwAwnorLhVJqS5ZxTi4pgcw6smebnt4zWVhTkh6ugDHEypHwNQBcw5WhBZcEJKgNbyVLnHok9ob6cfr3u","blskey_pop":"RbH9mY7M5p3UB3oj4sT1skYwMkxjoUnja8eTYfcm83VcNbxC9zR9pCiRhk4q1dJT3wkDBPGNKnk2p83vaJYLcgMuJtzoWoJAWAxjb3Mcq8Agf6cgQpBuzBq2uCzFPuQCAhDS4Kv9iwA6FsRnfvoeFTs1hhgSJVxQzDWMVTVAD9uCqu","client_ip":"35.169.19.171","client_port":"9702","node_ip":"54.225.56.21","node_port":"9701","services":["VALIDATOR"]},"dest":"4ETBDmHzx8iDQB6Xygmo9nNXtMgq9f6hxGArNhQ6Hh3u"},"metadata":{"from":"uSXXXEdBicPHMMhr3ddNF"},"type":"0"},"txnMetadata":{"seqNo":7,"txnId":"3c21718b07806b2f193b35953dda5b68b288efd551dce4467ce890703d5ba549"},"ver":"1"}`,
- indyNamespace: "indicio:testnet",
- isProduction: false,
- // FIXME: indy not fully working yet
- connectOnStartup: false,
- transactionAuthorAgreement: {
- acceptanceMechanism: "for_session",
- version: "1.0",
- },
- },
- ],
- }),
- dids: new DidsModule({
- resolvers: [
- new KeyDidResolver(),
- new JwkDidResolver(),
- new IndyVdrIndyDidResolver(),
- new WebDidResolver(),
- new CheqdDidResolver(),
- ],
- registrars: [
- new KeyDidRegistrar(),
- new JwkDidRegistrar(),
- new IndyVdrIndyDidRegistrar(),
- new CheqdDidRegistrar(),
- ],
- }),
askar: new AskarModule({
ariesAskar,
}),
openId4VcIssuer: new OpenId4VcIssuerModule({
- baseUrl: joinUriParts(AGENT_HOST, ["oid4vci"]),
+ baseUrl: joinUriParts(AGENT_HOST, ['oid4vci']),
router: openId4VciRouter,
endpoints: {
credential: {
@@ -115,8 +40,9 @@ export const agent = new Agent({
}),
openId4VcHolder: new OpenId4VcHolderModule(),
openId4VcVerifier: new OpenId4VcVerifierModule({
- baseUrl: joinUriParts(AGENT_HOST, ["siop"]),
+ baseUrl: joinUriParts(AGENT_HOST, ['siop']),
router: openId4VpRouter,
}),
+ x509: new X509Module(),
},
-});
+})
diff --git a/agent/src/constants.ts b/agent/src/constants.ts
index b80ad39..73868d8 100644
--- a/agent/src/constants.ts
+++ b/agent/src/constants.ts
@@ -1,31 +1,10 @@
-if (
- !process.env.ED25519_SEED ||
- !process.env.P256_SEED ||
- !process.env.AGENT_HOST ||
- !process.env.AGENT_WALLET_KEY
-) {
- throw new Error(
- "ED25519_SEED, P256_SEED, AGENT_HOST or AGENT_WALLET_KEY env variable not set"
- );
+if (!process.env.P256_SEED || !process.env.AGENT_HOST || !process.env.AGENT_WALLET_KEY) {
+ throw new Error('P256_SEED, AGENT_HOST or AGENT_WALLET_KEY env variable not set')
}
-const AGENT_HOST = process.env.AGENT_HOST;
-const AGENT_WALLET_KEY = process.env.AGENT_WALLET_KEY;
+const AGENT_HOST = process.env.AGENT_HOST
+const AGENT_WALLET_KEY = process.env.AGENT_WALLET_KEY
-const DID_INDY_INDICIO_TESTNET_PUBLIC_DID_SEED =
- process.env.DID_INDY_INDICIO_TESTNET_PUBLIC_DID_SEED;
+const P256_SEED = process.env.P256_SEED
-const CHEQD_TESTNET_COSMOS_PAYER_SEED =
- process.env.CHEQD_TESTNET_COSMOS_PAYER_SEED;
-
-const ED25519_SEED = process.env.ED25519_SEED;
-const P256_SEED = process.env.P256_SEED;
-
-export {
- AGENT_HOST,
- AGENT_WALLET_KEY,
- DID_INDY_INDICIO_TESTNET_PUBLIC_DID_SEED,
- CHEQD_TESTNET_COSMOS_PAYER_SEED,
- ED25519_SEED,
- P256_SEED,
-};
+export { AGENT_HOST, AGENT_WALLET_KEY, P256_SEED }
diff --git a/agent/src/did/cheqd.ts b/agent/src/did/cheqd.ts
deleted file mode 100644
index c01ebcd..0000000
--- a/agent/src/did/cheqd.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { agent } from "../agent";
-import { CheqdDidCreateOptions } from "@credo-ts/cheqd";
-import {
- DidDocumentBuilder,
- utils,
- KeyType,
- getEd25519VerificationKey2018,
-} from "@credo-ts/core";
-
-export async function createDidCheqd() {
- // NOTE: we need to pass custom document for cheqd if we want to add it to `assertionMethod`
-
- const did = `did:cheqd:testnet:${utils.uuid()}`;
- const key = await agent.wallet.createKey({
- keyType: KeyType.Ed25519,
- });
-
- const ed25519VerificationMethod = getEd25519VerificationKey2018({
- key,
- id: `${did}#key-1`,
- controller: did,
- });
-
- const didDocument = new DidDocumentBuilder(did)
- .addContext("https://w3id.org/security/suites/ed25519-2018/v1")
- .addVerificationMethod(ed25519VerificationMethod)
- .addAssertionMethod(ed25519VerificationMethod.id)
- .addAuthentication(ed25519VerificationMethod.id)
- .build();
-
- const didResult = await agent.dids.create({
- method: "cheqd",
- didDocument,
- options: {
- network: "testnet",
- },
- secret: {},
- });
-
- if (didResult.didState.state === "failed") {
- throw new Error("cheqd DID creation failed. " + didResult.didState.reason);
- }
-
- return [did];
-}
diff --git a/agent/src/did/createKeys.ts b/agent/src/did/createKeys.ts
deleted file mode 100644
index f6ae599..0000000
--- a/agent/src/did/createKeys.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { KeyType, TypedArrayEncoder } from "@credo-ts/core";
-import { agent } from "../agent";
-import { ED25519_SEED, P256_SEED } from "../constants";
-
-export async function createKeys() {
- const ed25519Key = await agent.wallet.createKey({
- keyType: KeyType.Ed25519,
- seed: TypedArrayEncoder.fromString(ED25519_SEED),
- });
-
- const p256Key = await agent.wallet.createKey({
- keyType: KeyType.P256,
- seed: TypedArrayEncoder.fromString(P256_SEED),
- });
-
- return [ed25519Key, p256Key];
-}
diff --git a/agent/src/did/index.ts b/agent/src/did/index.ts
deleted file mode 100644
index ee1c8f2..0000000
--- a/agent/src/did/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export * from "./util";
-export * from "./web";
-export * from "./jwk";
-export * from "./key";
-export * from "./cheqd";
-export * from "./indy";
-export * from "./setup";
diff --git a/agent/src/did/indy.ts b/agent/src/did/indy.ts
deleted file mode 100644
index 4765846..0000000
--- a/agent/src/did/indy.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { KeyType, TypedArrayEncoder } from "@credo-ts/core";
-import { indyDidFromPublicKeyBase58 } from "@credo-ts/core/build/utils";
-import { agent } from "../agent";
-
-export async function importIndyDid(
- namespaceIdentifier: string,
- privateKey: string
-) {
- const key = await agent.wallet.createKey({
- keyType: KeyType.Ed25519,
- privateKey: TypedArrayEncoder.fromString(privateKey),
- });
-
- const indyDid = `did:indy:${namespaceIdentifier}:${indyDidFromPublicKeyBase58(
- key.publicKeyBase58
- )}`;
-
- console.log({
- indyDid,
- publicKeyBase58: key.publicKeyBase58,
- });
- await agent.dids.import({
- did: indyDid,
- overwrite: true,
- });
-}
diff --git a/agent/src/did/jwk.ts b/agent/src/did/jwk.ts
deleted file mode 100644
index 7813846..0000000
--- a/agent/src/did/jwk.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { DidJwk, Key, getJwkFromKey } from "@credo-ts/core";
-import { agent } from "../agent";
-
-export async function createDidJwk(keys: Key[]) {
- const createdDids: string[] = [];
- for (const key of keys) {
- const didJwk = DidJwk.fromJwk(getJwkFromKey(key));
- await agent.dids.import({
- overwrite: true,
- did: didJwk.did,
- });
- createdDids.push(didJwk.did);
- }
-
- return createdDids;
-}
diff --git a/agent/src/did/key.ts b/agent/src/did/key.ts
deleted file mode 100644
index 6dbdfc2..0000000
--- a/agent/src/did/key.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Key, DidKey } from "@credo-ts/core";
-import { agent } from "../agent";
-
-export async function createDidKey(keys: Key[]) {
- const createdDids: string[] = [];
-
- for (const key of keys) {
- const didKey = new DidKey(key);
- await agent.dids.import({
- overwrite: true,
- did: didKey.did,
- });
- createdDids.push(didKey.did);
- }
-
- return createdDids;
-}
diff --git a/agent/src/did/setup.ts b/agent/src/did/setup.ts
deleted file mode 100644
index 73fbb6c..0000000
--- a/agent/src/did/setup.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { WalletKeyExistsError } from "@credo-ts/core";
-import { createDidCheqd } from "./cheqd";
-import { createKeys } from "./createKeys";
-import { createDidJwk } from "./jwk";
-import { createDidKey } from "./key";
-import { createDidWeb } from "./web";
-import { agent } from "../agent";
-
-const availableDids: string[] = [];
-
-export async function setupAllDids() {
- try {
- const keys = await createKeys();
-
- availableDids.push(...(await createDidKey(keys)));
- availableDids.push(...(await createDidJwk(keys)));
- availableDids.push(...(await createDidWeb(keys)));
- availableDids.push(...(await createDidCheqd()));
-
- await agent.genericRecords.save({
- id: "AVAILABLE_DIDS",
- content: {
- availableDids,
- },
- });
- } catch (error) {
- // If the key already exists, we assume the dids are already created
- if (error instanceof WalletKeyExistsError) {
- const availableDidsRecord = await agent.genericRecords.findById(
- "AVAILABLE_DIDS"
- );
- if (!availableDidsRecord) {
- throw new Error("No available dids record found");
- }
- availableDids.push(
- ...(availableDidsRecord.content.availableDids as string[])
- );
-
- return;
- }
-
- throw error;
- }
-}
-
-export function getAvailableDids() {
- return availableDids;
-}
diff --git a/agent/src/did/util.ts b/agent/src/did/util.ts
deleted file mode 100644
index 1d7638d..0000000
--- a/agent/src/did/util.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { agent } from "../agent";
-
-export async function hasDidForMethod(method: string) {
- const [createdDid] = await agent.dids.getCreatedDids({ method });
-
- return createdDid !== undefined;
-}
-
-export async function getDidForMethod(method: string) {
- const [createdDid] = await agent.dids.getCreatedDids({ method });
-
- if (!createdDid) {
- throw new Error(`did for method ${method} does not exist`);
- }
-
- return createdDid.did;
-}
diff --git a/agent/src/did/web.ts b/agent/src/did/web.ts
deleted file mode 100644
index 959c692..0000000
--- a/agent/src/did/web.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import {
- DidDocumentBuilder,
- Key,
- getKeyDidMappingByKeyType,
-} from "@credo-ts/core";
-import { agent } from "../agent";
-import { AGENT_HOST } from "../constants";
-
-const cleanHost = encodeURIComponent(
- AGENT_HOST.replace("https://", "").replace("http://", "")
-);
-
-const didWeb = `did:web:${cleanHost}`;
-
-export async function createDidWeb(keys: Key[]) {
- const verificationMethods = keys.flatMap((key) =>
- getKeyDidMappingByKeyType(key.keyType).getVerificationMethods(didWeb, key)
- );
-
- const didDocumentBuilder = new DidDocumentBuilder(didWeb);
-
- for (const verificationMethod of verificationMethods) {
- didDocumentBuilder
- .addVerificationMethod(verificationMethod)
- .addAssertionMethod(verificationMethod.id)
- .addAuthentication(verificationMethod.id);
- }
-
- const didDocument = didDocumentBuilder.build();
-
- await agent.dids.import({
- did: didWeb,
- didDocument,
- });
-
- return [didWeb];
-}
-
-export async function getWebDidDocument() {
- const [createdDid] = await agent.dids.getCreatedDids({ did: didWeb });
-
- if (!createdDid || !createdDid.didDocument) {
- throw new Error(`did does not exist`);
- }
-
- return createdDid.didDocument;
-}
diff --git a/agent/src/endpoints.ts b/agent/src/endpoints.ts
index c8321be..b581f64 100644
--- a/agent/src/endpoints.ts
+++ b/agent/src/endpoints.ts
@@ -1,348 +1,230 @@
-import { agent } from "./agent";
-import express, { NextFunction, Request, Response } from "express";
-import z from "zod";
-import { credentialSupportedIds } from "./issuerMetadata";
-import { getIssuer } from "./issuer";
import {
DifPresentationExchangeService,
JsonTransformer,
- KeyDidCreateOptions,
- KeyType,
RecordNotFoundError,
W3cJsonLdVerifiableCredential,
W3cJsonLdVerifiablePresentation,
W3cJwtVerifiableCredential,
W3cJwtVerifiablePresentation,
getJwkFromKey,
- getKeyFromVerificationMethod,
- parseDid,
-} from "@credo-ts/core";
-import { getAvailableDids, getWebDidDocument } from "./did";
-import { getVerifier } from "./verifier";
-import { OpenId4VcIssuanceSessionRepository } from "@credo-ts/openid4vc/build/openid4vc-issuer/repository";
-import { OfferSessionMetadata } from "./session";
-import { OpenId4VcVerificationSessionState } from "@credo-ts/openid4vc";
+} from '@credo-ts/core'
+import { OpenId4VcVerificationSessionState } from '@credo-ts/openid4vc'
+import { OpenId4VcIssuanceSessionRepository } from '@credo-ts/openid4vc/build/openid4vc-issuer/repository'
+import express, { type NextFunction, type Request, type Response } from 'express'
+import z from 'zod'
+import { agent } from './agent'
+import { AGENT_HOST } from './constants'
+import { getIssuer } from './issuer'
+import { credentialSupportedIds } from './issuerMetadata'
+import { getX509Certificate } from './keyMethods'
+import { getVerifier } from './verifier'
const zCreateOfferRequest = z.object({
// FIXME: rename offeredCredentials to credentialSupportedIds in AFJ
credentialSupportedIds: z.array(z.enum(credentialSupportedIds)),
- issuerDidMethod: z.string(),
-});
-
-export const apiRouter = express.Router();
-apiRouter.use(express.json());
-apiRouter.use(express.text());
-apiRouter.post(
- "/offers/create",
- async (request: Request, response: Response) => {
- const issuer = await getIssuer();
- // FIXME: somehow JSON doesn't work
- const createOfferRequest = zCreateOfferRequest.parse(
- typeof request.body === "string" ? JSON.parse(request.body) : request.body
- );
-
- const offer = await agent.modules.openId4VcIssuer.createCredentialOffer({
- issuerId: issuer.issuerId,
- offeredCredentials: createOfferRequest.credentialSupportedIds,
- preAuthorizedCodeFlowConfig: {
- userPinRequired: false,
- },
- });
-
- // FIXME: in 0.5.1 we can pass the issuanceMetadata to the createCredentialOffer method
- // directly
- const issuanceSessionRepository = agent.dependencyManager.resolve(
- OpenId4VcIssuanceSessionRepository
- );
- offer.issuanceSession.issuanceMetadata = {
- issuerDidMethod: createOfferRequest.issuerDidMethod,
- } satisfies OfferSessionMetadata;
- await issuanceSessionRepository.update(
- agent.context,
- offer.issuanceSession
- );
-
- return response.json(offer);
- }
-);
-
-apiRouter.get("/issuer", async (_, response: Response) => {
- const issuer = await getIssuer();
- const availableDids = getAvailableDids();
+ issuerId: z.string(),
+})
+
+export const apiRouter = express.Router()
+apiRouter.use(express.json())
+apiRouter.use(express.text())
+apiRouter.post('/offers/create', async (request: Request, response: Response) => {
+ const issuer = await getIssuer()
+ // FIXME: somehow JSON doesn't work
+ const createOfferRequest = zCreateOfferRequest.parse(
+ typeof request.body === 'string' ? JSON.parse(request.body) : request.body
+ )
+
+ const offer = await agent.modules.openId4VcIssuer.createCredentialOffer({
+ issuerId: issuer.issuerId,
+ offeredCredentials: createOfferRequest.credentialSupportedIds,
+ preAuthorizedCodeFlowConfig: {
+ userPinRequired: false,
+ },
+ })
+
+ return response.json(offer)
+})
+
+apiRouter.get('/issuer', async (_, response: Response) => {
+ const issuer = await getIssuer()
return response.json({
- credentialsSupported: issuer.credentialsSupported,
+ credentialsSupported: issuer.credentialsSupported.map((c) => ({
+ display: (c as { vct: string }).vct,
+ id: c.id,
+ })),
display: issuer.display,
- availableDidMethods: Array.from(
- new Set(availableDids.map((did) => `did:${parseDid(did).method}`))
- ),
- });
-});
+ availableX509Certificates: [AGENT_HOST],
+ })
+})
const zReceiveOfferRequest = z.object({
credentialOfferUri: z.string().url(),
-});
-
-apiRouter.post(
- "/offers/receive",
- async (request: Request, response: Response) => {
- const receiveOfferRequest = zReceiveOfferRequest.parse(
- typeof request.body === "string" ? JSON.parse(request.body) : request.body
- );
-
- const resolvedOffer =
- await agent.modules.openId4VcHolder.resolveCredentialOffer(
- receiveOfferRequest.credentialOfferUri
- );
- const credentials =
- await agent.modules.openId4VcHolder.acceptCredentialOfferUsingPreAuthorizedCode(
- resolvedOffer,
- {
- verifyCredentialStatus: false,
- credentialBindingResolver: async ({
- keyType,
- supportsJwk,
- supportedDidMethods,
- }) => {
- if (supportedDidMethods?.includes("did:key")) {
- const didKeyResult = await agent.dids.create(
- {
- method: "key",
- options: {
- keyType,
- },
- }
- );
-
- if (didKeyResult.didState.state !== "finished") {
- throw new Error("did creation failed");
- }
- const firstVerificationMethod =
- didKeyResult.didState.didDocument.verificationMethod?.[0];
- if (!firstVerificationMethod) {
- throw new Error("did document has no verification method");
- }
-
- return {
- method: "did",
- didUrl: firstVerificationMethod.id,
- };
- }
-
- if (supportsJwk) {
- const key = await agent.wallet.createKey({
- keyType,
- });
+})
+
+apiRouter.post('/offers/receive', async (request: Request, response: Response) => {
+ const receiveOfferRequest = zReceiveOfferRequest.parse(
+ typeof request.body === 'string' ? JSON.parse(request.body) : request.body
+ )
+
+ const resolvedOffer = await agent.modules.openId4VcHolder.resolveCredentialOffer(
+ receiveOfferRequest.credentialOfferUri
+ )
+ const token = await agent.modules.openId4VcHolder.requestToken({
+ resolvedCredentialOffer: resolvedOffer,
+ })
+ const credentials = await agent.modules.openId4VcHolder.requestCredentials({
+ resolvedCredentialOffer: resolvedOffer,
+ accessToken: token.accessToken,
+ cNonce: token.cNonce,
+ credentialBindingResolver: async ({ keyType, supportsJwk }) => {
+ if (supportsJwk) {
+ const key = await agent.wallet.createKey({
+ keyType,
+ })
- return {
- method: "jwk",
- jwk: getJwkFromKey(key),
- };
- }
-
- throw new Error(
- "only did:key and jwk are supported for holder binding"
- );
- },
- }
- );
-
- return response.json({
- credentials: credentials.map((credential) => {
- if (credential instanceof W3cJsonLdVerifiableCredential) {
- return {
- pretty: credential.toJson(),
- encoded: credential.toJson(),
- };
+ return {
+ method: 'jwk',
+ jwk: getJwkFromKey(key),
}
+ }
- if (credential instanceof W3cJwtVerifiableCredential) {
- return {
- pretty: JsonTransformer.toJSON(credential.credential),
- encoded: credential.serializedJwt,
- };
- }
+ throw new Error('only jwk is supported for holder binding')
+ },
+ })
- return {
- pretty: {
- ...credential,
- compact: undefined,
- },
- encoded: credential.compact,
- };
- }),
- });
- }
-);
+ return response.json({
+ credentials: credentials.map((credential) => JSON.stringify(credential.credential.payload)),
+ })
+})
const zCreatePresentationRequestBody = z.object({
presentationDefinition: z.record(z.string(), z.any()),
-});
-
-apiRouter.post(
- "/requests/create",
- async (request: Request, response: Response) => {
- const verifier = await getVerifier();
-
- // FIXME: somehow JSON doesn't work
- const createPresentationRequestBody = zCreatePresentationRequestBody.parse(
- typeof request.body === "string" ? JSON.parse(request.body) : request.body
- );
-
- // DIIPv1 uses ES256/P256 keys so we use that to create the request
- const webDid = await getWebDidDocument();
- const verificationMethods = webDid.verificationMethod ?? [];
- const keys = verificationMethods.map((v) =>
- getKeyFromVerificationMethod(v)
- );
- const verificationMethodIndex = keys.findIndex(
- (k) => k.keyType === KeyType.P256
- );
-
- if (verificationMethodIndex === -1) {
- return response.status(500).json({
- error: "No P-256 verification method found",
- });
- }
+})
- const { authorizationRequest, verificationSession } =
- await agent.modules.openId4VcVerifier.createAuthorizationRequest({
- verifierId: verifier.verifierId,
- requestSigner: {
- didUrl: verificationMethods[verificationMethodIndex].id,
- method: "did",
- },
- presentationExchange: {
- definition:
- createPresentationRequestBody.presentationDefinition as any,
- },
- });
+apiRouter.post('/requests/create', async (request: Request, response: Response) => {
+ const verifier = await getVerifier()
- return response.json({
- authorizationRequestUri: authorizationRequest,
- verificationSessionId: verificationSession.id,
- });
- }
-);
+ // FIXME: somehow JSON doesn't work
+ const createPresentationRequestBody = zCreatePresentationRequestBody.parse(
+ typeof request.body === 'string' ? JSON.parse(request.body) : request.body
+ )
+
+ const x509Certificate = getX509Certificate()
+
+ const { authorizationRequest, verificationSession } =
+ await agent.modules.openId4VcVerifier.createAuthorizationRequest({
+ verifierId: verifier.verifierId,
+ requestSigner: {
+ method: 'x5c',
+ x5c: [x509Certificate],
+ issuer: AGENT_HOST,
+ },
+ presentationExchange: {
+ definition: createPresentationRequestBody.presentationDefinition as any,
+ },
+ })
+
+ return response.json({
+ authorizationRequestUri: authorizationRequest,
+ verificationSessionId: verificationSession.id,
+ })
+})
const zReceivePresentationRequestBody = z.object({
authorizationRequestUri: z.string().url(),
-});
+})
-apiRouter.get("/requests/:verificationSessionId", async (request, response) => {
- const verificationSessionId = request.params.verificationSessionId;
+apiRouter.get('/requests/:verificationSessionId', async (request, response) => {
+ const verificationSessionId = request.params.verificationSessionId
try {
- const verificationSession =
- await agent.modules.openId4VcVerifier.getVerificationSessionById(
- verificationSessionId
- );
-
- if (
- verificationSession.state ===
- OpenId4VcVerificationSessionState.ResponseVerified
- ) {
- const verified =
- await agent.modules.openId4VcVerifier.getVerifiedAuthorizationResponse(
- verificationSessionId
- );
+ const verificationSession = await agent.modules.openId4VcVerifier.getVerificationSessionById(verificationSessionId)
+
+ if (verificationSession.state === OpenId4VcVerificationSessionState.ResponseVerified) {
+ const verified = await agent.modules.openId4VcVerifier.getVerifiedAuthorizationResponse(verificationSessionId)
return response.json({
verificationSessionId: verificationSession.id,
responseStatus: verificationSession.state,
error: verificationSession.errorMessage,
- presentations: verified.presentationExchange?.presentations.map(
- (presentation) => {
- if (presentation instanceof W3cJsonLdVerifiablePresentation) {
- return {
- pretty: presentation.toJson(),
- encoded: presentation.toJson(),
- };
+ presentations: verified.presentationExchange?.presentations.map((presentation) => {
+ if (presentation instanceof W3cJsonLdVerifiablePresentation) {
+ return {
+ pretty: presentation.toJson(),
+ encoded: presentation.toJson(),
}
+ }
- if (presentation instanceof W3cJwtVerifiablePresentation) {
- return {
- pretty: JsonTransformer.toJSON(presentation.presentation),
- encoded: presentation.serializedJwt,
- };
+ if (presentation instanceof W3cJwtVerifiablePresentation) {
+ return {
+ pretty: JsonTransformer.toJSON(presentation.presentation),
+ encoded: presentation.serializedJwt,
}
+ }
- return {
- pretty: {
- ...presentation,
- compact: undefined,
- },
- encoded: presentation.compact,
- };
+ return {
+ pretty: {
+ ...presentation,
+ compact: undefined,
+ },
+ encoded: presentation.compact,
}
- ),
+ }),
submission: verified.presentationExchange?.submission,
definition: verified.presentationExchange?.definition,
- });
+ })
}
return response.json({
verificationSessionId: verificationSession.id,
responseStatus: verificationSession.state,
error: verificationSession.errorMessage,
- });
+ })
} catch (error) {
if (error instanceof RecordNotFoundError) {
- return response.status(404).send("Verification session not found");
+ return response.status(404).send('Verification session not found')
}
}
-});
-
-apiRouter.post(
- "/requests/receive",
- async (request: Request, response: Response) => {
- const receivePresentationRequestBody =
- zReceivePresentationRequestBody.parse(
- typeof request.body === "string"
- ? JSON.parse(request.body)
- : request.body
- );
-
- const resolved =
- await agent.modules.openId4VcHolder.resolveSiopAuthorizationRequest(
- receivePresentationRequestBody.authorizationRequestUri
- );
-
- if (!resolved.presentationExchange) {
- return response.status(500).json({
- error:
- "Expected presentation_definition to be included in authorization request",
- });
- }
+})
- // FIXME: expose PresentationExchange API (or allow auto-select in another way)
- const presentationExchangeService = agent.dependencyManager.resolve(
- DifPresentationExchangeService
- );
-
- const selectedCredentials =
- presentationExchangeService.selectCredentialsForRequest(
- resolved.presentationExchange?.credentialsForRequest
- );
-
- const { submittedResponse, serverResponse } =
- await agent.modules.openId4VcHolder.acceptSiopAuthorizationRequest({
- authorizationRequest: resolved.authorizationRequest,
- presentationExchange: {
- credentials: selectedCredentials,
- },
- });
-
- return response.status(serverResponse.status).json(submittedResponse);
- }
-);
+apiRouter.post('/requests/receive', async (request: Request, response: Response) => {
+ const receivePresentationRequestBody = zReceivePresentationRequestBody.parse(
+ typeof request.body === 'string' ? JSON.parse(request.body) : request.body
+ )
-apiRouter.use(
- (error: Error, request: Request, response: Response, next: NextFunction) => {
- console.error("Unhandled error", error);
+ const resolved = await agent.modules.openId4VcHolder.resolveSiopAuthorizationRequest(
+ receivePresentationRequestBody.authorizationRequestUri
+ )
+
+ if (!resolved.presentationExchange) {
return response.status(500).json({
- error: error.message,
- });
+ error: 'Expected presentation_definition to be included in authorization request',
+ })
}
-);
+
+ // FIXME: expose PresentationExchange API (or allow auto-select in another way)
+ const presentationExchangeService = agent.dependencyManager.resolve(DifPresentationExchangeService)
+
+ const selectedCredentials = presentationExchangeService.selectCredentialsForRequest(
+ resolved.presentationExchange?.credentialsForRequest
+ )
+
+ const { submittedResponse, serverResponse } = await agent.modules.openId4VcHolder.acceptSiopAuthorizationRequest({
+ authorizationRequest: resolved.authorizationRequest,
+ presentationExchange: {
+ credentials: selectedCredentials,
+ },
+ })
+
+ return response.status(serverResponse.status).json(submittedResponse)
+})
+
+apiRouter.use((error: Error, request: Request, response: Response, next: NextFunction) => {
+ console.error('Unhandled error', error)
+ return response.status(500).json({
+ error: error.message,
+ })
+})
diff --git a/agent/src/issuer.ts b/agent/src/issuer.ts
index 441800c..b69c73e 100644
--- a/agent/src/issuer.ts
+++ b/agent/src/issuer.ts
@@ -1,44 +1,31 @@
-import { OpenId4VciCredentialRequestToCredentialMapper } from "@credo-ts/openid4vc";
-import {
- W3cCredential,
- parseDid,
- KeyType,
- getKeyFromVerificationMethod,
-} from "@credo-ts/core";
-import { agent } from "./agent";
-import {
- animoOpenId4VcPlaygroundCredentialJwtVc,
- animoOpenId4VcPlaygroundCredentialLdpVc,
- animoOpenId4VcPlaygroundCredentialSdJwtVcDid,
- animoOpenId4VcPlaygroundCredentialSdJwtVcJwk,
- credentialsSupported,
- issuerDisplay,
-} from "./issuerMetadata";
-import { OfferSessionMetadata } from "./session";
-import { getAvailableDids } from "./did";
-import { OpenId4VcIssuanceSessionRepository } from "@credo-ts/openid4vc/build/openid4vc-issuer/repository";
+import type { KeyType } from '@credo-ts/core'
+import type { OpenId4VciCredentialRequestToCredentialMapper } from '@credo-ts/openid4vc'
+import { agent } from './agent'
+import { AGENT_HOST } from './constants'
+import { credentialsSupported, issuerDisplay, mockPidOpenId4VcPlaygroundCredentialSdJwtVcJwk } from './issuerMetadata'
+import { getX509Certificate } from './keyMethods'
-const issuerId = "e451c49f-1186-4fe4-816d-a942151dfd59";
+const issuerId = 'e451c49f-1186-4fe4-816d-a942151dfd59'
export async function createIssuer() {
return agent.modules.openId4VcIssuer.createIssuer({
issuerId,
credentialsSupported,
display: issuerDisplay,
- });
+ })
}
export async function doesIssuerExist() {
try {
- await agent.modules.openId4VcIssuer.getByIssuerId(issuerId);
- return true;
+ await agent.modules.openId4VcIssuer.getIssuerByIssuerId(issuerId)
+ return true
} catch (error) {
- return false;
+ return false
}
}
export async function getIssuer() {
- return agent.modules.openId4VcIssuer.getByIssuerId(issuerId);
+ return agent.modules.openId4VcIssuer.getIssuerByIssuerId(issuerId)
}
export async function updateIssuer() {
@@ -46,163 +33,84 @@ export async function updateIssuer() {
issuerId,
credentialsSupported,
display: issuerDisplay,
- });
+ })
}
-export const credentialRequestToCredentialMapper: OpenId4VciCredentialRequestToCredentialMapper =
- async ({
- credentialsSupported,
- credentialRequest,
- issuanceSession,
- // FIXME: it would be useful if holderBinding would include some metadata on the key type / alg used
- // for the key binding
- holderBinding,
- }) => {
- const credentialSupported = credentialsSupported[0];
-
- // not sure if this check is needed anymore
- if (!issuanceSession) throw new Error("Issuance session not found");
- if (!issuanceSession.issuanceMetadata)
- throw new Error("No issuance metadata");
-
- const { issuerDidMethod } =
- issuanceSession.issuanceMetadata as unknown as OfferSessionMetadata;
-
- const possibleDids = getAvailableDids().filter((d) =>
- d.startsWith(issuerDidMethod)
- );
-
- let holderKeyType: KeyType;
- if (holderBinding.method === "jwk") {
- holderKeyType = holderBinding.jwk.keyType;
- } else {
- const holderDidDocument = await agent.dids.resolveDidDocument(
- holderBinding.didUrl
- );
- const verificationMethod = holderDidDocument.dereferenceKey(
- holderBinding.didUrl
- );
- holderKeyType = getKeyFromVerificationMethod(verificationMethod).keyType;
- }
-
- if (possibleDids.length === 0) {
- throw new Error("No available DIDs for the issuer method");
- }
-
- let issuerDidUrl: string | undefined = undefined;
-
- for (const possibleDid of possibleDids) {
- const didDocument = await agent.dids.resolveDidDocument(possibleDid);
- // Set the first verificationMethod as backup, in case we won't find a match
- if (!issuerDidUrl && didDocument.verificationMethod?.[0].id) {
- issuerDidUrl = didDocument.verificationMethod?.[0].id;
- }
+export const credentialRequestToCredentialMapper: OpenId4VciCredentialRequestToCredentialMapper = async ({
+ // FIXME: it would be useful if holderBinding would include some metadata on the key type / alg used
+ // for the key binding
+ holderBinding,
+}) => {
+ const credentialSupported = credentialsSupported[0]
- const matchingVerificationMethod = didDocument.assertionMethod?.find(
- (assertionMethod) => {
- const verificationMethod =
- typeof assertionMethod === "string"
- ? didDocument.dereferenceVerificationMethod(assertionMethod)
- : assertionMethod;
- const keyType =
- getKeyFromVerificationMethod(verificationMethod).keyType;
- return keyType === holderKeyType;
- }
- );
+ const x509Certificate = getX509Certificate()
- if (matchingVerificationMethod) {
- issuerDidUrl =
- typeof matchingVerificationMethod === "string"
- ? matchingVerificationMethod
- : matchingVerificationMethod.id;
- break;
- }
- }
-
- if (!issuerDidUrl) {
- throw new Error("No matching verification method found");
- }
-
- if (
- credentialSupported.format === "vc+sd-jwt" &&
- (credentialSupported.id ===
- animoOpenId4VcPlaygroundCredentialSdJwtVcDid.id ||
- credentialSupported.id ===
- animoOpenId4VcPlaygroundCredentialSdJwtVcJwk.id)
- ) {
- return {
- format: "vc+sd-jwt",
- holder: holderBinding,
- payload: {
- vct: credentialSupported.vct,
+ let holderKeyType: KeyType
+ if (holderBinding.method === 'jwk') {
+ holderKeyType = holderBinding.jwk.keyType
+ } else {
+ throw new Error(`Unsupported holder binding method: ${holderBinding.method}`)
+ }
- playground: {
- framework: "Aries Framework JavaScript",
- language: "TypeScript",
- version: "1.0",
- createdBy: "Animo Solutions",
- },
+ if (
+ credentialSupported.format === 'vc+sd-jwt' &&
+ credentialSupported.id === mockPidOpenId4VcPlaygroundCredentialSdJwtVcJwk.id
+ ) {
+ return {
+ credentialSupportedId: credentialSupported.id,
+ format: 'vc+sd-jwt',
+ holder: holderBinding,
+ payload: {
+ vct: credentialSupported.vct,
+ given_name: 'Erika',
+ family_name: 'Mustermann',
+ birthdate: '1963-08-12',
+ source_document_type: 'id_card',
+ address: {
+ street_address: 'Heidestraße 17',
+ locality: 'Köln',
+ postal_code: '51147',
+ country: 'DE',
},
- issuer: {
- didUrl: issuerDidUrl,
- method: "did",
+ nationalities: ['DE'],
+ gender: 'female',
+ birth_family_name: 'Gabler',
+ place_of_birth: {
+ locality: 'Berlin',
+ country: 'DE',
},
- disclosureFrame: {
- playground: {
- language: true,
- version: true,
- },
- } as any,
- };
- }
-
- if (
- (credentialSupported.format === "jwt_vc_json" &&
- credentialSupported.id ===
- animoOpenId4VcPlaygroundCredentialJwtVc.id) ||
- (credentialSupported.format === "ldp_vc" &&
- credentialSupported.id === animoOpenId4VcPlaygroundCredentialLdpVc.id)
- ) {
- if (holderBinding.method !== "did") {
- throw new Error("Only did holder binding supported for JWT VC");
- }
- return {
- format:
- credentialSupported.format === "jwt_vc_json" ? "jwt_vc" : "ldp_vc",
- verificationMethod: issuerDidUrl,
- credential: W3cCredential.fromJson({
- // FIXME: we need to include/cache default contexts in AFJ
- // It quite slow the first time now
- // And not secure
- "@context":
- credentialSupported.format === "ldp_vc"
- ? [
- "https://www.w3.org/2018/credentials/v1",
- // Fields must be defined for JSON-LD
- {
- "@vocab":
- "https://www.w3.org/ns/credentials/issuer-dependent#",
- },
- ]
- : ["https://www.w3.org/2018/credentials/v1"],
- // TODO: should 'VerifiableCredential' be in the issuer metadata type?
- // FIXME: jwt verification did not fail when this was array within array
- // W3cCredential is not validated in AFJ???
- type: ["VerifiableCredential", ...credentialSupported.types],
- issuanceDate: new Date().toISOString(),
- issuer: parseDid(issuerDidUrl).did,
- credentialSubject: {
- id: parseDid(holderBinding.didUrl).did,
- playground: {
- framework: "Aries Framework JavaScript",
- language: "TypeScript",
- version: "1.0",
- createdBy: "Animo Solutions",
- },
- },
- }),
- };
+ also_known_as: 'Schwester Agnes',
+ age_equal_or_over: {
+ '12': true,
+ '14': true,
+ '16': true,
+ '18': true,
+ '21': true,
+ '65': false,
+ },
+ },
+ issuer: {
+ method: 'x5c',
+ x5c: [x509Certificate],
+ issuer: AGENT_HOST,
+ },
+ disclosureFrame: {
+ _sd: [
+ 'given_name',
+ 'family_name',
+ 'birthdate',
+ 'source_document_type',
+ 'address',
+ 'nationalities',
+ 'gender',
+ 'birth_family_name',
+ 'place_of_birth',
+ 'also_known_as',
+ ],
+ age_equal_or_over: { _sd: ['12', '14', '16', '18', '21', '65'] },
+ },
}
+ }
- throw new Error(`Unsupported credential ${credentialSupported.id}`);
- };
+ throw new Error(`Unsupported credential ${credentialSupported.id}`)
+}
diff --git a/agent/src/issuerMetadata.ts b/agent/src/issuerMetadata.ts
index 13ab2a1..880169c 100644
--- a/agent/src/issuerMetadata.ts
+++ b/agent/src/issuerMetadata.ts
@@ -1,122 +1,49 @@
-import { JwaSignatureAlgorithm } from "@credo-ts/core";
+import { JwaSignatureAlgorithm } from '@credo-ts/core'
import {
- OpenId4VciCredentialSupportedWithId,
OpenId4VciCredentialFormatProfile,
- OpenId4VciIssuerMetadataDisplay,
-} from "@credo-ts/openid4vc";
+ type OpenId4VciCredentialSupportedWithId,
+ type OpenId4VciIssuerMetadataDisplay,
+} from '@credo-ts/openid4vc'
-const ANIMO_BLUE = "#5e7db6";
-const ANIMO_RED = "#E17471";
-const ANIMO_DARK_BACKGROUND = "#202223";
-const WHITE = "#FFFFFF";
+const ANIMO_DARK_BACKGROUND = '#202223'
+const WHITE = '#FFFFFF'
export const issuerDisplay = [
{
background_color: ANIMO_DARK_BACKGROUND,
- name: "Animo OpenID4VC Playground",
- locale: "en",
+ name: 'Animo + Funke OpenID4VC Playground',
+ locale: 'en',
logo: {
- alt_text: "Animo logo",
- url: "https://i.imgur.com/PUAIUed.jpeg",
+ alt_text: 'Animo logo',
+ url: 'https://i.imgur.com/PUAIUed.jpeg',
},
text_color: WHITE,
},
-] satisfies OpenId4VciIssuerMetadataDisplay[];
+] satisfies OpenId4VciIssuerMetadataDisplay[]
-export const animoOpenId4VcPlaygroundCredentialSdJwtVcDid = {
- id: "AnimoOpenId4VcPlaygroundSdJwtVcDid",
+export const mockPidOpenId4VcPlaygroundCredentialSdJwtVcJwk = {
+ id: 'mockPidOpenId4VcPlaygroundSdJwtVcJwk',
format: OpenId4VciCredentialFormatProfile.SdJwtVc,
- vct: "AnimoOpenId4VcPlayground",
- cryptographic_binding_methods_supported: ["did:key", "did:jwk"],
- cryptographic_suites_supported: [
- JwaSignatureAlgorithm.EdDSA,
- JwaSignatureAlgorithm.ES256,
- ],
- display: [
- {
- name: "SD-JWT-VC",
- description: "DID holder binding",
- background_color: ANIMO_DARK_BACKGROUND,
- locale: "en",
- text_color: WHITE,
- },
- ],
-} as const satisfies OpenId4VciCredentialSupportedWithId;
-
-export const animoOpenId4VcPlaygroundCredentialSdJwtVcJwk = {
- id: "AnimoOpenId4VcPlaygroundSdJwtVcJwk",
- format: OpenId4VciCredentialFormatProfile.SdJwtVc,
- vct: "AnimoOpenId4VcPlayground",
- cryptographic_binding_methods_supported: ["jwk"],
- cryptographic_suites_supported: [
- JwaSignatureAlgorithm.EdDSA,
- JwaSignatureAlgorithm.ES256,
- ],
+ vct: 'https://example.bmi.bund.de/credential/pid/1.0',
+ cryptographic_binding_methods_supported: ['jwk'],
+ credential_signing_alg_values_supported: [JwaSignatureAlgorithm.ES256],
display: [
{
- name: "SD-JWT-VC",
- description: "JWK holder binding",
+ name: 'SD-JWT-VC',
+ description: 'JWK holder binding',
background_color: ANIMO_DARK_BACKGROUND,
- locale: "en",
+ locale: 'en',
text_color: WHITE,
},
],
-} as const satisfies OpenId4VciCredentialSupportedWithId;
-
-export const animoOpenId4VcPlaygroundCredentialJwtVc = {
- id: "AnimoOpenId4VcPlaygroundJwtVc",
- format: OpenId4VciCredentialFormatProfile.JwtVcJson,
- types: ["AnimoOpenId4VcPlayground"],
- cryptographic_binding_methods_supported: ["did:key", "did:jwk"],
- cryptographic_suites_supported: [
- JwaSignatureAlgorithm.EdDSA,
- JwaSignatureAlgorithm.ES256,
- ],
- display: [
- {
- name: "JWT VC",
- background_color: ANIMO_DARK_BACKGROUND,
- locale: "en",
- text_color: WHITE,
- },
- ],
-} as const satisfies OpenId4VciCredentialSupportedWithId;
-
-export const animoOpenId4VcPlaygroundCredentialLdpVc = {
- id: "AnimoOpenId4VcPlaygroundLdpVc",
- format: OpenId4VciCredentialFormatProfile.LdpVc,
- types: ["AnimoOpenId4VcPlayground"],
- "@context": ["https://www.w3.org/2018/credentials/v1"],
- cryptographic_binding_methods_supported: ["did:key", "did:jwk"],
- cryptographic_suites_supported: [
- JwaSignatureAlgorithm.EdDSA,
- // TODO: is it needed that proof type is added here?
- // According to spec yes, but it's only used for the request proof,
- // which is a jwt/cwt (so alg)
- "Ed25519Signature2018",
- ],
- display: [
- {
- name: "LDP VC",
- background_color: ANIMO_DARK_BACKGROUND,
- locale: "en",
- text_color: WHITE,
- },
- ],
-} as const satisfies OpenId4VciCredentialSupportedWithId;
+} as const satisfies OpenId4VciCredentialSupportedWithId
export const credentialsSupported = [
- animoOpenId4VcPlaygroundCredentialSdJwtVcDid,
- animoOpenId4VcPlaygroundCredentialSdJwtVcJwk,
- animoOpenId4VcPlaygroundCredentialJwtVc,
- // Not really working yet
- // FIXME: Ed25519Signature2018 required ed25519 context url
- // but that is bullshit, as you can just use another verification
- // method to issue/verify such as JsonWebKey or MultiKey
- // animoOpenId4VcPlaygroundCredentialLdpVc,
-] as const satisfies OpenId4VciCredentialSupportedWithId[];
-type CredentialSupportedId = (typeof credentialsSupported)[number]["id"];
+ mockPidOpenId4VcPlaygroundCredentialSdJwtVcJwk,
+] as const satisfies OpenId4VciCredentialSupportedWithId[]
+
+type CredentialSupportedId = (typeof credentialsSupported)[number]['id']
export const credentialSupportedIds = credentialsSupported.map((s) => s.id) as [
CredentialSupportedId,
- ...CredentialSupportedId[]
-];
+ ...CredentialSupportedId[],
+]
diff --git a/agent/src/keyMethods/createKeys.ts b/agent/src/keyMethods/createKeys.ts
new file mode 100644
index 0000000..97d6945
--- /dev/null
+++ b/agent/src/keyMethods/createKeys.ts
@@ -0,0 +1,12 @@
+import { KeyType, TypedArrayEncoder } from '@credo-ts/core'
+import { agent } from '../agent'
+import { P256_SEED } from '../constants'
+
+export async function createKeys() {
+ const p256Key = await agent.wallet.createKey({
+ keyType: KeyType.P256,
+ seed: TypedArrayEncoder.fromString(P256_SEED),
+ })
+
+ return p256Key
+}
diff --git a/agent/src/keyMethods/createSelfSignedCertificate.ts b/agent/src/keyMethods/createSelfSignedCertificate.ts
new file mode 100644
index 0000000..5309310
--- /dev/null
+++ b/agent/src/keyMethods/createSelfSignedCertificate.ts
@@ -0,0 +1,13 @@
+import { type Key, X509Service } from '@credo-ts/core'
+import { agent } from '../agent'
+import { AGENT_HOST } from '../constants'
+
+export const createSelfSignedCertificate = async (key: Key) =>
+ (
+ await X509Service.createSelfSignedCertificate(agent.context, {
+ key,
+ extensions: [[{ type: 'url', value: AGENT_HOST }]],
+ notBefore: new Date(0), // Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)
+ notAfter: new Date(10000000000000), // Sat Nov 20 2286 18:46:40 GMT+0100 (Central European Standard Time)
+ })
+ ).toString('base64')
diff --git a/agent/src/keyMethods/index.ts b/agent/src/keyMethods/index.ts
new file mode 100644
index 0000000..5a774a6
--- /dev/null
+++ b/agent/src/keyMethods/index.ts
@@ -0,0 +1 @@
+export * from './setup'
diff --git a/agent/src/keyMethods/setup.ts b/agent/src/keyMethods/setup.ts
new file mode 100644
index 0000000..7c46e81
--- /dev/null
+++ b/agent/src/keyMethods/setup.ts
@@ -0,0 +1,46 @@
+import { WalletKeyExistsError, X509Api, X509Module, X509Service } from '@credo-ts/core'
+import { agent } from '../agent'
+import { createKeys } from './createKeys'
+import { createSelfSignedCertificate } from './createSelfSignedCertificate'
+
+let x509Certificate: string | undefined = undefined
+
+export async function setupX509Certificate() {
+ try {
+ const key = await createKeys()
+
+ x509Certificate = await createSelfSignedCertificate(key)
+
+ await agent.genericRecords.save({
+ id: 'X509_CERTIFICATE',
+ content: {
+ certificate: x509Certificate,
+ },
+ })
+ } catch (error) {
+ // If the key already exists, we assume the self-signed certificate is already created
+ if (error instanceof WalletKeyExistsError) {
+ const x509Record = await agent.genericRecords.findById('X509_CERTIFICATE')
+ if (!x509Record) {
+ throw new Error('No available key method record found')
+ }
+ x509Certificate = x509Record.content.certificate as string
+ } else {
+ throw error
+ }
+ }
+
+ console.log('==== X.509 Certificate ====')
+ console.log(x509Certificate)
+ console.log('===========================')
+
+ const x509 = agent.dependencyManager.resolve(X509Api)
+ await x509.addTrustedCertificate(x509Certificate)
+}
+
+export function getX509Certificate() {
+ if (!x509Certificate) {
+ throw new Error('X509 certificate is not setup properly')
+ }
+ return x509Certificate
+}
diff --git a/agent/src/server.ts b/agent/src/server.ts
index cb3419b..f32105b 100644
--- a/agent/src/server.ts
+++ b/agent/src/server.ts
@@ -1,47 +1,41 @@
-import { agent, openId4VciRouter, openId4VpRouter } from "./agent";
-import { apiRouter } from "./endpoints";
-import { createIssuer, doesIssuerExist, updateIssuer } from "./issuer";
-import { createVerifier, doesVerifierExist } from "./verifier";
-import express, { Response } from "express";
-import { getWebDidDocument, setupAllDids } from "./did";
-import cors from "cors";
+import cors from 'cors'
+import express from 'express'
+import { agent, openId4VciRouter, openId4VpRouter } from './agent'
+import { apiRouter } from './endpoints'
+import { createIssuer, doesIssuerExist, updateIssuer } from './issuer'
+import { setupX509Certificate } from './keyMethods'
+import { createVerifier, doesVerifierExist } from './verifier'
async function run() {
- await agent.initialize();
+ await agent.initialize()
if (!(await doesIssuerExist())) {
- await createIssuer();
+ await createIssuer()
} else {
// We update the issuer metadata on every startup to sync the static issuer metadata with the issuer metadata record
- await updateIssuer();
+ await updateIssuer()
}
if (!(await doesVerifierExist())) {
- await createVerifier();
+ await createVerifier()
}
- await setupAllDids();
+ await setupX509Certificate()
- const app = express();
- app.use(cors({ origin: "*" }));
+ const app = express()
+ app.use(cors({ origin: '*' }))
- app.use("/oid4vci", openId4VciRouter);
- app.use("/siop", openId4VpRouter);
- app.use("/api", apiRouter);
- app.use("/.well-known/did.json", async (_, response: Response) => {
- const didWeb = await getWebDidDocument();
- return response.json(didWeb.toJSON());
- });
+ app.use('/oid4vci', openId4VciRouter)
+ app.use('/siop', openId4VpRouter)
+ app.use('/api', apiRouter)
- app.listen(3001, () =>
- agent.config.logger.info("app listening on port 3001")
- );
+ app.listen(3001, () => agent.config.logger.info('app listening on port 3001'))
// @ts-ignore
app.use((err, _, res, __) => {
- console.error(err.stack);
- res.status(500).send("Something broke!");
- });
+ console.error(err.stack)
+ res.status(500).send('Something broke!')
+ })
}
-run();
+run()
diff --git a/agent/src/session.ts b/agent/src/session.ts
index 537ec44..7b81129 100644
--- a/agent/src/session.ts
+++ b/agent/src/session.ts
@@ -1,3 +1,3 @@
export interface OfferSessionMetadata {
- issuerDidMethod: string;
+ issuerDidMethod: string
}
diff --git a/agent/src/verifier.ts b/agent/src/verifier.ts
index 06545fb..3c9ab6e 100644
--- a/agent/src/verifier.ts
+++ b/agent/src/verifier.ts
@@ -1,22 +1,22 @@
-import { agent } from "./agent";
+import { agent } from './agent'
-const verifierId = "c01ea0f3-34df-41d5-89d1-50ef3d181855";
+const verifierId = 'c01ea0f3-34df-41d5-89d1-50ef3d181855'
export async function createVerifier() {
return agent.modules.openId4VcVerifier.createVerifier({
verifierId,
- });
+ })
}
export async function doesVerifierExist() {
try {
- await agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId);
- return true;
+ await agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId)
+ return true
} catch (error) {
- return false;
+ return false
}
}
export async function getVerifier() {
- return agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId);
+ return agent.modules.openId4VcVerifier.getVerifierByVerifierId(verifierId)
}
diff --git a/app/app/layout.tsx b/app/app/layout.tsx
index 1c6d988..f4b1b77 100644
--- a/app/app/layout.tsx
+++ b/app/app/layout.tsx
@@ -1,22 +1,22 @@
-import type { Metadata } from "next";
-import { Inter } from "next/font/google";
-import "./globals.css";
+import type { Metadata } from 'next'
+import { Inter } from 'next/font/google'
+import './globals.css'
-const inter = Inter({ subsets: ["latin"] });
+const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
- title: "OpenID4VC Playground",
- description: "By Animo",
-};
+ title: 'OpenID4VC Playground',
+ description: 'By Animo',
+}
export default function RootLayout({
children,
}: {
- children: React.ReactNode;
+ children: React.ReactNode
}) {
return (
{children}
- );
+ )
}
diff --git a/app/app/page.tsx b/app/app/page.tsx
index 82b3f19..467c5d9 100644
--- a/app/app/page.tsx
+++ b/app/app/page.tsx
@@ -1,5 +1,5 @@
-import { Main } from "@/components/main";
+import { Main } from '@/components/main'
export default function Home() {
- return ;
+ return
}
diff --git a/app/components.json b/app/components.json
index 5f94bb8..dae32f9 100644
--- a/app/components.json
+++ b/app/components.json
@@ -13,4 +13,4 @@
"utils": "@/lib/utils",
"components": "@/components"
}
-}
\ No newline at end of file
+}
diff --git a/app/components/IssueTab.tsx b/app/components/IssueTab.tsx
index 4734998..4783b12 100644
--- a/app/components/IssueTab.tsx
+++ b/app/components/IssueTab.tsx
@@ -1,56 +1,44 @@
-import { ExclamationTriangleIcon } from "@radix-ui/react-icons";
-import { Label } from "@/components/ui/label";
-import {
- SelectValue,
- SelectTrigger,
- SelectItem,
- SelectGroup,
- SelectContent,
- Select,
-} from "@/components/ui/select";
-import {
- TooltipProvider,
- Tooltip,
- TooltipTrigger,
- TooltipContent,
-} from "@/components/ui/tooltip";
-import QRCode from "react-qr-code";
-import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
-import { Button } from "@/components/ui/button";
-import { Card } from "@/components/ui/card";
-import { FormEvent, useEffect, useState } from "react";
-import { getIssuer, createOffer } from "../lib/api";
+import { Button } from '@/components/ui/button'
+import { Card } from '@/components/ui/card'
+import { Label } from '@/components/ui/label'
+import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
+import { type FormEvent, useEffect, useState } from 'react'
+import QRCode from 'react-qr-code'
+import { createOffer, getIssuer } from '../lib/api'
export function IssueTab() {
- const [credentialType, setCredentialType] = useState();
- const [issuerDid, setIssuerDid] = useState();
- const [credentialOfferUri, setCredentialOfferUri] = useState();
+ const [credentialType, setCredentialType] = useState()
+ const [issuerId, setIssuerid] = useState()
+ const [credentialOfferUri, setCredentialOfferUri] = useState()
const [issuer, setIssuer] = useState<{
credentialsSupported: Array<{
- id: string;
- display: [{ name: string; description?: string }];
- }>;
- availableDidMethods: string[];
- display: {};
- }>();
+ id: string
+ display: string
+ }>
+ availableX509Certificates: string[]
+ display: {}
+ }>()
useEffect(() => {
- getIssuer().then(setIssuer);
- }, []);
+ getIssuer().then((i) => {
+ setIssuer(i)
+ console.log(i)
+ })
+ }, [])
async function onSubmitIssueCredential(e: FormEvent) {
- e.preventDefault();
- const _issuerDidMethod = issuerDid ?? issuer?.availableDidMethods[0];
- const _credentialType =
- credentialType ?? issuer?.credentialsSupported[0].id;
- if (!_issuerDidMethod || !_credentialType) {
- throw new Error("No issuer or credential type");
+ e.preventDefault()
+ const _issuerId = issuerId ?? issuer?.availableX509Certificates[0]
+ const _credentialType = credentialType ?? issuer?.credentialsSupported[0].id
+ if (!_issuerId || !_credentialType) {
+ throw new Error('No issuer or credential type')
}
const offer = await createOffer({
credentialSupportedId: _credentialType,
- issuerDidMethod: _issuerDidMethod,
- });
- setCredentialOfferUri(offer.credentialOffer);
+ issuerId: _issuerId,
+ })
+ setCredentialOfferUri(offer.credentialOffer)
}
return (
@@ -58,54 +46,36 @@ export function IssueTab() {
-
-
- Warning
-
- When using the{" "}
-
- Paradym Wallet
-
- , only issuance of JWT credentials (not SD-JWT credentials) using a
- did method other than did:cheqd
is supported.
-
-
- );
+ )
}
diff --git a/app/components/ReceiveTab.tsx b/app/components/ReceiveTab.tsx
index c71c0d7..0674638 100644
--- a/app/components/ReceiveTab.tsx
+++ b/app/components/ReceiveTab.tsx
@@ -1,20 +1,19 @@
-import { FormEvent, useState } from "react";
-import { receiveOffer } from "../lib/api";
-import { Label } from "@/components/ui/label";
-import { HighLight } from "@/components/highLight";
-import { Button } from "@/components/ui/button";
-import { Card } from "@/components/ui/card";
+import { HighLight } from '@/components/highLight'
+import { Button } from '@/components/ui/button'
+import { Card } from '@/components/ui/card'
+import { Label } from '@/components/ui/label'
+import { type FormEvent, useState } from 'react'
+import { receiveOffer } from '../lib/api'
export function ReceiveTab() {
- const [receiveCredentialOfferUri, setReceiveCredentialOfferUri] =
- useState();
- const [receivedCredentials, setReceivedCredentials] = useState();
+ const [receiveCredentialOfferUri, setReceiveCredentialOfferUri] = useState()
+ const [receivedCredentials, setReceivedCredentials] = useState()
async function onSubmitReceiveOffer(e: FormEvent) {
- e.preventDefault();
- if (!receiveCredentialOfferUri) return;
+ e.preventDefault()
+ if (!receiveCredentialOfferUri) return
- setReceivedCredentials(await receiveOffer(receiveCredentialOfferUri));
+ setReceivedCredentials(await receiveOffer(receiveCredentialOfferUri))
}
return (
@@ -26,31 +25,20 @@ export function ReceiveTab() {
className="w-full h-20 p-2 rounded-md bg-white border border-gray-300"
id="credential-offer-uri"
required
- onChange={(e) =>
- setReceiveCredentialOfferUri(e.currentTarget.value)
- }
+ onChange={(e) => setReceiveCredentialOfferUri(e.currentTarget.value)}
/>
{receivedCredentials ? (
-
+
) : (
-
- JSON content of the credential will be displayed here
-
+
JSON content of the credential will be displayed here
)}
-
-Animo OpenID4VC Playground
+Funke OpenID4VC Playground
> [!TIP]
-> Check out the demo at https://openid4vc.animo.id
+> Check out the demo at https://funke.animo.id
## ✨ Hi there!
-Welcome to the repository of Animo's OpenID4VC Playground. This interactive playground demonstrates the use of OpenID4VC with different credential formats (such as SD-JWT VCs). This demo is built using [Aries Framework Javascript (AFJ)](https://github.com/hyperledger/aries-framework-javascript). AFJ is a framework written in TypeScript for building decentralized identity services.
+Welcome to the repository of Animo's OpenID4VC Playground. This interactive playground demonstrates the use of OpenID4VC with different credential formats (such as SD-JWT VCs). This demo is built using [Credo](https://github.com/openwallet-foundation/credo-ts). Credo is a framework written in TypeScript for building decentralized identity services.
## 🛠️ Usage
From 6bc0f34b7c57498418406edba1e54b3f73a92936 Mon Sep 17 00:00:00 2001
From: Timo Glastra
Date: Wed, 14 Aug 2024 15:31:23 +0200
Subject: [PATCH 015/172] fix: show error
Signed-off-by: Timo Glastra
---
app/components/VerifyBlock.tsx | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/app/components/VerifyBlock.tsx b/app/components/VerifyBlock.tsx
index dfb8d7e..ac4d8e9 100644
--- a/app/components/VerifyBlock.tsx
+++ b/app/components/VerifyBlock.tsx
@@ -8,7 +8,7 @@ import { HighLight } from './highLight'
import { Alert, AlertDescription, AlertTitle } from './ui/alert'
import { Button } from './ui/button'
import { Card } from './ui/card'
-import { TypographyH2, TypographyH3, TypographyH4 } from './ui/typography'
+import { TypographyH3, TypographyH4 } from './ui/typography'
type VerifyBlockProps = {
flowName: string
@@ -36,7 +36,7 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam
requestStatus?.responseStatus !== 'Error'
const authorizationRequestUriHasBeenFetched = requestStatus?.responseStatus === 'RequestUriRetrieved'
- const hasResponse = requestStatus?.responseStatus === 'ResponseVerified'
+ const hasResponse = requestStatus?.responseStatus === 'ResponseVerified' || requestStatus?.responseStatus === 'Error'
const isSuccess = requestStatus?.responseStatus === 'ResponseVerified'
useInterval({
@@ -67,10 +67,14 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam
return (
{flowName}
-
@@ -112,18 +112,24 @@ export const VerifyBlock: React.FC = ({ createRequest, flowNam
{requestStatus?.error ?? 'Unknown error occurred'}
)}
- {requestStatus.definition &&
- Presentation Definition
-
-
}
- {requestStatus.submission &&
- Presentation Submission
-
-
}
- {requestStatus.presentations &&
- Presentations
-
-
}
+ {requestStatus.definition && (
+
+ Presentation Definition
+
+
+ )}
+ {requestStatus.submission && (
+
+ Presentation Submission
+
+
+ )}
+ {requestStatus.presentations && (
+
+ Presentations
+
+
+ )}
)}
diff --git a/app/components/VerifyTab.tsx b/app/components/VerifyTab.tsx
index db342c1..4e8ea02 100644
--- a/app/components/VerifyTab.tsx
+++ b/app/components/VerifyTab.tsx
@@ -1,9 +1,10 @@
-import { createRequest } from '../lib/api'
+import { createRequest, getIssuer } from '../lib/api'
import { VerifyBlock } from './VerifyBlock'
export function VerifyTab() {
- const createCRequest = () =>
- createRequest({
+ const createCRequest = async () => {
+ const issuer = (await getIssuer()).availableX509Certificates[0]
+ return await createRequest({
presentationDefinition: {
id: crypto.randomUUID(),
name: 'PID Credential request for C',
@@ -33,10 +34,7 @@ export function VerifyTab() {
path: ['$.iss'],
filter: {
type: 'string',
- enum: [
- 'https://demo.pid-issuer.bundesdruckerei.de/c',
- 'https://demo.pid-issuer.bundesdruckerei.de/c1',
- ],
+ enum: ['https://demo.pid-issuer.bundesdruckerei.de/c','https://demo.pid-issuer.bundesdruckerei.de/c1', issuer],
},
},
{
@@ -53,7 +51,9 @@ export function VerifyTab() {
},
],
},
+ flow: 'c'
})
+ }
const createBPrimeRequest = () =>
createRequest({
@@ -76,6 +76,7 @@ export function VerifyTab() {
},
],
},
+ flow: 'b''
})
return (
diff --git a/app/lib/api.ts b/app/lib/api.ts
index 16310e8..083148a 100644
--- a/app/lib/api.ts
+++ b/app/lib/api.ts
@@ -65,8 +65,10 @@ export async function receiveOffer(offerUri: string) {
export async function createRequest({
presentationDefinition,
+ flow,
}: {
presentationDefinition: any
+ flow: string
}) {
const response = await fetch(`${NEXT_PUBLIC_API_URL}/api/requests/create`, {
method: 'POST',
@@ -75,6 +77,7 @@ export async function createRequest({
},
body: JSON.stringify({
presentationDefinition,
+ flow,
}),
})
diff --git a/package.json b/package.json
index 9860ab1..fd2e9f4 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
"pnpm": {
"patchedDependencies": {
"@sphereon/did-auth-siop@0.15.1-next.4": "patches/@sphereon__did-auth-siop@0.15.1-next.4.patch",
- "@credo-ts/openid4vc@0.5.10-alpha-20240801095850": "patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch"
+ "@credo-ts/openid4vc@0.5.10-alpha-20240801095850": "patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch",
+ "@credo-ts/core@0.5.10-alpha-20240801095850": "patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch"
}
}
}
diff --git a/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch b/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
new file mode 100644
index 0000000..d4dfe4c
--- /dev/null
+++ b/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
@@ -0,0 +1,54 @@
+diff --git a/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts b/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
+index de5fe62881d049c4030125e0a4cc8ca38de41be9..1c1a48e75f081f2f52bddd0a970544e7438c77f2 100644
+--- a/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
++++ b/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
+@@ -90,4 +90,5 @@ export type SdJwtVcVerifyOptions = {
+ nonce: string;
+ };
+ requiredClaimKeys?: Array;
++ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ };
+diff --git a/build/modules/sd-jwt-vc/SdJwtVcService.js b/build/modules/sd-jwt-vc/SdJwtVcService.js
+index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2a8fae452 100644
+--- a/build/modules/sd-jwt-vc/SdJwtVcService.js
++++ b/build/modules/sd-jwt-vc/SdJwtVcService.js
+@@ -112,7 +112,7 @@ let SdJwtVcService = class SdJwtVcService {
+ throw new SdJwtVcError_1.SdJwtVcError(`The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate.`);
+ }
+ }
+- async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys }) {
++ async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys, verifyHs256Callback }) {
+ const sdjwt = new sd_jwt_vc_1.SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext));
+ const verificationResult = {
+ isValid: false,
+@@ -142,7 +142,7 @@ let SdJwtVcService = class SdJwtVcService {
+ const holderBinding = this.parseHolderBindingFromCredential(sdJwtVc);
+ const holder = holderBinding ? await this.extractKeyFromHolderBinding(agentContext, holderBinding) : undefined;
+ sdjwt.config({
+- verifier: this.verifier(agentContext, issuer.key),
++ verifier: this.verifier(agentContext, issuer.key, verifyHs256Callback),
+ kbVerifier: holder ? this.verifier(agentContext, holder.key) : undefined,
+ });
+ const requiredKeys = requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'];
+@@ -261,11 +261,20 @@ let SdJwtVcService = class SdJwtVcService {
+ /**
+ * @todo validate the JWT header (alg)
+ */
+- verifier(agentContext, key) {
++ verifier(agentContext, key, verifyHs256Callback) {
+ return async (message, signatureBase64Url) => {
+ if (!key) {
+ throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
+ }
++
++ const [header] = message.split(".")
++ if(header) {
++ const parsedHeader = utils_2.TypedArrayEncoder.fromBase64(header).toString()
++ const { alg } = JSON.parse(parsedHeader)
++ if(alg === "HS256") {
++ return await verifyHs256Callback(key, new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
++ }
++ }
+ return await agentContext.wallet.verify({
+ signature: utils_2.TypedArrayEncoder.fromBase64(signatureBase64Url),
+ key,
diff --git a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index a6d444b..d3d830c 100644
--- a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -1,3 +1,106 @@
+diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa1aba251e 100644
+--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
++++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+@@ -81,13 +81,16 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ first: 10000,
+ meta: 'OpenId4VcSiopVerifierService.createAuthorizationRequest',
+ }), (0, rxjs_1.map)((e) => e.payload.record)));
++ console.log(JSON.stringify(options, null ,2))
+ const authorizationRequest = await relyingParty.createAuthorizationRequest({
+ correlationId,
+ nonce,
+ state,
+ requestByReferenceURI: hostedAuthorizationRequestUri,
+ jwtIssuer,
++ additionalPayloadClaims: options.additionalPayloadClaims
+ });
++ console.log(JSON.stringify(authorizationRequest, null, 2))
+ // NOTE: it's not possible to set the uri scheme when using the RP to create an auth request, only lower level
+ // functions allow this. So we need to replace the uri scheme manually.
+ let authorizationRequestUri = (await authorizationRequest.uri()).encodedUri;
+@@ -144,6 +147,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ presentationVerificationCallback: this.getPresentationVerificationCallback(agentContext, {
+ nonce: requestNonce,
+ audience: requestClientId,
++ verifyHs256Callback: options.verifyHs256Callback
+ }),
+ },
+ });
+@@ -335,6 +339,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ keyBinding: {
+ audience: options.audience,
+ nonce: options.nonce,
++ verifyHs256Callback: options.verifyHs256Callback
+ },
+ });
+ isValid = verificationResult.verification.isValid;
+diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54bc919fad7 100644
+--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
++++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+@@ -18,12 +18,15 @@ export interface OpenId4VcSiopCreateAuthorizationRequestOptions {
+ presentationExchange?: {
+ definition: DifPresentationExchangeDefinitionV2;
+ };
++
++ additionalPayloadClaims?: Record
+ }
+ export interface OpenId4VcSiopVerifyAuthorizationResponseOptions {
+ /**
+ * The authorization response received from the OpenID Provider (OP).
+ */
+ authorizationResponse: OpenId4VcSiopAuthorizationResponsePayload;
++ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ }
+ export interface OpenId4VcSiopCreateAuthorizationRequestReturn {
+ authorizationRequest: string;
+diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+index baffab5ef01cffde68fefefdd89f561f75b59032..c57f258de062a64cf5252f458bd5e6b279e42a79 100644
+--- a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
++++ b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+@@ -7,5 +7,6 @@ export interface OpenId4VcSiopAuthorizationEndpointConfig {
+ * @default /authorize
+ */
+ endpointPath: string;
++ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ }
+ export declare function configureAuthorizationEndpoint(router: Router, config: OpenId4VcSiopAuthorizationEndpointConfig): void;
+diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.js b/build/openid4vc-verifier/router/authorizationEndpoint.js
+index a523a1e668863929f49b50fea6786e42955e5149..cc156969b3ca6b7e853a62a9a6f4f5ebfb182c03 100644
+--- a/build/openid4vc-verifier/router/authorizationEndpoint.js
++++ b/build/openid4vc-verifier/router/authorizationEndpoint.js
+@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.configureAuthorizationEndpoint = configureAuthorizationEndpoint;
+ const router_1 = require("../../shared/router");
+ const OpenId4VcSiopVerifierService_1 = require("../OpenId4VcSiopVerifierService");
++const core_1 = require("@credo-ts/core");
++
+ function configureAuthorizationEndpoint(router, config) {
+ router.post(config.endpointPath, async (request, response, next) => {
+ const { agentContext, verifier } = (0, router_1.getRequestContext)(request);
+@@ -16,6 +18,13 @@ function configureAuthorizationEndpoint(router, config) {
+ authorizationResponse,
+ verifierId: verifier.verifierId,
+ });
++ let verifyHs256Callback = undefined
++ const parsedAuthorizationRequest = core_1.Jwt.fromSerializedJwt(verificationSession.authorizationRequestJwt)
++ const rpEphPub = parsedAuthorizationRequest.payload.additionalClaims.rp_eph_pub
++ if(rpEphPub !== null && rpEphPub !== void 0) {
++ verifyHs256Callback = options.verifyHs256Callback(agentContext, rpEphPub.jwk)
++ }
++
+ if (!verificationSession) {
+ agentContext.config.logger.warn(`No verification session found for incoming authorization response for verifier ${verifier.verifierId}`);
+ return (0, router_1.sendErrorResponse)(response, agentContext.config.logger, 404, 'invalid_request', null);
+@@ -23,6 +32,7 @@ function configureAuthorizationEndpoint(router, config) {
+ await openId4VcVerifierService.verifyAuthorizationResponse(agentContext, {
+ authorizationResponse: request.body,
+ verificationSession,
++ verifyHs256Callback: verifyHs256Callback
+ });
+ response.status(200).send();
+ }
diff --git a/build/shared/utils.js b/build/shared/utils.js
index 36037ab98cf59f64b56d107aef9b2eb02b491c60..7eccc2ab99d396366299138df8d99376ca35696c 100644
--- a/build/shared/utils.js
diff --git a/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch b/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
index 2f02816..b35c651 100644
--- a/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
+++ b/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
@@ -1,5 +1,29 @@
+diff --git a/dist/request-object/Payload.js b/dist/request-object/Payload.js
+index f270cc5dd7ca4da9f93a16a400297ec8be9da936..d15b1ff70a68fdcd566707032e08e200cad3bb0f 100644
+--- a/dist/request-object/Payload.js
++++ b/dist/request-object/Payload.js
+@@ -35,12 +35,17 @@ const createRequestObjectPayload = (opts) => __awaiter(void 0, void 0, void 0, f
+ const nbf = (_e = payload.nbf) !== null && _e !== void 0 ? _e : iat;
+ const exp = (_f = payload.exp) !== null && _f !== void 0 ? _f : iat + validInSec;
+ const jti = (_g = payload.jti) !== null && _g !== void 0 ? _g : (0, uuid_1.v4)();
+- return (0, helpers_1.removeNullUndefined)(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ response_type: (_h = payload.response_type) !== null && _h !== void 0 ? _h : types_1.ResponseType.ID_TOKEN, scope: (_j = payload.scope) !== null && _j !== void 0 ? _j : types_1.Scope.OPENID,
++ const obj = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ response_type: (_h = payload.response_type) !== null && _h !== void 0 ? _h : types_1.ResponseType.ID_TOKEN, scope: (_j = payload.scope) !== null && _j !== void 0 ? _j : types_1.Scope.OPENID,
+ //TODO implement /.well-known/openid-federation support in the OP side to resolve the client_id (URL) and retrieve the metadata
+ client_id: clientId, client_id_scheme: opts.requestObject.payload.client_id_scheme }, (payload.redirect_uri && { redirect_uri: payload.redirect_uri })), (payload.response_uri && { response_uri: payload.response_uri })), { response_mode: (_k = payload.response_mode) !== null && _k !== void 0 ? _k : types_1.ResponseMode.DIRECT_POST }), (payload.id_token_hint && { id_token_hint: payload.id_token_hint })), { registration_uri: registration.clientMetadataOpts.reference_uri, nonce: (0, helpers_1.getNonce)(state, payload.nonce), state }), registration.payload), { claims, presentation_definition_uri: payload.presentation_definition_uri, presentation_definition: payload.presentation_definition, iat,
+ nbf,
+ exp,
+- jti }));
++ jti })
++
++ if(opts.additionalPayloadClaims !== null && opts.additionalPayloadClaims !== void 0) {
++ Object.assign(obj, opts.additionalPayloadClaims)
++ }
++ return (0, helpers_1.removeNullUndefined)(obj);
+ });
+ exports.createRequestObjectPayload = createRequestObjectPayload;
+ const assertValidRequestObjectPayload = (verPayload) => {
diff --git a/dist/request-object/RequestObject.js b/dist/request-object/RequestObject.js
-index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..359f45a7c4fc49fce2a8b67f2b9f596a1440b79c 100644
+index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..afb5ac1b1670566c55617deb3e811f0675a7d5ef 100644
--- a/dist/request-object/RequestObject.js
+++ b/dist/request-object/RequestObject.js
@@ -92,7 +92,6 @@ class RequestObject {
@@ -10,6 +34,20 @@ index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..359f45a7c4fc49fce2a8b67f2b9f596a
this.payload.client_id_scheme = jwtIssuer.clientIdScheme;
const header = { x5c: jwtIssuer.x5c, typ: 'JWT' };
this.jwt = yield this.opts.createJwtCallback(jwtIssuer, { header, payload: this.payload });
+diff --git a/dist/rp/RP.js b/dist/rp/RP.js
+index 92b27cbb69e2a6d44a7cf08b6f63326424fad1ce..06469a6f216c07f50649b98c63576fdf2c5448e7 100644
+--- a/dist/rp/RP.js
++++ b/dist/rp/RP.js
+@@ -218,6 +218,9 @@ class RP {
+ newOpts.requestObject.payload.claims = Object.assign(Object.assign({}, newOpts.requestObject.payload.claims), claimsWithTarget.propertyValue);
+ }
+ }
++ if(opts.additionalPayloadClaims !== null && opts.additionalPayloadClaims !== void 0) {
++ newOpts.additionalPayloadClaims = opts.additionalPayloadClaims
++ }
+ return newOpts;
+ }
+ newVerifyAuthorizationResponseOpts(authorizationResponse, opts) {
diff --git a/dist/types/JwtVerifier.js b/dist/types/JwtVerifier.js
index 90ecefe0c7b0859b05af643e5d7d88b271821e03..78eb1a0f24e79bead215b0ce507c17d230792791 100644
--- a/dist/types/JwtVerifier.js
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 70fbcfc..0d6f2b5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,11 +5,14 @@ settings:
excludeLinksFromLockfile: false
patchedDependencies:
+ '@credo-ts/core@0.5.10-alpha-20240801095850':
+ hash: l4twkbbkkn42qavc23ivocq3ry
+ path: patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
'@credo-ts/openid4vc@0.5.10-alpha-20240801095850':
- hash: ij2ukmbyghkte73e7dlixridre
+ hash: owfxcg6cf2dpbokdjdnq226t2y
path: patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
'@sphereon/did-auth-siop@0.15.1-next.4':
- hash: ursdgfgtybii6toqd2gon4vrsi
+ hash: mzeq3zftd7djamf7faz4ef6yam
path: patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
importers:
@@ -27,13 +30,13 @@ importers:
version: 0.5.10-alpha-20240801095850(@hyperledger/aries-askar-shared@0.2.3)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/core':
specifier: 0.5.10-alpha-20240801095850
- version: 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ version: 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/node':
specifier: 0.5.10-alpha-20240801095850
version: 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/openid4vc':
specifier: 0.5.10-alpha-20240801095850
- version: 0.5.10-alpha-20240801095850(patch_hash=ij2ukmbyghkte73e7dlixridre)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ version: 0.5.10-alpha-20240801095850(patch_hash=owfxcg6cf2dpbokdjdnq226t2y)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@hyperledger/aries-askar-nodejs':
specifier: ^0.2.3
version: 0.2.3
@@ -7169,7 +7172,7 @@ snapshots:
'@credo-ts/askar@0.5.10-alpha-20240801095850(@hyperledger/aries-askar-shared@0.2.3)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
- '@credo-ts/core': 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@hyperledger/aries-askar-shared': 0.2.3
bn.js: 5.2.1
class-transformer: 0.5.1
@@ -7184,7 +7187,7 @@ snapshots:
- supports-color
- web-streams-polyfill
- '@credo-ts/core@0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
+ '@credo-ts/core@0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
'@digitalcredentials/jsonld': 6.0.0(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@digitalcredentials/jsonld-signatures': 9.4.0(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
@@ -7238,7 +7241,7 @@ snapshots:
dependencies:
'@2060.io/ffi-napi': 4.0.9
'@2060.io/ref-napi': 3.0.6
- '@credo-ts/core': 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@types/express': 4.17.21
express: 4.18.2
ws: 8.16.0
@@ -7252,10 +7255,10 @@ snapshots:
- utf-8-validate
- web-streams-polyfill
- '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=ij2ukmbyghkte73e7dlixridre)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
+ '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=owfxcg6cf2dpbokdjdnq226t2y)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
- '@credo-ts/core': 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
- '@sphereon/did-auth-siop': 0.15.1-next.4(patch_hash=ursdgfgtybii6toqd2gon4vrsi)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@sphereon/did-auth-siop': 0.15.1-next.4(patch_hash=mzeq3zftd7djamf7faz4ef6yam)
'@sphereon/oid4vci-client': 0.15.1-next.4
'@sphereon/oid4vci-common': 0.15.1-next.4
'@sphereon/oid4vci-issuer': 0.15.1-next.4
@@ -8936,7 +8939,7 @@ snapshots:
'@sovpro/delimited-stream@1.1.0': {}
- '@sphereon/did-auth-siop@0.15.1-next.4(patch_hash=ursdgfgtybii6toqd2gon4vrsi)':
+ '@sphereon/did-auth-siop@0.15.1-next.4(patch_hash=mzeq3zftd7djamf7faz4ef6yam)':
dependencies:
'@astronautlabs/jsonpath': 1.1.2
'@sphereon/did-uni-client': 0.6.3
@@ -10392,7 +10395,7 @@ snapshots:
eslint: 8.56.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0)
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0)
eslint-plugin-react: 7.33.2(eslint@8.56.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0)
@@ -10416,7 +10419,7 @@ snapshots:
enhanced-resolve: 5.15.0
eslint: 8.56.0
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
fast-glob: 3.3.2
get-tsconfig: 4.7.2
is-core-module: 2.13.1
@@ -10438,7 +10441,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
+ eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0):
dependencies:
array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3
From 597913f30f17d5c02d62a5dff66d416c7fcae419 Mon Sep 17 00:00:00 2001
From: Timo Glastra
Date: Sun, 25 Aug 2024 21:16:30 +0200
Subject: [PATCH 021/172] feat: flow combined
Signed-off-by: Timo Glastra
---
agent/src/endpoints.ts | 58 +++++++++++++++++-------------------
app/components/VerifyTab.tsx | 41 +++++--------------------
app/lib/api.ts | 3 --
3 files changed, 35 insertions(+), 67 deletions(-)
diff --git a/agent/src/endpoints.ts b/agent/src/endpoints.ts
index 62768a1..b693003 100644
--- a/agent/src/endpoints.ts
+++ b/agent/src/endpoints.ts
@@ -6,11 +6,10 @@ import {
TypedArrayEncoder,
W3cJsonLdVerifiablePresentation,
W3cJwtVerifiablePresentation,
- getJwkFromJson,
getJwkFromKey,
} from '@credo-ts/core'
import { OpenId4VcVerificationSessionState } from '@credo-ts/openid4vc'
-import { Key as AskarKey, KeyAlgs, keyAlgToString } from '@hyperledger/aries-askar-nodejs'
+import { Key as AskarKey, KeyAlgs } from '@hyperledger/aries-askar-nodejs'
import express, { type NextFunction, type Request, type Response } from 'express'
import z from 'zod'
import { agent } from './agent'
@@ -116,12 +115,10 @@ apiRouter.post('/offers/receive', async (request: Request, response: Response) =
const zCreatePresentationRequestBody = z.object({
presentationDefinition: z.record(z.string(), z.any()),
- flow: z.string(),
})
apiRouter.post('/requests/create', async (request: Request, response: Response) => {
const verifier = await getVerifier()
- // This will also be done for the C flow, but that does not matter right now
// FIXME: somehow JSON doesn't work
const createPresentationRequestBody = zCreatePresentationRequestBody.parse(
@@ -131,38 +128,36 @@ apiRouter.post('/requests/create', async (request: Request, response: Response)
const x509Certificate = getX509Certificate()
const definition = createPresentationRequestBody.presentationDefinition
- const flow = createPresentationRequestBody.flow
-
- const additionalPayloadClaims: { rp_eph_pub?: Record } = {}
- if (flow === "b'") {
- try {
- // TODO: disable for real credential
- // Key for the fake credential. Can be removed when the pid issuer updated
- await agent.wallet.createKey({
- keyType: KeyType.P256,
- privateKey: TypedArrayEncoder.fromHex('ad38184e0d5d9af97b023b6421707dc079f7d66a185bfd4c589837e3cb69fbfb'),
- })
- // Ignore key already exist
- } catch {}
-
- const askarKey = AskarKey.fromSecretBytes({
- secretKey: new Uint8Array(
- TypedArrayEncoder.fromHex('ad38184e0d5d9af97b023b6421707dc079f7d66a185bfd4c589837e3cb69fbfb')
- ),
- algorithm: KeyAlgs.EcSecp256r1,
+
+ try {
+ // TODO: disable for real credential
+ // Key for the fake credential. Can be removed when the pid issuer updated
+ await agent.wallet.createKey({
+ keyType: KeyType.P256,
+ privateKey: TypedArrayEncoder.fromHex('ad38184e0d5d9af97b023b6421707dc079f7d66a185bfd4c589837e3cb69fbfb'),
})
+ // Ignore key already exist
+ } catch {}
+
+ const askarKey = AskarKey.fromSecretBytes({
+ secretKey: new Uint8Array(
+ TypedArrayEncoder.fromHex('ad38184e0d5d9af97b023b6421707dc079f7d66a185bfd4c589837e3cb69fbfb')
+ ),
+ algorithm: KeyAlgs.EcSecp256r1,
+ })
- additionalPayloadClaims.rp_eph_pub = {
+ const additionalPayloadClaims = {
+ rp_eph_pub: {
jwk: askarKey.jwkPublic,
- }
-
- // TODO: enable for real credential
- // const key = await agent.context.wallet.createKey({keyType: KeyType.P256})
- // additionalClaims["rp_eph_pub"] = {
- // jwk: getJwkFromKey(key).toJson(),
- // };
+ },
}
+ // TODO: enable for real credential
+ // const key = await agent.context.wallet.createKey({keyType: KeyType.P256})
+ // additionalClaims["rp_eph_pub"] = {
+ // jwk: getJwkFromKey(key).toJson(),
+ // };
+
const { authorizationRequest, verificationSession } =
await agent.modules.openId4VcVerifier.createAuthorizationRequest({
verifierId: verifier.verifierId,
@@ -174,6 +169,7 @@ apiRouter.post('/requests/create', async (request: Request, response: Response)
presentationExchange: {
definition: definition as any,
},
+ // @ts-ignore
additionalPayloadClaims,
})
diff --git a/app/components/VerifyTab.tsx b/app/components/VerifyTab.tsx
index 4e8ea02..3d3a61c 100644
--- a/app/components/VerifyTab.tsx
+++ b/app/components/VerifyTab.tsx
@@ -34,7 +34,12 @@ export function VerifyTab() {
path: ['$.iss'],
filter: {
type: 'string',
- enum: ['https://demo.pid-issuer.bundesdruckerei.de/c','https://demo.pid-issuer.bundesdruckerei.de/c1', issuer],
+ enum: [
+ 'https://demo.pid-issuer.bundesdruckerei.de/c',
+ 'https://demo.pid-issuer.bundesdruckerei.de/c1',
+ 'https://demo.pid-issuer.bundesdruckerei.de/b1',
+ issuer,
+ ],
},
},
{
@@ -47,49 +52,19 @@ export function VerifyTab() {
],
},
name: 'PID Name',
- purpose: 'Verify your name',
+ purpose: 'To open a bank account we need to verify your identity.',
},
],
},
- flow: 'c'
})
}
- const createBPrimeRequest = () =>
- createRequest({
- presentationDefinition: {
- id: crypto.randomUUID(),
- name: "PID Credential request for B'",
- input_descriptors: [
- {
- id: crypto.randomUUID(),
- constraints: {
- limit_disclosure: 'preferred',
- fields: [
- {
- path: ['$.given_name'],
- },
- ],
- },
- name: 'PID Name',
- purpose: 'Verify your name',
- },
- ],
- },
- flow: 'b''
- })
-
return (
<>
-
-
>
)
}
diff --git a/app/lib/api.ts b/app/lib/api.ts
index 083148a..16310e8 100644
--- a/app/lib/api.ts
+++ b/app/lib/api.ts
@@ -65,10 +65,8 @@ export async function receiveOffer(offerUri: string) {
export async function createRequest({
presentationDefinition,
- flow,
}: {
presentationDefinition: any
- flow: string
}) {
const response = await fetch(`${NEXT_PUBLIC_API_URL}/api/requests/create`, {
method: 'POST',
@@ -77,7 +75,6 @@ export async function createRequest({
},
body: JSON.stringify({
presentationDefinition,
- flow,
}),
})
From 780335bcd2dde72039e31dee455ca99121a69c3d Mon Sep 17 00:00:00 2001
From: Timo Glastra
Date: Sun, 25 Aug 2024 21:42:41 +0200
Subject: [PATCH 022/172] fix: make it work
Signed-off-by: Timo Glastra
---
agent/package.json | 3 +-
...ts__core@0.5.10-alpha-20240801095850.patch | 54 +++++++++
...penid4vc@0.5.10-alpha-20240801095850.patch | 103 ++++++++++++++++++
...phereon__did-auth-siop@0.15.1-next.4.patch | 40 ++++++-
app/components/VerifyTab.tsx | 4 +-
...penid4vc@0.5.10-alpha-20240801095850.patch | 2 +-
pnpm-lock.yaml | 6 +-
7 files changed, 204 insertions(+), 8 deletions(-)
create mode 100644 agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
diff --git a/agent/package.json b/agent/package.json
index ea2099f..b78bc99 100644
--- a/agent/package.json
+++ b/agent/package.json
@@ -26,7 +26,8 @@
"pnpm": {
"patchedDependencies": {
"@sphereon/did-auth-siop@0.15.1-next.4": "patches/@sphereon__did-auth-siop@0.15.1-next.4.patch",
- "@credo-ts/openid4vc@0.5.10-alpha-20240801095850": "patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch"
+ "@credo-ts/openid4vc@0.5.10-alpha-20240801095850": "patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch",
+ "@credo-ts/core@0.5.10-alpha-20240801095850": "patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch"
}
}
}
diff --git a/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
new file mode 100644
index 0000000..d4dfe4c
--- /dev/null
+++ b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
@@ -0,0 +1,54 @@
+diff --git a/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts b/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
+index de5fe62881d049c4030125e0a4cc8ca38de41be9..1c1a48e75f081f2f52bddd0a970544e7438c77f2 100644
+--- a/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
++++ b/build/modules/sd-jwt-vc/SdJwtVcOptions.d.ts
+@@ -90,4 +90,5 @@ export type SdJwtVcVerifyOptions = {
+ nonce: string;
+ };
+ requiredClaimKeys?: Array;
++ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ };
+diff --git a/build/modules/sd-jwt-vc/SdJwtVcService.js b/build/modules/sd-jwt-vc/SdJwtVcService.js
+index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2a8fae452 100644
+--- a/build/modules/sd-jwt-vc/SdJwtVcService.js
++++ b/build/modules/sd-jwt-vc/SdJwtVcService.js
+@@ -112,7 +112,7 @@ let SdJwtVcService = class SdJwtVcService {
+ throw new SdJwtVcError_1.SdJwtVcError(`The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate.`);
+ }
+ }
+- async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys }) {
++ async verify(agentContext, { compactSdJwtVc, keyBinding, requiredClaimKeys, verifyHs256Callback }) {
+ const sdjwt = new sd_jwt_vc_1.SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext));
+ const verificationResult = {
+ isValid: false,
+@@ -142,7 +142,7 @@ let SdJwtVcService = class SdJwtVcService {
+ const holderBinding = this.parseHolderBindingFromCredential(sdJwtVc);
+ const holder = holderBinding ? await this.extractKeyFromHolderBinding(agentContext, holderBinding) : undefined;
+ sdjwt.config({
+- verifier: this.verifier(agentContext, issuer.key),
++ verifier: this.verifier(agentContext, issuer.key, verifyHs256Callback),
+ kbVerifier: holder ? this.verifier(agentContext, holder.key) : undefined,
+ });
+ const requiredKeys = requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'];
+@@ -261,11 +261,20 @@ let SdJwtVcService = class SdJwtVcService {
+ /**
+ * @todo validate the JWT header (alg)
+ */
+- verifier(agentContext, key) {
++ verifier(agentContext, key, verifyHs256Callback) {
+ return async (message, signatureBase64Url) => {
+ if (!key) {
+ throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
+ }
++
++ const [header] = message.split(".")
++ if(header) {
++ const parsedHeader = utils_2.TypedArrayEncoder.fromBase64(header).toString()
++ const { alg } = JSON.parse(parsedHeader)
++ if(alg === "HS256") {
++ return await verifyHs256Callback(key, new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
++ }
++ }
+ return await agentContext.wallet.verify({
+ signature: utils_2.TypedArrayEncoder.fromBase64(signatureBase64Url),
+ key,
diff --git a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index a6d444b..f57d424 100644
--- a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -1,3 +1,106 @@
+diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa1aba251e 100644
+--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
++++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+@@ -81,13 +81,16 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ first: 10000,
+ meta: 'OpenId4VcSiopVerifierService.createAuthorizationRequest',
+ }), (0, rxjs_1.map)((e) => e.payload.record)));
++ console.log(JSON.stringify(options, null ,2))
+ const authorizationRequest = await relyingParty.createAuthorizationRequest({
+ correlationId,
+ nonce,
+ state,
+ requestByReferenceURI: hostedAuthorizationRequestUri,
+ jwtIssuer,
++ additionalPayloadClaims: options.additionalPayloadClaims
+ });
++ console.log(JSON.stringify(authorizationRequest, null, 2))
+ // NOTE: it's not possible to set the uri scheme when using the RP to create an auth request, only lower level
+ // functions allow this. So we need to replace the uri scheme manually.
+ let authorizationRequestUri = (await authorizationRequest.uri()).encodedUri;
+@@ -144,6 +147,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ presentationVerificationCallback: this.getPresentationVerificationCallback(agentContext, {
+ nonce: requestNonce,
+ audience: requestClientId,
++ verifyHs256Callback: options.verifyHs256Callback
+ }),
+ },
+ });
+@@ -335,6 +339,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+ keyBinding: {
+ audience: options.audience,
+ nonce: options.nonce,
++ verifyHs256Callback: options.verifyHs256Callback
+ },
+ });
+ isValid = verificationResult.verification.isValid;
+diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54bc919fad7 100644
+--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
++++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+@@ -18,12 +18,15 @@ export interface OpenId4VcSiopCreateAuthorizationRequestOptions {
+ presentationExchange?: {
+ definition: DifPresentationExchangeDefinitionV2;
+ };
++
++ additionalPayloadClaims?: Record
+ }
+ export interface OpenId4VcSiopVerifyAuthorizationResponseOptions {
+ /**
+ * The authorization response received from the OpenID Provider (OP).
+ */
+ authorizationResponse: OpenId4VcSiopAuthorizationResponsePayload;
++ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ }
+ export interface OpenId4VcSiopCreateAuthorizationRequestReturn {
+ authorizationRequest: string;
+diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+index baffab5ef01cffde68fefefdd89f561f75b59032..c57f258de062a64cf5252f458bd5e6b279e42a79 100644
+--- a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
++++ b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+@@ -7,5 +7,6 @@ export interface OpenId4VcSiopAuthorizationEndpointConfig {
+ * @default /authorize
+ */
+ endpointPath: string;
++ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
+ }
+ export declare function configureAuthorizationEndpoint(router: Router, config: OpenId4VcSiopAuthorizationEndpointConfig): void;
+diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.js b/build/openid4vc-verifier/router/authorizationEndpoint.js
+index a523a1e668863929f49b50fea6786e42955e5149..cc156969b3ca6b7e853a62a9a6f4f5ebfb182c03 100644
+--- a/build/openid4vc-verifier/router/authorizationEndpoint.js
++++ b/build/openid4vc-verifier/router/authorizationEndpoint.js
+@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.configureAuthorizationEndpoint = configureAuthorizationEndpoint;
+ const router_1 = require("../../shared/router");
+ const OpenId4VcSiopVerifierService_1 = require("../OpenId4VcSiopVerifierService");
++const core_1 = require("@credo-ts/core");
++
+ function configureAuthorizationEndpoint(router, config) {
+ router.post(config.endpointPath, async (request, response, next) => {
+ const { agentContext, verifier } = (0, router_1.getRequestContext)(request);
+@@ -16,6 +18,13 @@ function configureAuthorizationEndpoint(router, config) {
+ authorizationResponse,
+ verifierId: verifier.verifierId,
+ });
++ let verifyHs256Callback = undefined
++ const parsedAuthorizationRequest = core_1.Jwt.fromSerializedJwt(verificationSession.authorizationRequestJwt)
++ const rpEphPub = parsedAuthorizationRequest.payload.additionalClaims.rp_eph_pub
++ if(rpEphPub !== null && rpEphPub !== void 0) {
++ verifyHs256Callback = config.verifyHs256Callback(agentContext, rpEphPub.jwk)
++ }
++
+ if (!verificationSession) {
+ agentContext.config.logger.warn(`No verification session found for incoming authorization response for verifier ${verifier.verifierId}`);
+ return (0, router_1.sendErrorResponse)(response, agentContext.config.logger, 404, 'invalid_request', null);
+@@ -23,6 +32,7 @@ function configureAuthorizationEndpoint(router, config) {
+ await openId4VcVerifierService.verifyAuthorizationResponse(agentContext, {
+ authorizationResponse: request.body,
+ verificationSession,
++ verifyHs256Callback: verifyHs256Callback
+ });
+ response.status(200).send();
+ }
diff --git a/build/shared/utils.js b/build/shared/utils.js
index 36037ab98cf59f64b56d107aef9b2eb02b491c60..7eccc2ab99d396366299138df8d99376ca35696c 100644
--- a/build/shared/utils.js
diff --git a/agent/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch b/agent/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
index 2f02816..b35c651 100644
--- a/agent/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
+++ b/agent/patches/@sphereon__did-auth-siop@0.15.1-next.4.patch
@@ -1,5 +1,29 @@
+diff --git a/dist/request-object/Payload.js b/dist/request-object/Payload.js
+index f270cc5dd7ca4da9f93a16a400297ec8be9da936..d15b1ff70a68fdcd566707032e08e200cad3bb0f 100644
+--- a/dist/request-object/Payload.js
++++ b/dist/request-object/Payload.js
+@@ -35,12 +35,17 @@ const createRequestObjectPayload = (opts) => __awaiter(void 0, void 0, void 0, f
+ const nbf = (_e = payload.nbf) !== null && _e !== void 0 ? _e : iat;
+ const exp = (_f = payload.exp) !== null && _f !== void 0 ? _f : iat + validInSec;
+ const jti = (_g = payload.jti) !== null && _g !== void 0 ? _g : (0, uuid_1.v4)();
+- return (0, helpers_1.removeNullUndefined)(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ response_type: (_h = payload.response_type) !== null && _h !== void 0 ? _h : types_1.ResponseType.ID_TOKEN, scope: (_j = payload.scope) !== null && _j !== void 0 ? _j : types_1.Scope.OPENID,
++ const obj = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ response_type: (_h = payload.response_type) !== null && _h !== void 0 ? _h : types_1.ResponseType.ID_TOKEN, scope: (_j = payload.scope) !== null && _j !== void 0 ? _j : types_1.Scope.OPENID,
+ //TODO implement /.well-known/openid-federation support in the OP side to resolve the client_id (URL) and retrieve the metadata
+ client_id: clientId, client_id_scheme: opts.requestObject.payload.client_id_scheme }, (payload.redirect_uri && { redirect_uri: payload.redirect_uri })), (payload.response_uri && { response_uri: payload.response_uri })), { response_mode: (_k = payload.response_mode) !== null && _k !== void 0 ? _k : types_1.ResponseMode.DIRECT_POST }), (payload.id_token_hint && { id_token_hint: payload.id_token_hint })), { registration_uri: registration.clientMetadataOpts.reference_uri, nonce: (0, helpers_1.getNonce)(state, payload.nonce), state }), registration.payload), { claims, presentation_definition_uri: payload.presentation_definition_uri, presentation_definition: payload.presentation_definition, iat,
+ nbf,
+ exp,
+- jti }));
++ jti })
++
++ if(opts.additionalPayloadClaims !== null && opts.additionalPayloadClaims !== void 0) {
++ Object.assign(obj, opts.additionalPayloadClaims)
++ }
++ return (0, helpers_1.removeNullUndefined)(obj);
+ });
+ exports.createRequestObjectPayload = createRequestObjectPayload;
+ const assertValidRequestObjectPayload = (verPayload) => {
diff --git a/dist/request-object/RequestObject.js b/dist/request-object/RequestObject.js
-index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..359f45a7c4fc49fce2a8b67f2b9f596a1440b79c 100644
+index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..afb5ac1b1670566c55617deb3e811f0675a7d5ef 100644
--- a/dist/request-object/RequestObject.js
+++ b/dist/request-object/RequestObject.js
@@ -92,7 +92,6 @@ class RequestObject {
@@ -10,6 +34,20 @@ index dc3a12be88d9ecf399433b42cbc93b46bccfef0d..359f45a7c4fc49fce2a8b67f2b9f596a
this.payload.client_id_scheme = jwtIssuer.clientIdScheme;
const header = { x5c: jwtIssuer.x5c, typ: 'JWT' };
this.jwt = yield this.opts.createJwtCallback(jwtIssuer, { header, payload: this.payload });
+diff --git a/dist/rp/RP.js b/dist/rp/RP.js
+index 92b27cbb69e2a6d44a7cf08b6f63326424fad1ce..06469a6f216c07f50649b98c63576fdf2c5448e7 100644
+--- a/dist/rp/RP.js
++++ b/dist/rp/RP.js
+@@ -218,6 +218,9 @@ class RP {
+ newOpts.requestObject.payload.claims = Object.assign(Object.assign({}, newOpts.requestObject.payload.claims), claimsWithTarget.propertyValue);
+ }
+ }
++ if(opts.additionalPayloadClaims !== null && opts.additionalPayloadClaims !== void 0) {
++ newOpts.additionalPayloadClaims = opts.additionalPayloadClaims
++ }
+ return newOpts;
+ }
+ newVerifyAuthorizationResponseOpts(authorizationResponse, opts) {
diff --git a/dist/types/JwtVerifier.js b/dist/types/JwtVerifier.js
index 90ecefe0c7b0859b05af643e5d7d88b271821e03..78eb1a0f24e79bead215b0ce507c17d230792791 100644
--- a/dist/types/JwtVerifier.js
diff --git a/app/components/VerifyTab.tsx b/app/components/VerifyTab.tsx
index 3d3a61c..6eb62d0 100644
--- a/app/components/VerifyTab.tsx
+++ b/app/components/VerifyTab.tsx
@@ -7,7 +7,7 @@ export function VerifyTab() {
return await createRequest({
presentationDefinition: {
id: crypto.randomUUID(),
- name: 'PID Credential request for C',
+ name: "PID Credential Request C/B'",
input_descriptors: [
{
id: crypto.randomUUID(),
@@ -51,7 +51,7 @@ export function VerifyTab() {
},
],
},
- name: 'PID Name',
+ name: 'Bank Account Identity Verification',
purpose: 'To open a bank account we need to verify your identity.',
},
],
diff --git a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index d3d830c..f57d424 100644
--- a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -87,7 +87,7 @@ index a523a1e668863929f49b50fea6786e42955e5149..cc156969b3ca6b7e853a62a9a6f4f5eb
+ const parsedAuthorizationRequest = core_1.Jwt.fromSerializedJwt(verificationSession.authorizationRequestJwt)
+ const rpEphPub = parsedAuthorizationRequest.payload.additionalClaims.rp_eph_pub
+ if(rpEphPub !== null && rpEphPub !== void 0) {
-+ verifyHs256Callback = options.verifyHs256Callback(agentContext, rpEphPub.jwk)
++ verifyHs256Callback = config.verifyHs256Callback(agentContext, rpEphPub.jwk)
+ }
+
if (!verificationSession) {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0d6f2b5..6544bde 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,7 +9,7 @@ patchedDependencies:
hash: l4twkbbkkn42qavc23ivocq3ry
path: patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
'@credo-ts/openid4vc@0.5.10-alpha-20240801095850':
- hash: owfxcg6cf2dpbokdjdnq226t2y
+ hash: sadesmpnu2t64txibqqipssq5a
path: patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
'@sphereon/did-auth-siop@0.15.1-next.4':
hash: mzeq3zftd7djamf7faz4ef6yam
@@ -36,7 +36,7 @@ importers:
version: 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/openid4vc':
specifier: 0.5.10-alpha-20240801095850
- version: 0.5.10-alpha-20240801095850(patch_hash=owfxcg6cf2dpbokdjdnq226t2y)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ version: 0.5.10-alpha-20240801095850(patch_hash=sadesmpnu2t64txibqqipssq5a)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@hyperledger/aries-askar-nodejs':
specifier: ^0.2.3
version: 0.2.3
@@ -7255,7 +7255,7 @@ snapshots:
- utf-8-validate
- web-streams-polyfill
- '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=owfxcg6cf2dpbokdjdnq226t2y)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
+ '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=sadesmpnu2t64txibqqipssq5a)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
'@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@sphereon/did-auth-siop': 0.15.1-next.4(patch_hash=mzeq3zftd7djamf7faz4ef6yam)
From 09615bb5740d95fecc54e7d899bb7c82142f106f Mon Sep 17 00:00:00 2001
From: Timo Glastra
Date: Mon, 26 Aug 2024 16:06:16 +0200
Subject: [PATCH 023/172] update title
Signed-off-by: Timo Glastra
---
app/app/layout.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/app/layout.tsx b/app/app/layout.tsx
index f4b1b77..c7def59 100644
--- a/app/app/layout.tsx
+++ b/app/app/layout.tsx
@@ -5,7 +5,7 @@ import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
- title: 'OpenID4VC Playground',
+ title: 'Animo Funke Playground',
description: 'By Animo',
}
From 8c4fc9684881141f4c2280e995790f1b4faaa4d8 Mon Sep 17 00:00:00 2001
From: Berend Sliedrecht
Date: Mon, 26 Aug 2024 15:26:09 +0200
Subject: [PATCH 024/172] feat: b prime presentation working
Signed-off-by: Berend Sliedrecht
---
...ts__core@0.5.10-alpha-20240801095850.patch | 41 +++++++++++---
...penid4vc@0.5.10-alpha-20240801095850.patch | 17 ++----
agent/src/agent.ts | 2 +-
agent/src/verifyHs256Callback.ts | 56 ++++++++++++++-----
app/components/VerifyTab.tsx | 4 +-
app/components/main.tsx | 17 +-----
...ts__core@0.5.10-alpha-20240801095850.patch | 41 +++++++++++---
...penid4vc@0.5.10-alpha-20240801095850.patch | 31 ++++------
pnpm-lock.yaml | 24 ++++----
9 files changed, 137 insertions(+), 96 deletions(-)
diff --git a/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
index d4dfe4c..f09bb70 100644
--- a/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
+++ b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
@@ -9,7 +9,7 @@ index de5fe62881d049c4030125e0a4cc8ca38de41be9..1c1a48e75f081f2f52bddd0a970544e7
+ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
};
diff --git a/build/modules/sd-jwt-vc/SdJwtVcService.js b/build/modules/sd-jwt-vc/SdJwtVcService.js
-index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2a8fae452 100644
+index add911d9570edcad9945c4819bfc56cf6f715201..76bc45a0ac804a8d8f9318fc2847caddb753781e 100644
--- a/build/modules/sd-jwt-vc/SdJwtVcService.js
+++ b/build/modules/sd-jwt-vc/SdJwtVcService.js
@@ -112,7 +112,7 @@ let SdJwtVcService = class SdJwtVcService {
@@ -30,25 +30,48 @@ index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2
kbVerifier: holder ? this.verifier(agentContext, holder.key) : undefined,
});
const requiredKeys = requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'];
-@@ -261,11 +261,20 @@ let SdJwtVcService = class SdJwtVcService {
+@@ -261,10 +261,19 @@ let SdJwtVcService = class SdJwtVcService {
/**
* @todo validate the JWT header (alg)
*/
- verifier(agentContext, key) {
+ verifier(agentContext, key, verifyHs256Callback) {
return async (message, signatureBase64Url) => {
- if (!key) {
- throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
- }
+- if (!key) {
+- throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
++ if (!key && !verifyHs256Callback) {
++ throw new SdJwtVcError_1.SdJwtVcError('The public key, or verifyHs256Callback, used to verify the signature is missing');
++ }
+
+ const [header] = message.split(".")
+ if(header) {
+ const parsedHeader = utils_2.TypedArrayEncoder.fromBase64(header).toString()
+ const { alg } = JSON.parse(parsedHeader)
-+ if(alg === "HS256") {
-+ return await verifyHs256Callback(key, new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
++ if(alg === "DVS-P256-SHA2256-HS256") {
++ return await verifyHs256Callback(new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
+ }
-+ }
+ }
return await agentContext.wallet.verify({
signature: utils_2.TypedArrayEncoder.fromBase64(signatureBase64Url),
- key,
+@@ -274,6 +283,9 @@ let SdJwtVcService = class SdJwtVcService {
+ };
+ }
+ async extractKeyFromIssuer(agentContext, issuer) {
++ if(issuer.method === 'http') {
++ return { key: '' }
++ }
+ if (issuer.method === 'did') {
+ const parsedDid = (0, dids_1.parseDid)(issuer.didUrl);
+ if (!parsedDid.fragment) {
+@@ -373,6 +385,11 @@ let SdJwtVcService = class SdJwtVcService {
+ didUrl,
+ };
+ }
++ if(iss.startsWith('http')) {
++ return {
++ method: 'http'
++ }
++ }
+ throw new SdJwtVcError_1.SdJwtVcError("Unsupported 'iss' value. Only did is supported at the moment.");
+ }
+ parseHolderBindingFromCredential(sdJwtVc) {
diff --git a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index f57d424..baad778 100644
--- a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -1,25 +1,16 @@
diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
-index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa1aba251e 100644
+index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..5cd025a34d71622bb6a934f99457df9ab9fe4da0 100644
--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
-@@ -81,13 +81,16 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
- first: 10000,
- meta: 'OpenId4VcSiopVerifierService.createAuthorizationRequest',
- }), (0, rxjs_1.map)((e) => e.payload.record)));
-+ console.log(JSON.stringify(options, null ,2))
- const authorizationRequest = await relyingParty.createAuthorizationRequest({
- correlationId,
- nonce,
+@@ -87,6 +87,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
state,
requestByReferenceURI: hostedAuthorizationRequestUri,
jwtIssuer,
+ additionalPayloadClaims: options.additionalPayloadClaims
});
-+ console.log(JSON.stringify(authorizationRequest, null, 2))
// NOTE: it's not possible to set the uri scheme when using the RP to create an auth request, only lower level
// functions allow this. So we need to replace the uri scheme manually.
- let authorizationRequestUri = (await authorizationRequest.uri()).encodedUri;
-@@ -144,6 +147,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+@@ -144,6 +145,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
presentationVerificationCallback: this.getPresentationVerificationCallback(agentContext, {
nonce: requestNonce,
audience: requestClientId,
@@ -27,7 +18,7 @@ index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa
}),
},
});
-@@ -335,6 +339,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+@@ -335,6 +337,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
keyBinding: {
audience: options.audience,
nonce: options.nonce,
diff --git a/agent/src/agent.ts b/agent/src/agent.ts
index d14729d..2f10e2d 100644
--- a/agent/src/agent.ts
+++ b/agent/src/agent.ts
@@ -1,5 +1,5 @@
import { AskarModule } from '@credo-ts/askar'
-import { Agent, ConsoleLogger, Key, LogLevel, X509Module, joinUriParts } from '@credo-ts/core'
+import { Agent, ConsoleLogger, LogLevel, X509Module, joinUriParts } from '@credo-ts/core'
import { agentDependencies } from '@credo-ts/node'
import { OpenId4VcHolderModule, OpenId4VcIssuerModule, OpenId4VcVerifierModule } from '@credo-ts/openid4vc'
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'
diff --git a/agent/src/verifyHs256Callback.ts b/agent/src/verifyHs256Callback.ts
index 6ec38d0..2141f64 100644
--- a/agent/src/verifyHs256Callback.ts
+++ b/agent/src/verifyHs256Callback.ts
@@ -1,4 +1,4 @@
-import { createECDH, createHmac } from 'crypto'
+import { createECDH, createHmac, hkdfSync } from 'crypto'
import { assertAskarWallet } from '@credo-ts/askar/build/utils/assertAskarWallet'
import {
type AgentContext,
@@ -7,23 +7,22 @@ import {
KeyType,
type P256Jwk,
TypedArrayEncoder,
+ X509Service,
getJwkFromJson,
getJwkFromKey,
} from '@credo-ts/core'
-import { Key as AskarKey, Jwk, type JwkProps } from '@hyperledger/aries-askar-nodejs'
const createMac = (privateKey: Buffer, publicKey: Buffer, message: Buffer) => {
+ const info = Buffer.from('DVS-1')
+ const salt = Buffer.from('')
+
const ecdh = createECDH('prime256v1')
- ecdh.setPrivateKey(privateKey)
- const sharedSecret = ecdh.computeSecret(publicKey)
+ ecdh.setPrivateKey(Buffer.from(privateKey))
+ const dh = ecdh.computeSecret(publicKey)
- // Spec does not define SHA-256, can be a cause if the mac is invalid
- return createHmac('sha256', sharedSecret).update(message).digest()
-}
+ const derivedSecret = hkdfSync('sha256', dh, salt, info, 32)
-const getCredoKeyFromJwk = (jwk: Record): Key => {
- const askarKey = AskarKey.fromJwk({ jwk: new Jwk(jwk as JwkProps) })
- return new Key(askarKey.publicBytes, KeyType.P256)
+ return createHmac('sha256', Buffer.from(derivedSecret)).update(message).digest()
}
const getPrivateKeyFromAskar = async (context: AgentContext, keyId: string) => {
@@ -42,7 +41,7 @@ const getPrivateKeyFromAskar = async (context: AgentContext, keyId: string) => {
}
const getPublicKeyFromJwk = async (jwk: P256Jwk) => {
- const key = Buffer.concat([Buffer.from([0x04]), Buffer.from(jwk.x, 'base64'), Buffer.from(jwk.y, 'base64')])
+ const key = Buffer.concat([Buffer.from([0x04]), Buffer.from(jwk.x, 'base64url'), Buffer.from(jwk.y, 'base64url')])
return key
}
@@ -68,21 +67,48 @@ const diffieHellmanKeyExchangeAndVerify = async ({
return mac.toString('hex') === ourMac
}
+// https://demo.pid-issuer.bundesdruckerei.de
+const bdrPidIssuerCertificate = `-----BEGIN CERTIFICATE-----
+MIICdDCCAhugAwIBAgIBAjAKBggqhkjOPQQDAjCBiDELMAkGA1UEBhMCREUxDzANBgNVBAcMBkJlcmxpbjEdMBsGA1UECgwUQnVuZGVzZHJ1Y2tlcmVpIEdtYkgxETAPBgNVBAsMCFQgQ1MgSURFMTYwNAYDVQQDDC1TUFJJTkQgRnVua2UgRVVESSBXYWxsZXQgUHJvdG90eXBlIElzc3VpbmcgQ0EwHhcNMjQwNTMxMDgxMzE3WhcNMjUwNzA1MDgxMzE3WjBsMQswCQYDVQQGEwJERTEdMBsGA1UECgwUQnVuZGVzZHJ1Y2tlcmVpIEdtYkgxCjAIBgNVBAsMAUkxMjAwBgNVBAMMKVNQUklORCBGdW5rZSBFVURJIFdhbGxldCBQcm90b3R5cGUgSXNzdWVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOFBq4YMKg4w5fTifsytwBuJf/7E7VhRPXiNm52S3q1ETIgBdXyDK3kVxGxgeHPivLP3uuMvS6iDEc7qMxmvduKOBkDCBjTAdBgNVHQ4EFgQUiPhCkLErDXPLW2/J0WVeghyw+mIwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwLQYDVR0RBCYwJIIiZGVtby5waWQtaXNzdWVyLmJ1bmRlc2RydWNrZXJlaS5kZTAfBgNVHSMEGDAWgBTUVhjAiTjoDliEGMl2Yr+ru8WQvjAKBggqhkjOPQQDAgNHADBEAiAbf5TzkcQzhfWoIoyi1VN7d8I9BsFKm1MWluRph2byGQIgKYkdrNf2xXPjVSbjW/U/5S5vAEC5XxcOanusOBroBbU=
+-----END CERTIFICATE-----`
+
+const compressP256PublicKey = (uncompressed: Uint8Array): Uint8Array => {
+ if (uncompressed.length !== 65 || uncompressed[0] !== 0x04) {
+ throw new Error('Invalid uncompressed P-256 public key')
+ }
+
+ const x = uncompressed.slice(1, 33) // Extract x coordinate (32 bytes)
+ const y = uncompressed.slice(33, 65) // Extract y coordinate (32 bytes)
+
+ // Determine the prefix: 0x02 if y is even, 0x03 if y is odd
+ const prefix = y[y.length - 1] % 2 === 0 ? 0x02 : 0x03
+
+ // Create the compressed key by concatenating the prefix with x
+ const compressed = Buffer.concat([Buffer.from([prefix]), x])
+
+ return new Uint8Array(compressed)
+}
-export const verifyHs256Callback =
- (context: AgentContext, verifierKey: Record) =>
- async (key: Key, data: Uint8Array, signatureBase64Url: string) => {
+export const verifyHs256Callback = (context: AgentContext, verifierKey: Record) => {
+ const cert = X509Service.parseCertificate(context, {
+ encodedCertificate: bdrPidIssuerCertificate,
+ })
+ return async (data: Uint8Array, signatureBase64Url: string) => {
+ console.error('arrived!')
const mac = TypedArrayEncoder.fromBase64(signatureBase64Url)
const jwk = getJwkFromJson(verifierKey as JwkJson)
+ const theirKeyBytes = compressP256PublicKey(new Uint8Array(cert.publicKey.publicKey))
+
const isValid = await diffieHellmanKeyExchangeAndVerify({
mac: Buffer.from(mac),
message: Buffer.from(data),
myKey: jwk.key,
- theirKey: getJwkFromKey(key) as P256Jwk,
+ theirKey: getJwkFromKey(new Key(theirKeyBytes, KeyType.P256)) as P256Jwk,
context,
})
return isValid
}
+}
diff --git a/app/components/VerifyTab.tsx b/app/components/VerifyTab.tsx
index 6eb62d0..6eaac6e 100644
--- a/app/components/VerifyTab.tsx
+++ b/app/components/VerifyTab.tsx
@@ -2,7 +2,7 @@ import { createRequest, getIssuer } from '../lib/api'
import { VerifyBlock } from './VerifyBlock'
export function VerifyTab() {
- const createCRequest = async () => {
+ const createRequestForVerification = async () => {
const issuer = (await getIssuer()).availableX509Certificates[0]
return await createRequest({
presentationDefinition: {
@@ -63,7 +63,7 @@ export function VerifyTab() {
<>
>
)
diff --git a/app/components/main.tsx b/app/components/main.tsx
index a2539b4..427c6f2 100644
--- a/app/components/main.tsx
+++ b/app/components/main.tsx
@@ -1,11 +1,6 @@
'use client'
-/**
- * This code was generated by v0 by Vercel.
- * @see https://v0.dev/t/yoUa0S8t4oT
- */
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
-import { IssueTab } from './IssueTab'
-import { ReceiveTab } from './ReceiveTab'
import { VerifyTab } from './VerifyTab'
export function Main() {
@@ -29,18 +24,10 @@ export function Main() {
Playground
-
+
- Issue
- Receive
Verify
-
-
-
-
-
-
diff --git a/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch b/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
index d4dfe4c..63af959 100644
--- a/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
+++ b/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
@@ -9,7 +9,7 @@ index de5fe62881d049c4030125e0a4cc8ca38de41be9..1c1a48e75f081f2f52bddd0a970544e7
+ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
};
diff --git a/build/modules/sd-jwt-vc/SdJwtVcService.js b/build/modules/sd-jwt-vc/SdJwtVcService.js
-index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2a8fae452 100644
+index add911d9570edcad9945c4819bfc56cf6f715201..76bc45a0ac804a8d8f9318fc2847caddb753781e 100644
--- a/build/modules/sd-jwt-vc/SdJwtVcService.js
+++ b/build/modules/sd-jwt-vc/SdJwtVcService.js
@@ -112,7 +112,7 @@ let SdJwtVcService = class SdJwtVcService {
@@ -30,25 +30,48 @@ index add911d9570edcad9945c4819bfc56cf6f715201..77a2279f8f42525bfcf11897b0b2f9e2
kbVerifier: holder ? this.verifier(agentContext, holder.key) : undefined,
});
const requiredKeys = requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'];
-@@ -261,11 +261,20 @@ let SdJwtVcService = class SdJwtVcService {
+@@ -261,10 +261,19 @@ let SdJwtVcService = class SdJwtVcService {
/**
* @todo validate the JWT header (alg)
*/
- verifier(agentContext, key) {
+ verifier(agentContext, key, verifyHs256Callback) {
return async (message, signatureBase64Url) => {
- if (!key) {
- throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
- }
+- if (!key) {
+- throw new SdJwtVcError_1.SdJwtVcError('The public key used to verify the signature is missing');
++ if (!key && !verifyHs256Callback) {
++ throw new SdJwtVcError_1.SdJwtVcError('The public key, or verifyHs256Callback, used to verify the signature is missing');
++ }
+
+ const [header] = message.split(".")
+ if(header) {
+ const parsedHeader = utils_2.TypedArrayEncoder.fromBase64(header).toString()
+ const { alg } = JSON.parse(parsedHeader)
-+ if(alg === "HS256") {
-+ return await verifyHs256Callback(key, new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
++ if(alg === "DVS-P256-SHA256-HS256") {
++ return await verifyHs256Callback(new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
+ }
-+ }
+ }
return await agentContext.wallet.verify({
signature: utils_2.TypedArrayEncoder.fromBase64(signatureBase64Url),
- key,
+@@ -274,6 +283,9 @@ let SdJwtVcService = class SdJwtVcService {
+ };
+ }
+ async extractKeyFromIssuer(agentContext, issuer) {
++ if(issuer.method === 'http') {
++ return { key: '' }
++ }
+ if (issuer.method === 'did') {
+ const parsedDid = (0, dids_1.parseDid)(issuer.didUrl);
+ if (!parsedDid.fragment) {
+@@ -373,6 +385,11 @@ let SdJwtVcService = class SdJwtVcService {
+ didUrl,
+ };
+ }
++ if(iss.startsWith('http')) {
++ return {
++ method: 'http'
++ }
++ }
+ throw new SdJwtVcError_1.SdJwtVcError("Unsupported 'iss' value. Only did is supported at the moment.");
+ }
+ parseHolderBindingFromCredential(sdJwtVc) {
diff --git a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index f57d424..b8e5848 100644
--- a/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -1,25 +1,16 @@
diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
-index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa1aba251e 100644
+index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..ee9bb2b30b132a8f29672ae84d2d241673895948 100644
--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
-@@ -81,13 +81,16 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
- first: 10000,
- meta: 'OpenId4VcSiopVerifierService.createAuthorizationRequest',
- }), (0, rxjs_1.map)((e) => e.payload.record)));
-+ console.log(JSON.stringify(options, null ,2))
- const authorizationRequest = await relyingParty.createAuthorizationRequest({
- correlationId,
- nonce,
+@@ -87,6 +87,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
state,
requestByReferenceURI: hostedAuthorizationRequestUri,
jwtIssuer,
+ additionalPayloadClaims: options.additionalPayloadClaims
});
-+ console.log(JSON.stringify(authorizationRequest, null, 2))
// NOTE: it's not possible to set the uri scheme when using the RP to create an auth request, only lower level
// functions allow this. So we need to replace the uri scheme manually.
- let authorizationRequestUri = (await authorizationRequest.uri()).encodedUri;
-@@ -144,6 +147,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
+@@ -144,6 +145,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
presentationVerificationCallback: this.getPresentationVerificationCallback(agentContext, {
nonce: requestNonce,
audience: requestClientId,
@@ -27,16 +18,16 @@ index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..606d46ca8f48281b6f5248b33e5e9baa
}),
},
});
-@@ -335,6 +339,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
- keyBinding: {
+@@ -336,6 +338,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
audience: options.audience,
nonce: options.nonce,
-+ verifyHs256Callback: options.verifyHs256Callback
},
++ verifyHs256Callback: options.verifyHs256Callback
});
isValid = verificationResult.verification.isValid;
+ }
diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
-index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54bc919fad7 100644
+index 5abfb1bc5710849f656085593c77f3ab3898e4b7..a8325ea21d0e44b148be522931af503218333b50 100644
--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
@@ -18,12 +18,15 @@ export interface OpenId4VcSiopCreateAuthorizationRequestOptions {
@@ -51,23 +42,23 @@ index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54b
* The authorization response received from the OpenID Provider (OP).
*/
authorizationResponse: OpenId4VcSiopAuthorizationResponsePayload;
-+ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
++ verifyHs256Callback?: (data: Uint8Array, signatureBase64Url: string) => Promise
}
export interface OpenId4VcSiopCreateAuthorizationRequestReturn {
authorizationRequest: string;
diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
-index baffab5ef01cffde68fefefdd89f561f75b59032..c57f258de062a64cf5252f458bd5e6b279e42a79 100644
+index baffab5ef01cffde68fefefdd89f561f75b59032..bd46ce861b2141c0a7b1f8b6b3203b87eb3ab857 100644
--- a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+++ b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
@@ -7,5 +7,6 @@ export interface OpenId4VcSiopAuthorizationEndpointConfig {
* @default /authorize
*/
endpointPath: string;
-+ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
++ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (data: Uint8Array, signatureBase64Url: string) => Promise
}
export declare function configureAuthorizationEndpoint(router: Router, config: OpenId4VcSiopAuthorizationEndpointConfig): void;
diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.js b/build/openid4vc-verifier/router/authorizationEndpoint.js
-index a523a1e668863929f49b50fea6786e42955e5149..cc156969b3ca6b7e853a62a9a6f4f5ebfb182c03 100644
+index a523a1e668863929f49b50fea6786e42955e5149..f0ec69e858ad46d47bdbcbdced62103fa4469af3 100644
--- a/build/openid4vc-verifier/router/authorizationEndpoint.js
+++ b/build/openid4vc-verifier/router/authorizationEndpoint.js
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6544bde..a4c2ae5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -6,10 +6,10 @@ settings:
patchedDependencies:
'@credo-ts/core@0.5.10-alpha-20240801095850':
- hash: l4twkbbkkn42qavc23ivocq3ry
+ hash: ppnx2tn5rxkbexppgt3az3cgw4
path: patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
'@credo-ts/openid4vc@0.5.10-alpha-20240801095850':
- hash: sadesmpnu2t64txibqqipssq5a
+ hash: tblyokdb47ihudwgv7lz4njqkm
path: patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
'@sphereon/did-auth-siop@0.15.1-next.4':
hash: mzeq3zftd7djamf7faz4ef6yam
@@ -30,13 +30,13 @@ importers:
version: 0.5.10-alpha-20240801095850(@hyperledger/aries-askar-shared@0.2.3)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/core':
specifier: 0.5.10-alpha-20240801095850
- version: 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ version: 0.5.10-alpha-20240801095850(patch_hash=ppnx2tn5rxkbexppgt3az3cgw4)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/node':
specifier: 0.5.10-alpha-20240801095850
version: 0.5.10-alpha-20240801095850(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@credo-ts/openid4vc':
specifier: 0.5.10-alpha-20240801095850
- version: 0.5.10-alpha-20240801095850(patch_hash=sadesmpnu2t64txibqqipssq5a)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ version: 0.5.10-alpha-20240801095850(patch_hash=tblyokdb47ihudwgv7lz4njqkm)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@hyperledger/aries-askar-nodejs':
specifier: ^0.2.3
version: 0.2.3
@@ -7172,7 +7172,7 @@ snapshots:
'@credo-ts/askar@0.5.10-alpha-20240801095850(@hyperledger/aries-askar-shared@0.2.3)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
- '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=ppnx2tn5rxkbexppgt3az3cgw4)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@hyperledger/aries-askar-shared': 0.2.3
bn.js: 5.2.1
class-transformer: 0.5.1
@@ -7187,7 +7187,7 @@ snapshots:
- supports-color
- web-streams-polyfill
- '@credo-ts/core@0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
+ '@credo-ts/core@0.5.10-alpha-20240801095850(patch_hash=ppnx2tn5rxkbexppgt3az3cgw4)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
'@digitalcredentials/jsonld': 6.0.0(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@digitalcredentials/jsonld-signatures': 9.4.0(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
@@ -7241,7 +7241,7 @@ snapshots:
dependencies:
'@2060.io/ffi-napi': 4.0.9
'@2060.io/ref-napi': 3.0.6
- '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=ppnx2tn5rxkbexppgt3az3cgw4)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@types/express': 4.17.21
express: 4.18.2
ws: 8.16.0
@@ -7255,9 +7255,9 @@ snapshots:
- utf-8-validate
- web-streams-polyfill
- '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=sadesmpnu2t64txibqqipssq5a)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
+ '@credo-ts/openid4vc@0.5.10-alpha-20240801095850(patch_hash=tblyokdb47ihudwgv7lz4njqkm)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)':
dependencies:
- '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=l4twkbbkkn42qavc23ivocq3ry)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
+ '@credo-ts/core': 0.5.10-alpha-20240801095850(patch_hash=ppnx2tn5rxkbexppgt3az3cgw4)(expo@50.0.3(@babel/core@7.23.9)(@react-native/babel-preset@0.73.20(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))))(react-native@0.73.2(@babel/core@7.23.9)(@babel/preset-env@7.23.9(@babel/core@7.23.9))(react@18.2.0))(web-streams-polyfill@3.3.2)
'@sphereon/did-auth-siop': 0.15.1-next.4(patch_hash=mzeq3zftd7djamf7faz4ef6yam)
'@sphereon/oid4vci-client': 0.15.1-next.4
'@sphereon/oid4vci-common': 0.15.1-next.4
@@ -10395,7 +10395,7 @@ snapshots:
eslint: 8.56.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0)
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0)
eslint-plugin-react: 7.33.2(eslint@8.56.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0)
@@ -10419,7 +10419,7 @@ snapshots:
enhanced-resolve: 5.15.0
eslint: 8.56.0
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
fast-glob: 3.3.2
get-tsconfig: 4.7.2
is-core-module: 2.13.1
@@ -10441,7 +10441,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0):
+ eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
dependencies:
array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3
From 582bb4e921bb943070eea96bc2788e29c4d0ece8 Mon Sep 17 00:00:00 2001
From: Berend Sliedrecht
Date: Mon, 26 Aug 2024 16:48:36 +0200
Subject: [PATCH 025/172] fix: include patcjes
Signed-off-by: Berend Sliedrecht
---
...-ts__core@0.5.10-alpha-20240801095850.patch | 2 +-
...openid4vc@0.5.10-alpha-20240801095850.patch | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
index f09bb70..63af959 100644
--- a/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
+++ b/agent/patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch
@@ -47,7 +47,7 @@ index add911d9570edcad9945c4819bfc56cf6f715201..76bc45a0ac804a8d8f9318fc2847cadd
+ if(header) {
+ const parsedHeader = utils_2.TypedArrayEncoder.fromBase64(header).toString()
+ const { alg } = JSON.parse(parsedHeader)
-+ if(alg === "DVS-P256-SHA2256-HS256") {
++ if(alg === "DVS-P256-SHA256-HS256") {
+ return await verifyHs256Callback(new Uint8Array(utils_2.TypedArrayEncoder.fromString(message)), signatureBase64Url)
+ }
}
diff --git a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
index baad778..b8e5848 100644
--- a/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
+++ b/agent/patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
@@ -1,5 +1,5 @@
diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
-index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..5cd025a34d71622bb6a934f99457df9ab9fe4da0 100644
+index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..ee9bb2b30b132a8f29672ae84d2d241673895948 100644
--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
+++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierService.js
@@ -87,6 +87,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
@@ -18,16 +18,16 @@ index d6fd170fd937b0d8df047e6fb9b74636d6ee84ab..5cd025a34d71622bb6a934f99457df9a
}),
},
});
-@@ -335,6 +337,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
- keyBinding: {
+@@ -336,6 +338,7 @@ let OpenId4VcSiopVerifierService = class OpenId4VcSiopVerifierService {
audience: options.audience,
nonce: options.nonce,
-+ verifyHs256Callback: options.verifyHs256Callback
},
++ verifyHs256Callback: options.verifyHs256Callback
});
isValid = verificationResult.verification.isValid;
+ }
diff --git a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
-index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54bc919fad7 100644
+index 5abfb1bc5710849f656085593c77f3ab3898e4b7..a8325ea21d0e44b148be522931af503218333b50 100644
--- a/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
+++ b/build/openid4vc-verifier/OpenId4VcSiopVerifierServiceOptions.d.ts
@@ -18,12 +18,15 @@ export interface OpenId4VcSiopCreateAuthorizationRequestOptions {
@@ -42,23 +42,23 @@ index 5abfb1bc5710849f656085593c77f3ab3898e4b7..c514681426c8f63b2a076070287ea54b
* The authorization response received from the OpenID Provider (OP).
*/
authorizationResponse: OpenId4VcSiopAuthorizationResponsePayload;
-+ verifyHs256Callback?: (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
++ verifyHs256Callback?: (data: Uint8Array, signatureBase64Url: string) => Promise
}
export interface OpenId4VcSiopCreateAuthorizationRequestReturn {
authorizationRequest: string;
diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
-index baffab5ef01cffde68fefefdd89f561f75b59032..c57f258de062a64cf5252f458bd5e6b279e42a79 100644
+index baffab5ef01cffde68fefefdd89f561f75b59032..bd46ce861b2141c0a7b1f8b6b3203b87eb3ab857 100644
--- a/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
+++ b/build/openid4vc-verifier/router/authorizationEndpoint.d.ts
@@ -7,5 +7,6 @@ export interface OpenId4VcSiopAuthorizationEndpointConfig {
* @default /authorize
*/
endpointPath: string;
-+ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (key: Key, data: Uint8Array, signatureBase64Url: string) => Promise
++ verifyHs256Callback: (agentContext: AgentContext, rpEphPub: Record) => (data: Uint8Array, signatureBase64Url: string) => Promise
}
export declare function configureAuthorizationEndpoint(router: Router, config: OpenId4VcSiopAuthorizationEndpointConfig): void;
diff --git a/build/openid4vc-verifier/router/authorizationEndpoint.js b/build/openid4vc-verifier/router/authorizationEndpoint.js
-index a523a1e668863929f49b50fea6786e42955e5149..cc156969b3ca6b7e853a62a9a6f4f5ebfb182c03 100644
+index a523a1e668863929f49b50fea6786e42955e5149..f0ec69e858ad46d47bdbcbdced62103fa4469af3 100644
--- a/build/openid4vc-verifier/router/authorizationEndpoint.js
+++ b/build/openid4vc-verifier/router/authorizationEndpoint.js
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
From f1a8e15efd5e64f7d14488c99c183a8f89af7f84 Mon Sep 17 00:00:00 2001
From: Martin Auer
Date: Tue, 27 Aug 2024 12:12:17 +0200
Subject: [PATCH 026/172] feat: mdoc draft (#21)
---
README.md | 4 +-
agent/package.json | 19 +-
agent/sphereon-did-auth-siop-0.16.0.tgz | Bin 0 -> 853549 bytes
agent/src/constants.ts | 6 +-
agent/src/endpoints.ts | 46 +-
app/components/IssueTab.tsx | 32 +-
app/components/ReceiveTab.tsx | 24 +-
app/components/VerifyBlock.tsx | 101 +-
app/components/VerifyTab.tsx | 213 ++-
app/components/main.tsx | 10 +
package.json | 8 +-
..._core@0.5.11-pr-1996-20240826150533.patch} | 0
...penid4vc@0.5.10-alpha-20240801095850.patch | 142 --
...nid4vc@0.5.11-pr-1996-20240826150533.patch | 1572 +++++++++++++++++
... => @sphereon__did-auth-siop@0.16.0.patch} | 0
pnpm-lock.yaml | 1014 +++++++++--
sphereon-did-auth-siop-0.16.0.tgz | Bin 0 -> 853549 bytes
17 files changed, 2856 insertions(+), 335 deletions(-)
create mode 100644 agent/sphereon-did-auth-siop-0.16.0.tgz
rename patches/{@credo-ts__core@0.5.10-alpha-20240801095850.patch => @credo-ts__core@0.5.11-pr-1996-20240826150533.patch} (100%)
delete mode 100644 patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch
create mode 100644 patches/@credo-ts__openid4vc@0.5.11-pr-1996-20240826150533.patch
rename patches/{@sphereon__did-auth-siop@0.15.1-next.4.patch => @sphereon__did-auth-siop@0.16.0.patch} (100%)
create mode 100644 sphereon-did-auth-siop-0.16.0.tgz
diff --git a/README.md b/README.md
index 1cd967b..fb05ef3 100644
--- a/README.md
+++ b/README.md
@@ -75,11 +75,11 @@ Open three terminal windows, and then run the following:
npx ngrok http 3001
```
-Copy the https url from the ngrok command and set that as the `AGENT_HOST`
+Copy the https url from the ngrok command and set that as the `AGENT_HOST` and `AGENT_DNS`
```bash
cd agent
-AGENT_HOST=https://30f9-58-136-114-148.ngrok-free.app pnpm dev
+AGENT_DNS=30f9-58-136-114-148.ngrok-free.app AGENT_HOST=https://30f9-58-136-114-148.ngrok-free.app pnpm dev
```
```bash
diff --git a/agent/package.json b/agent/package.json
index b78bc99..a0a9292 100644
--- a/agent/package.json
+++ b/agent/package.json
@@ -1,10 +1,12 @@
{
"name": "agent",
"dependencies": {
- "@credo-ts/askar": "0.5.10-alpha-20240801095850",
- "@credo-ts/core": "0.5.10-alpha-20240801095850",
- "@credo-ts/node": "0.5.10-alpha-20240801095850",
- "@credo-ts/openid4vc": "0.5.10-alpha-20240801095850",
+ "@credo-ts/askar": "0.5.11-pr-1996-20240826150533",
+ "@credo-ts/cheqd": "0.5.11-pr-1996-20240826150533",
+ "@credo-ts/core": "0.5.11-pr-1996-20240826150533",
+ "@credo-ts/indy-vdr": "0.5.11-pr-1996-20240826150533",
+ "@credo-ts/node": "0.5.11-pr-1996-20240826150533",
+ "@credo-ts/openid4vc": "0.5.11-pr-1996-20240826150533",
"@hyperledger/aries-askar-nodejs": "^0.2.3",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
@@ -24,10 +26,13 @@
"dev": "tsx watch -r dotenv/config src/server.ts dotenv_config_path=.env.development"
},
"pnpm": {
+ "overrides": {
+ "@sphereon/did-auth-siop": "file:./sphereon-did-auth-siop-0.16.0.tgz"
+ },
"patchedDependencies": {
- "@sphereon/did-auth-siop@0.15.1-next.4": "patches/@sphereon__did-auth-siop@0.15.1-next.4.patch",
- "@credo-ts/openid4vc@0.5.10-alpha-20240801095850": "patches/@credo-ts__openid4vc@0.5.10-alpha-20240801095850.patch",
- "@credo-ts/core@0.5.10-alpha-20240801095850": "patches/@credo-ts__core@0.5.10-alpha-20240801095850.patch"
+ "@sphereon/did-auth-siop@0.16.0": "patches/@sphereon__did-auth-siop@0.16.0.patch",
+ "@credo-ts/openid4vc@0.5.11-pr-1996-20240826150533": "patches/@credo-ts__openid4vc@0.5.11-pr-1996-20240826150533.patch",
+ "@credo-ts/core@0.5.11-pr-1996-20240826150533": "patches/@credo-ts__core@0.5.11-pr-1996-20240826150533.patch"
}
}
}
diff --git a/agent/sphereon-did-auth-siop-0.16.0.tgz b/agent/sphereon-did-auth-siop-0.16.0.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..2a184a4ab60a556ce7d6f1c988ca8abe2598f7a6
GIT binary patch
literal 853549
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