Skip to content

Commit

Permalink
Merge branch 'main' into sd-jwt-support
Browse files Browse the repository at this point in the history
Signed-off-by: F-Node-Karlsruhe <christian.fries@eecc.de>
  • Loading branch information
F-Node-Karlsruhe committed Oct 20, 2023
2 parents 1ca43ad + a6681cb commit a21820c
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 30 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ WIP
- add support for SD-JWT


1.7.4 (2023-10-10)
---

- fix build node version


1.7.3 (2023-10-09)
---

- support empty presentations for proof of possession


1.7.2 (2023-09-11)
---

Expand Down
23 changes: 14 additions & 9 deletions api/__tests__/credential.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import request from "supertest";

import app from "../src/index";
import server from "../src/index";

afterAll(done => {
server.close();
done();
});

const revoked2020Credential: any = {
"@context": [
Expand Down Expand Up @@ -192,14 +197,14 @@ const manipulatedCredential = Object.assign({ ...GS1LicenceCredential }, { issua
describe("Verifier API Test for Credentials", () => {

test("Verify vc by id", async () => {
const res = await request(app).get("/api/verifier/vc/https%253A%252F%252Fid.gs1.org%252Fvc%252Flicence%252Fgs1_prefix%252F05");
const res = await request(server).get("/api/verifier/vc/https%253A%252F%252Fid.gs1.org%252Fvc%252Flicence%252Fgs1_prefix%252F05");
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty('verified');
expect(res.body.verified).toBe(true);
});

test("Verify single credential", async () => {
const res = await request(app).post("/api/verifier").send([GS1LicenceCredential]);
const res = await request(server).post("/api/verifier").send([GS1LicenceCredential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
Expand All @@ -209,14 +214,14 @@ describe("Verifier API Test for Credentials", () => {
* Test selective disclosure DataIntegrityProof credential
*/
test("Verify single DataIntegrityProof credential", async () => {
const res = await request(app).post("/api/verifier").send([SDCredential]);
const res = await request(server).post("/api/verifier").send([SDCredential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
});

test("Verify multiple credentials", async () => {
const res = await request(app).post("/api/verifier").send([GS1LicenceCredential, GS1LicenceCredential]);
const res = await request(server).post("/api/verifier").send([GS1LicenceCredential, GS1LicenceCredential]);
expect(res.statusCode).toEqual(200);
res.body.forEach((el: any) => {
expect(el).toHaveProperty('verified');
Expand All @@ -228,7 +233,7 @@ describe("Verifier API Test for Credentials", () => {
* Test StatusList2020 revoked credential
*/
test("Verify revoked credential", async () => {
const res = await request(app).post("/api/verifier").send([revoked2020Credential]);
const res = await request(server).post("/api/verifier").send([revoked2020Credential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(false);
Expand All @@ -240,7 +245,7 @@ describe("Verifier API Test for Credentials", () => {
* Test StatusList2021 revoked credential
*/
test("Verify revoked credential", async () => {
const res = await request(app).post("/api/verifier").send([revoked2021Credential]);
const res = await request(server).post("/api/verifier").send([revoked2021Credential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(false);
Expand All @@ -252,7 +257,7 @@ describe("Verifier API Test for Credentials", () => {
* Test StatusList2021 suspended credential
*/
test("Verify suspended credential", async () => {
const res = await request(app).post("/api/verifier").send([suspended2021Credential]);
const res = await request(server).post("/api/verifier").send([suspended2021Credential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(false);
Expand All @@ -261,7 +266,7 @@ describe("Verifier API Test for Credentials", () => {
});

test("Falsify single credential", async () => {
const res = await request(app).post("/api/verifier").send([manipulatedCredential]);
const res = await request(server).post("/api/verifier").send([manipulatedCredential]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(false);
Expand Down
15 changes: 10 additions & 5 deletions api/__tests__/presentation.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import request from "supertest";

import app from "../src/index";
import server from "../src/index";

afterAll(done => {
server.close();
done();
});

const sdJWTPresentation: string = "eyJhbGciOiJFUzM4NCIsImtpZCI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpGUXlJc0luZ2lPaUpJWTNRd1gyTmliRzVzYkV0VFYxOWFVVnBtUlhkRGIwbFFaRlpWYW1kTlNXMW1OWEZzUkRKVWVEaG1TM0ZLUTFoeVYxSnlOMVZwU2xCWGVsTldhbXBHSWl3aWVTSTZJbTAxTlhka1ZUbG1hVXROWDFWQmR6WlpTMWs1Ym1kdGEyZzRlbWhKVG1JM1V6bFhTVzVtTFhvelIxaENOR3RST0dJNGVtOVBla3RvWjB0elRqTm9jRzBpTENKamNuWWlPaUpRTFRNNE5DSjkjMCJ9.eyJhcnJheV93aXRoX3JlY3Vyc2l2ZV9zZCI6WyJib3JpbmciLHsiZm9vIjoiYmFyIiwiX3NkIjpbInFnSG0yNjAyTlFZQjh4Z0RISmEwRTZIeDJxZnM0UWNzRURqREcyRDlaOUUiXX0sW3siLi4uIjoiNWExUFRkX0xJUVd0djVBMWdxM0R5QXZyQTh0QnlVZDJaMHF0SlJGSzF4RSJ9LHsiLi4uIjoiWW1tN0d4MnZNSlVHaDVjQ2tsZUpkaEV3MWVlTHNLRWF2SVZFT1hBMXVOUSJ9XV0sInRlc3QyIjpbeyIuLi4iOiJ2RDYzS2Z1bGFUT2NlNlh6WUlsXy1RSGFCUUVxR1lfVXA0S1lCell5QUJZIn0seyIuLi4iOiI1Z3Q4ZzlkMlNXVUZIZklZYWJXUFM5TlIxTTVNb3pKbnoyNUlGR01tdmhjIn1dLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpGUXlJc0luZ2lPaUpJWTNRd1gyTmliRzVzYkV0VFYxOWFVVnBtUlhkRGIwbFFaRlpWYW1kTlNXMW1OWEZzUkRKVWVEaG1TM0ZLUTFoeVYxSnlOMVZwU2xCWGVsTldhbXBHSWl3aWVTSTZJbTAxTlhka1ZUbG1hVXROWDFWQmR6WlpTMWs1Ym1kdGEyZzRlbWhKVG1JM1V6bFhTVzVtTFhvelIxaENOR3RST0dJNGVtOVBla3RvWjB0elRqTm9jRzBpTENKamNuWWlPaUpRTFRNNE5DSjkiLCJpYXQiOjE2OTQ3Njk1NDUsImV4cCI6MTcyNjM5MTk0NSwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMzg0IiwieCI6InNoY24xeE43ODBLRWRuZVFVVXZ3bUhmQUM0Y0VWb2ZGSjlWc002RDlfLTdlaGtLdVdUN2NSUTZ3R0ZnU3hWbFEiLCJ5IjoiSHl2V1NYc25sT3RvRzJzNjB6a0ZTN2FmR01oU0pXUW5TX3BRaURfN0ptNHNQd3RMSnVnMy1OOW5pQjJOVl9DXyJ9fX0.JoD9gePif8jfnlf-45KwNMe1TuHWKWbWqbECzPHeY9vQVBMd3Sd0VrB2aXSlyKqDkZPPpQsVk5nSC3ofOEUAm7HHfHN42Vzr3-4XNPfoTJmarPZNFMtbjgWayBWyUuSX~WyI0SHdhRHk1dU9SczdMbjZ0b1NpR0N3IiwgImJheiIsIHsicXV4IjogInF1dXgifV0~WyJvdVl4cUZMRGZxZW5VUHptUWZBWEh3IiwgImJhciJd~WyJUMHpiWURfR1FSVVdocjJuYjc2SmpRIiwgImZvbyJd~WyJRRldFR1ZwNlNpZ19rdzJHYml1dnZBIiwgImJhciJd~eyJhbGciOiJFUzM4NCIsInR5cCI6ImtiK2p3dCJ9.eyJub25jZSI6Ijk4NzY1NDMyMTAiLCJhdWQiOiJkaWQ6d2ViOnZlcmlmaWVyLmV4YW1wbGUiLCJpYXQiOjE2OTQ3Njk1NDV9.zl9qYTnspJXq1EhMsQmgSfKixyVdruYX0JdGC26SygAKlvjL5UlUKb6LhjxF_tGw3MV5WIXdfGODlqjHmynPnRNAh8snXxn4j1ONUhuNHDqbxBEhGZKXIEJyIjj2Ibcf"

Expand Down Expand Up @@ -200,7 +205,7 @@ const statusPresentation: any = {
describe("Verifier API Test for Presentations", () => {

test("Verify presentation with status", async () => {
const res = await request(app).post("/api/verifier").send([statusPresentation]);
const res = await request(server).post("/api/verifier").send([statusPresentation]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
Expand All @@ -212,7 +217,7 @@ describe("Verifier API Test for Presentations", () => {
});

test("Verify single presentation with challenge", async () => {
const res = await request(app).post("/api/verifier").query({ challenge: '12345' }).send([multiPresentation]);
const res = await request(server).post("/api/verifier").query({ challenge: '12345' }).send([multiPresentation]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
Expand All @@ -224,7 +229,7 @@ describe("Verifier API Test for Presentations", () => {
});

test("Verify single presentation with challenge & domain", async () => {
const res = await request(app).post("/api/verifier").query({ challenge: '12345', domain: 'ssi.eecc.de/verifier' }).send([domainPresentation]);
const res = await request(server).post("/api/verifier").query({ challenge: '12345', domain: 'ssi.eecc.de/verifier' }).send([domainPresentation]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(true);
Expand All @@ -236,7 +241,7 @@ describe("Verifier API Test for Presentations", () => {
});

test("Falsify single presentation with wrong challenge", async () => {
const res = await request(app).post("/api/verifier").query({ challenge: 'falseChallenge', domain: 'ssi.eecc.de/verifier' }).send([domainPresentation]);
const res = await request(server).post("/api/verifier").query({ challenge: 'falseChallenge', domain: 'ssi.eecc.de/verifier' }).send([domainPresentation]);
expect(res.statusCode).toEqual(200);
expect(res.body[0]).toHaveProperty('verified');
expect(res.body[0].verified).toBe(false);
Expand Down
1 change: 1 addition & 0 deletions api/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ module.exports = {
},
],
},
testTimeout: 60000
};
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vc-verifier",
"version": "1.7.2",
"version": "1.7.4",
"description": "The EECC verifier for verifiable credentials which provides an verification API as well as the corresponding UI.",
"main": "index.js",
"type": "module",
Expand Down
12 changes: 6 additions & 6 deletions api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ app.use('/api/verifier', verifyRouter);

const port = process.env.PORT ? Number.parseInt(process.env.PORT) : 3000

if (process.env.NODE_ENV !== 'test') {
const server = app.listen(port, async () => {
console.log(`Started API Server on port ${port}`);
});
}

export default app;
const server = app.listen(port, async () => {
console.log(`Started API Server on port ${port}`);
});


export default server;
4 changes: 2 additions & 2 deletions api/src/routers/verify/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const verifyRouter = Router();
* @summary Refers to W3C Credential
* @typedef {object} SignedCredential
* @property {array<string>} context.required - The JSON-LD context URIs of the credential
* @property {string} id.required - The id of the the credential as an IRI
* @property {string} id - The id of the the credential as an IRI
* @property {array<string>} type.required - The types of the credential
* @property {string} issuer.required - The DID of the issuer of the credential
* @property {string} issuanceDate.required - The issuance date of the credential in ISO format 2022-09-26T09:01:07.437Z
Expand All @@ -36,7 +36,7 @@ export const verifyRouter = Router();
* @typedef {object} SignedPresentation
* @property {array<string>} context.required - The JSON-LD context URIs of the presentation
* @property {array<string>} type.required - The types of the presentation. Should be 'VerifiablePresentation'
* @property {string} holder.required - The DID of the holder of the credentials, i.e. the presenter
* @property {string} holder - The DID of the holder of the credentials, i.e. the presenter
* @property {array<SignedCredential>} verifiableCredential - Array of included credentials
* @property {object} proof.required - The cryptographic signature of the holder over the presentation
*/
Expand Down
13 changes: 9 additions & 4 deletions api/src/services/verifier/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@

import { verifyDataIntegrityProof } from './dataintegrity.js';
import { verifySDJWT } from './sdjwt.js';




export class Verifier {

static async verify(verifiable: Verifiable | string, challenge?: string, domain?: string): Promise<VerificationResult> {

// vc-jwt or sd-jwt
if (typeof verifiable == 'string') return await verifySDJWT(verifiable, challenge, domain)
if (typeof verifiable == 'string' && verifiable.startsWith('ey')) return await verifySDJWT(verifiable, challenge, domain)

// DataIntegrityProof
return await verifyDataIntegrityProof(verifiable, challenge, domain);

if (typeof verifiable == 'object') return await verifyDataIntegrityProof(verifiable, challenge, domain);

throw new Error('Unrecognized credential type!')

}

}
2 changes: 1 addition & 1 deletion frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# develop stage
FROM node:lts-alpine as develop-stage
FROM node:18.17-alpine as develop-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "verifier_frontend",
"version": "1.7.2",
"version": "1.7.4",
"description": "Vue frontend for the EECC vc verifier API",
"scripts": {
"build": "vue-cli-service build",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import api from '../api'

export default createStore({
state: {
version: '1.7.2',
version: '1.7.4',
authentication: undefined,
verifiables: [],
disclosedCredentials: [],
Expand Down

0 comments on commit a21820c

Please sign in to comment.