From c8e6b626780854274375073187aff48e9596b2b5 Mon Sep 17 00:00:00 2001 From: Nikos Triantafyllou Date: Fri, 21 Jun 2024 14:52:11 +0300 Subject: [PATCH 1/5] formating --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a40b6f..45a4cdd 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "SERVER_URL=https://fb13-2a02-587-870a-9d00-812c-35df-3c2a-93f4.ngrok-free.app node server.js" + "dev": "SERVER_URL=https://2131-2a02-587-870a-9d00-82cc-e03d-e6be-d2f8.ngrok-free.app node server.js" }, "author": "", "license": "ISC", From ea69ba29267f3dd004de56eb2792fa5fc5c454cb Mon Sep 17 00:00:00 2001 From: Nikos Triantafyllou Date: Mon, 1 Jul 2024 18:27:42 +0300 Subject: [PATCH 2/5] changes for issue#12 --- data/verifier-config.json | 39 +++++++++++++++++++++++ package.json | 2 +- routes/verifierRoutes.js | 33 +++++++++++++++++++- utils/cryptoUtils.js | 65 ++++++++++++++++++++------------------- 4 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 data/verifier-config.json diff --git a/data/verifier-config.json b/data/verifier-config.json new file mode 100644 index 0000000..a4f57df --- /dev/null +++ b/data/verifier-config.json @@ -0,0 +1,39 @@ +{ + "client_id": "https://dss.aegean.gr", + "client_name": "UAegean EWC Verifier", + "redirect_uris": [ + "https://example-verifier.com/callback" + ], + "vp_formats_supported": [ + "jwt_vc_json", + "ldp_vc" + ], + "vp_token_endpoint_auth_methods_supported": [ + "client_secret_basic", + "client_secret_post" + ], + "presentation_definition_uri": "https://example-verifier.com/presentation-definitions", + "scopes_supported": [ + "openid", + "profile", + "vc_present" + ], + "response_types_supported": [ + "vp_token" + ], + "grant_types_supported": [ + "authorization_code" + ], + "id_token_signing_alg_values_supported": [ + "RS256", + "ES256" + ], + "vp_token_signing_alg_values_supported": [ + "RS256", + "ES256" + ], + "subject_types_supported": [ + "pairwise" + ] + } + \ No newline at end of file diff --git a/package.json b/package.json index 45a4cdd..d7a647d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "SERVER_URL=https://2131-2a02-587-870a-9d00-82cc-e03d-e6be-d2f8.ngrok-free.app node server.js" + "dev": "SERVER_URL=https://95cf-2a02-587-8713-1c00-7651-758f-5657-ed40.ngrok-free.app node server.js" }, "author": "", "license": "ISC", diff --git a/routes/verifierRoutes.js b/routes/verifierRoutes.js index 2744e96..49659dc 100644 --- a/routes/verifierRoutes.js +++ b/routes/verifierRoutes.js @@ -57,6 +57,9 @@ const presentation_definition_alliance_and_education_Id = JSON.parse( ) ); // +const clientMetadata = JSON.parse( + fs.readFileSync("./data/verifier-config.json", "utf-8") +); const jwks = pemToJWK(publicKeyPem, "public"); @@ -221,9 +224,37 @@ verifierRouter.get("/vpRequestJwt/:id", async (req, res) => { serverURL, privateKey ); - res.type("text/plain").send(jwtToken); + + + clientMetadata.presentation_definition_uri= serverURL+"/presentation-definition/1" + + let vpRequest= { + response_type: "vp_token", + client_id: clientId, + client_id_scheme: "redirect_uri", + presentation_definition: presentation_definition_jwt, + redirect_uri: response_uri, + // response_mode: "direct_post", + client_metadata : encodeURIComponent(JSON.stringify(clientMetadata)), + } + + console.log("will send vpRequest") + console.log(vpRequest) + + res.json(vpRequest); }); + +verifierRouter.get("/presentation-definition/:type", async (req, res) => { + const { type } = req.params; + if(type == 1) { + res.type("application/json").send(presentation_definition_jwt); + } + console.log("ERROR getting presentatiton-definition type") + res.status(500) +}) + + // *******************PILOT USE CASES ****************************** verifierRouter.get("/vp-request/:type", async (req, res) => { const { type } = req.params; diff --git a/utils/cryptoUtils.js b/utils/cryptoUtils.js index f4fa526..b740802 100644 --- a/utils/cryptoUtils.js +++ b/utils/cryptoUtils.js @@ -49,49 +49,52 @@ export function buildVpRequestJwt( */ /** - * response_uri - * client_id_scheme: "redirect_uri", - * iss": "https://some.io", - * presentation_definition: {} - * "response_type": "vp_token", - "state": "344306f6-0323-4ef5-9348-70fc328efd85", - "exp": 1712309984, - "nonce": "1fRxngVjYq0oETeZxNYfId", - "iat": 1712306384, - "client_id": "https://some.io/openid4vp/authorization-response", - "response_mode": "direct_post" + Location: https://client.example.org/universal-link? + response_type=vp_token + &client_id=https%3A%2F%2Fclient.example.org%2Fcb + &client_id_scheme=redirect_uri + &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb + &presentation_definition=... + &nonce=n-0S6_WzA2Mj + &client_metadata=%7B%22vp_formats%22:%7B%22jwt_vp%22:% + 7B%22alg%22:%5B%22EdDSA%22,%22ES256K%22%5D%7D,%22ldp + _vp%22:%7B%22proof_type%22:%5B%22Ed25519Signature201 + 8%22%5D%7D%7D%7D * */ let jwtPayload = { - client_id_scheme: "redirect_uri", - response_uri: response_uri, //TODO Note: If the Client Identifier scheme redirect_uri is used in conjunction with the Response Mode direct_post, and the response_uri parameter is present, the client_id value MUST be equal to the response_uri value - iss: serverURL, - presentation_definition: presentation_definition, response_type: "vp_token", - state: state, - exp: Math.floor(Date.now() / 1000) + 60, - nonce: nonce, - iat: Math.floor(Date.now() / 1000), client_id: client_id, - response_mode: "direct_post", + client_id_scheme: "redirect_uri", + presentation_definition: presentation_definition, + redirect_uri: response_uri, + // response_mode: "direct_post", + client_metadata : "", + + // response_uri: response_uri, //TODO Note: If the Client Identifier scheme redirect_uri is used in conjunction with the Response Mode direct_post, and the response_uri parameter is present, the client_id value MUST be equal to the response_uri value + // iss: serverURL, + // state: state, + // exp: Math.floor(Date.now() / 1000) + 60, + // nonce: nonce, + // iat: Math.floor(Date.now() / 1000), // nbf: Math.floor(Date.now() / 1000), // redirect_uri: redirect_uri, // scope: "openid", }; - const header = { - alg: "ES256", - kid: `aegean#authentication-key`, //this kid needs to be resolvable from the did.json endpoint - }; - - const token = jwt.sign(jwtPayload, privateKey, { - algorithm: "ES256", - noTimestamp: true, - header, - }); - return token; + // const header = { + // alg: "ES256", + // kid: `aegean#authentication-key`, //this kid needs to be resolvable from the did.json endpoint + // }; + + // const token = jwt.sign(jwtPayload, privateKey, { + // algorithm: "ES256", + // noTimestamp: true, + // header, + // }); + return jwtPayload; } export async function decryptJWE(jweToken, privateKeyPEM) { From cb283573e13e9512d05071011de2d057f88aef05 Mon Sep 17 00:00:00 2001 From: Nikos Triantafyllou Date: Mon, 1 Jul 2024 18:42:02 +0300 Subject: [PATCH 3/5] corrected clientMetadata --- routes/verifierRoutes.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/routes/verifierRoutes.js b/routes/verifierRoutes.js index 49659dc..3360e1c 100644 --- a/routes/verifierRoutes.js +++ b/routes/verifierRoutes.js @@ -214,19 +214,21 @@ verifierRouter.get("/vpRequestJwt/:id", async (req, res) => { claims: null, }); - let jwtToken = buildVpRequestJwt( - stateParam, - nonce, - clientId, - response_uri, - presentation_definition_jwt, - jwks, - serverURL, - privateKey - ); + // let jwtToken = buildVpRequestJwt( + // stateParam, + // nonce, + // clientId, + // response_uri, + // presentation_definition_jwt, + // jwks, + // serverURL, + // privateKey + // ); clientMetadata.presentation_definition_uri= serverURL+"/presentation-definition/1" + clientMetadata.redirect_uris= [response_uri] + clientMetadata.client_id=clientId let vpRequest= { response_type: "vp_token", From 48edfc19985979b104671c4771ff6c98d08f6009 Mon Sep 17 00:00:00 2001 From: Nikos Triantafyllou Date: Mon, 1 Jul 2024 23:41:42 +0300 Subject: [PATCH 4/5] fixed issue#12 --- package.json | 2 +- routes/verifierRoutes.js | 95 +++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index d7a647d..7a7f699 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "SERVER_URL=https://95cf-2a02-587-8713-1c00-7651-758f-5657-ed40.ngrok-free.app node server.js" + "dev": "SERVER_URL=https://dd0d-2a02-587-8713-1c00-f2ea-680b-e09-62ed.ngrok-free.app node server.js" }, "author": "", "license": "ISC", diff --git a/routes/verifierRoutes.js b/routes/verifierRoutes.js index 3360e1c..30e6166 100644 --- a/routes/verifierRoutes.js +++ b/routes/verifierRoutes.js @@ -65,8 +65,8 @@ const jwks = pemToJWK(publicKeyPem, "public"); let verificationSessions = []; //TODO these should be redis or something a proper cache... let sessions = []; -let sessionHistory = new TimedArray(30000) //cache data for 30sec -let verificationResultsHistory = new TimedArray(30000) //cache data for 30sec +let sessionHistory = new TimedArray(30000); //cache data for 30sec +let verificationResultsHistory = new TimedArray(30000); //cache data for 30sec verifierRouter.get("/generateVPRequest", async (req, res) => { const stateParam = req.query.id ? req.query.id : uuidv4(); @@ -214,48 +214,36 @@ verifierRouter.get("/vpRequestJwt/:id", async (req, res) => { claims: null, }); - // let jwtToken = buildVpRequestJwt( - // stateParam, - // nonce, - // clientId, - // response_uri, - // presentation_definition_jwt, - // jwks, - // serverURL, - // privateKey - // ); - - - clientMetadata.presentation_definition_uri= serverURL+"/presentation-definition/1" - clientMetadata.redirect_uris= [response_uri] - clientMetadata.client_id=clientId + clientMetadata.presentation_definition_uri = + serverURL + "/presentation-definition/1"; + clientMetadata.redirect_uris = [response_uri]; + clientMetadata.client_id = clientId; - let vpRequest= { - response_type: "vp_token", + let vpRequest = { client_id: clientId, client_id_scheme: "redirect_uri", + response_uri: response_uri, + response_type: "vp_token", + response_mode: "direct_post", presentation_definition: presentation_definition_jwt, - redirect_uri: response_uri, - // response_mode: "direct_post", - client_metadata : encodeURIComponent(JSON.stringify(clientMetadata)), - } + nonce: nonce, + state: uuid, + }; - console.log("will send vpRequest") - console.log(vpRequest) + // console.log("will send vpRequest"); + // console.log(vpRequest); - res.json(vpRequest); + res.json(vpRequest); }); - verifierRouter.get("/presentation-definition/:type", async (req, res) => { const { type } = req.params; - if(type == 1) { + if (type == 1) { res.type("application/json").send(presentation_definition_jwt); } - console.log("ERROR getting presentatiton-definition type") - res.status(500) -}) - + console.log("ERROR getting presentatiton-definition type"); + res.status(500); +}); // *******************PILOT USE CASES ****************************** verifierRouter.get("/vp-request/:type", async (req, res) => { @@ -322,17 +310,27 @@ verifierRouter.get("/vpRequest/:type/:id", async (req, res) => { return res.status(400).type("text/plain").send("Invalid type parameter"); } - let jwtToken = buildVpRequestJwt( - stateParam, - nonce, - clientId, - response_uri, - presentationDefinition, - jwks, - serverURL, - privateKey - ); - res.type("text/plain").send(jwtToken); + // let jwtToken = buildVpRequestJwt( + // stateParam, + // nonce, + // clientId, + // response_uri, + // presentationDefinition, + // jwks, + // serverURL, + // privateKey + // ); + let vpRequest = { + client_id: clientId, + client_id_scheme: "redirect_uri", + response_uri: response_uri, + response_type: "vp_token", + response_mode: "direct_post", + presentation_definition: presentation_definition_jwt, + nonce: nonce, + state: uuid, + }; + res.json(vpRequest); }); verifierRouter.post("/direct_post_jwt/:id", async (req, res) => { @@ -360,9 +358,9 @@ verifierRouter.post("/direct_post_jwt/:id", async (req, res) => { // Convert credentials to claims let claims; try { - console.log(credentialsJwtArray) + console.log(credentialsJwtArray); claims = await flattenCredentialsToClaims(credentialsJwtArray); - console.log(claims) + console.log(claims); if (!claims) { throw new Error("Claims conversion returned null or undefined."); } @@ -397,8 +395,8 @@ verifierRouter.get(["/verificationStatus"], (req, res) => { result = verificationSessions[index].claims; sessions.splice(index, 1); verificationSessions.splice(index, 1); - sessionHistory.addElement(sessionId) - verificationResultsHistory.addElement(result) + sessionHistory.addElement(sessionId); + verificationResultsHistory.addElement(result); } // console.log(`new sessions`); // console.log(sessions); @@ -421,7 +419,7 @@ verifierRouter.get(["/verificationStatus"], (req, res) => { verifierRouter.get(["/verificationStatusHistory"], (req, res) => { let sessionId = req.query.sessionId; - let index = sessionHistory.getCurrentArray().indexOf(sessionId); + let index = sessionHistory.getCurrentArray().indexOf(sessionId); if (index >= 0) { res.json({ status: "success", @@ -438,7 +436,6 @@ verifierRouter.get(["/verificationStatusHistory"], (req, res) => { } }); - function buildVP( client_id, redirect_uri, From 6749a71705e64a0e029126613879e26ca8621441 Mon Sep 17 00:00:00 2001 From: Nikos Triantafyllou Date: Tue, 10 Sep 2024 13:59:05 +0300 Subject: [PATCH 5/5] issue with sig header for sd-jwt --- package.json | 2 +- routes/codeFlowJwtRoutes.js | 29 +++++++++++++++++++++-------- routes/routes.js | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 7a7f699..34650d2 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "SERVER_URL=https://dd0d-2a02-587-8713-1c00-f2ea-680b-e09-62ed.ngrok-free.app node server.js" + "dev": "SERVER_URL=https://cf55-2a02-587-870d-e900-a1b1-2ac9-eea6-a3b6.ngrok-free.app node server.js" }, "author": "", "license": "ISC", diff --git a/routes/codeFlowJwtRoutes.js b/routes/codeFlowJwtRoutes.js index 0ffaa0f..83b8c59 100644 --- a/routes/codeFlowJwtRoutes.js +++ b/routes/codeFlowJwtRoutes.js @@ -90,16 +90,29 @@ codeFlowRouter.get("/authorize", async (req, res) => { //validations let errors = []; + /* + [{"format":"jwt_vc", + "locations":["https://issuer.example.com"], + "type":"openid_credential", + "types":["VerifiableCredential","VerifiableAttestation","VerifiablePortableDocumentA1"]}] + */ if (!authorizationDetails) { - //errors.push("no credentials requested"); + errors.push("no credentials requested"); console.log(`no credentials requested`); - } else if (authorizationDetails.credential_definition) { - console.log( - `credential ${authorizationDetails.credential_definition.type} was requested` - ); - } else if (authorizationDetails.types) { - //EBSI style - console.log(`credential ${authorizationDetails.types} was requested`); + } else { + try{ + if (authorizationDetails.credential_definition) { + console.log( + `credential ${authorizationDetails.credential_definition.type} was requested` + ); + } else if (authorizationDetails.types) { + //EBSI style + console.log(`credential ${authorizationDetails.types} was requested`); + } + }catch(error){ + errors.push("no credentials requested"); + } + } if (responseType !== "code") { diff --git a/routes/routes.js b/routes/routes.js index 5a36abb..7116fdb 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -770,7 +770,7 @@ router.post("/credential", async (req, res) => { const sdjwt = new SDJwtVcInstance({ signer, verifier, - signAlg: "ES384", + signAlg: "ES256", hasher: digest, hashAlg: "SHA-256", saltGenerator: generateSalt,