Skip to content

Commit

Permalink
ferryboardingpass use cases
Browse files Browse the repository at this point in the history
  • Loading branch information
endimion committed May 28, 2024
1 parent a0f7d29 commit d634446
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 4 deletions.
132 changes: 131 additions & 1 deletion data/issuer-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,137 @@
}
}
}
},
"ferryBoardingPassCredential": {
"format": "vc_jwt",
"scope": "ferryBoardingPassCredential",
"cryptographic_binding_methods_supported": ["jwk"],
"cryptographic_suites_supported": ["ES256"],
"display": [
{
"name": "Ferry Boarding Pass",
"locale": "en-GB",
"background_color": "#12107c",
"text_color": "#FFFFFF"
}
],
"credential_definition": {
"type": ["ferryBoardingPassCredential"],
"claims": {
"identifier": {
"display": [
{
"name": "Identifier",
"locale": "en-GB"
}
]
},
"ticketQR": {
"display": [
{
"name": "Ticket QR Code",
"locale": "en-GB"
}
]
},
"ticketNumber": {
"display": [
{
"name": "Ticket Number",
"locale": "en-GB"
}
]
},
"ticketLet": {
"display": [
{
"name": "Ticket Letter",
"locale": "en-GB"
}
]
},
"lastName": {
"display": [
{
"name": "Last Name",
"locale": "en-GB"
}
]
},
"firstName": {
"display": [
{
"name": "First Name",
"locale": "en-GB"
}
]
},
"seatType": {
"display": [
{
"name": "Seat Type",
"locale": "en-GB"
}
]
},
"seatNumber": {
"display": [
{
"name": "Seat Number",
"locale": "en-GB"
}
]
},
"departureDate": {
"display": [
{
"name": "Departure Date",
"locale": "en-GB"
}
]
},
"departureTime": {
"display": [
{
"name": "Departure Time",
"locale": "en-GB"
}
]
},
"arrivalDate": {
"display": [
{
"name": "Arrival Date",
"locale": "en-GB"
}
]
},
"arrivalTime": {
"display": [
{
"name": "Arrival Time",
"locale": "en-GB"
}
]
},
"arrivalPort": {
"display": [
{
"name": "Arrival Port",
"locale": "en-GB"
}
]
},
"vesselDescription": {
"display": [
{
"name": "Vessel Description",
"locale": "en-GB"
}
]
}
}
}
}

}
}
66 changes: 66 additions & 0 deletions data/presentation_definition_ferryboardingpass.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"id": "d49ee616-0e8d-4698-aff5-2a8a2362652d",
"name": "ferry-boarding-pass-proof",
"format": {
"jwt_vc": {
"alg": ["ES256", "ES384"]
}
},
"input_descriptors": [
{
"id": "abd4acb1-1dcb-41ad-8596-ceb1401a69c7",
"format": {
"jwt_vc": {
"alg": ["ES256", "ES384"]
}
},
"constraints": {
"fields": [
{
"path": ["$.credentialSubject.identifier", "$.vc.credentialSubject.identifier"]
},
{
"path": ["$.credentialSubject.ticketQR", "$.vc.credentialSubject.ticketQR"]
},
{
"path": ["$.credentialSubject.ticketNumber", "$.vc.credentialSubject.ticketNumber"]
},
{
"path": ["$.credentialSubject.ticketLet", "$.vc.credentialSubject.ticketLet"]
},
{
"path": ["$.credentialSubject.lastName", "$.vc.credentialSubject.lastName"]
},
{
"path": ["$.credentialSubject.firstName", "$.vc.credentialSubject.firstName"]
},
{
"path": ["$.credentialSubject.seatType", "$.vc.credentialSubject.seatType"]
},
{
"path": ["$.credentialSubject.seatNumber", "$.vc.credentialSubject.seatNumber"]
},
{
"path": ["$.credentialSubject.departureDate", "$.vc.credentialSubject.departureDate"]
},
{
"path": ["$.credentialSubject.departureTime", "$.vc.credentialSubject.departureTime"]
},
{
"path": ["$.credentialSubject.arrivalDate", "$.vc.credentialSubject.arrivalDate"]
},
{
"path": ["$.credentialSubject.arrivalTime", "$.vc.credentialSubject.arrivalTime"]
},
{
"path": ["$.credentialSubject.arrivalPort", "$.vc.credentialSubject.arrivalPort"]
},
{
"path": ["$.credentialSubject.vesselDescription", "$.vc.credentialSubject.vesselDescription"]
}
]
},
"limit_disclosure": "required"
}
]
}
76 changes: 76 additions & 0 deletions routes/boardingPassRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import express from "express";
import fs from "fs";
import { v4 as uuidv4 } from "uuid";
import {
pemToJWK,
generateNonce,
base64UrlEncodeSha256,
} from "../utils/cryptoUtils.js";
import {
buildAccessToken,
generateRefreshToken,
buildIdToken,
} from "../utils/tokenUtils.js";

import {
getAuthCodeSessions,
getPreCodeSessions,
} from "../services/cacheService.js";

import { SDJwtVcInstance } from "@sd-jwt/sd-jwt-vc";
import {
createSignerVerifier,
digest,
generateSalt,
} from "../utils/sdjwtUtils.js";
import jwt from "jsonwebtoken";

import qr from "qr-image";
import imageDataURI from "image-data-uri";
import { streamToBuffer } from "@jorgeferrero/stream-to-buffer";

const boardingPassRouter = express.Router();

const serverURL = process.env.SERVER_URL || "http://localhost:3000";

const privateKey = fs.readFileSync("./private-key.pem", "utf-8");
const publicKeyPem = fs.readFileSync("./public-key.pem", "utf-8");

boardingPassRouter.get(["/pre-offer-jwt-bpass"], async (req, res) => {
const uuid = req.query.sessionId ? req.query.sessionId : uuidv4();
const preSessions = getPreCodeSessions();
if (preSessions.sessions.indexOf(uuid) < 0) {
preSessions.sessions.push(uuid);
preSessions.results.push({ sessionId: uuid, status: "pending" });
}
let credentialOffer = `openid-credential-offer://?credential_offer_uri=${serverURL}/credential-offer-pre-jwt-bpass/${uuid}`; //OfferUUID
let code = qr.image(credentialOffer, {
type: "png",
ec_level: "H",
size: 10,
margin: 10,
});
let mediaType = "PNG";
let encodedQR = imageDataURI.encode(await streamToBuffer(code), mediaType);
res.json({
qr: encodedQR,
deepLink: credentialOffer,
sessionId: uuid,
});
});

boardingPassRouter.get(["/credential-offer-pre-jwt-bpass/:id"], (req, res) => {
res.json({
credential_issuer: serverURL,
credentials: ["ferryBoardingPassCredential"],
grants: {
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": req.params.id,
user_pin_required: true,
},
},
});
});


export default boardingPassRouter;
43 changes: 43 additions & 0 deletions routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,49 @@ router.post("/credential", async (req, res) => {
).toISOString(),
},
};
} else if (
requestedCredentials != null &&
requestedCredentials[0] === "ferryBoardingPassCredential"
) {
payload = {
iss: serverURL,
sub: decodedHeaderSubjectDID || "",
iat: Math.floor(Date.now() / 1000), // Token issued at time
exp: Math.floor(Date.now() / 1000) + 60 * 60, // Token expiration time (1 hour from now)
jti: "urn:did:1904a925-38bd-4eda-b682-4b5e3ca9d4bc",
vc: {
type: ["VerifiableCredential", "ferryBoardingPassCredential"],
"@context": ["https://www.w3.org/2018/credentials/v1"],
issuer: serverURL,
credentialSubject: {
id: decodedHeaderSubjectDID || "", // Replace with the actual subject DID
identifier: "John Doe",
ticketQR:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAAB5AQAAAAA+SX7VAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABlUlEQVRIDe2YMUtCQRCFZxQVhQo2hdwV2NhZ+ggLFzcBrcNLYktjb2AiBBkDEtFiFE3d7WVo+BR+BX+gtEop3Rjb7ndmxmh8HTIz5TdvzZk5MhGoUZ1Hnz1swr3/ehyHt6nuKPexG5XQPeDqcgrBXT3wGso+ULuLoDr/owxPI27WqZLPKpFvH2FqESkBu8WqwCrCL3r6Ne3Slo6I0A9H/UUXH5KoJwUbPFLU5CJqsZubAiZwVLja4YpAyyKcijulVDrwjeMaLs5CmlgHds1GZc9K8T/AXTDwLB0yzhFb2CHavBtL68YRuBN3le6HB54Rz6MPGoNx7N2e3ws+b9YL2scQY8jI9iA9gN0FbgeEQLzUXwl90kpAmNyDe4SjH5itwbPfNRi7w0Ogl8KiB1QWUDZc0h34sFjDwrIs+w6GCSnNhWbzP9FAvVd8BzCgbChAkd4VnLQZX9VaQd9gM0b9D/UZoTQAAAABJRU5ErkJggg==",
ticketNumber: "ABC123456789",
ticketLet: "A",
lastName: "Doe",
firstName: "John",
seatType: "Economy",
seatNumber: "12A",
departureDate: "2023-11-30",
departureTime: "13:07:34",
arrivalDate: "2023-11-30",
arrivalTime: "15:30:00",
arrivalPort: "NYC",
vesselDescription: "Ferry XYZ",
},
issuanceDate: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expirationDate: new Date(
(Math.floor(Date.now() / 1000) + 60 * 60) * 1000
).toISOString(),
validFrom: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
},
};
} else {
//sign as jwt
payload = {
Expand Down
15 changes: 12 additions & 3 deletions routes/verifierRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ const presentation_definition_educational_id = JSON.parse(
const presentation_definition_alliance_id = JSON.parse(
fs.readFileSync("./data/presentation_definition_alliance_id.json", "utf-8")
);

const presentation_definition_ferryboardingpass = JSON.parse(
fs.readFileSync(
"./data/presentation_definition_ferryboardingpass.json",
"utf-8"
)
);
//

const jwks = pemToJWK(publicKeyPem, "public");
Expand Down Expand Up @@ -260,11 +267,13 @@ verifierRouter.get("/vpRequest/:type/:id", async (req, res) => {
presentationDefinition = presentation_definition_pid;
} else if (type === "epassport") {
presentationDefinition = presentation_definition_epass;
} else if (type === "educationId" || type === "educationid" ) {
} else if (type === "educationId" || type === "educationid") {
presentationDefinition = presentation_definition_educational_id;
} else if(type==="allianceId" || type === "allianceid"){
} else if (type === "allianceId" || type === "allianceid") {
presentationDefinition = presentation_definition_alliance_id;
}else {
} else if (type === "ferryboardingpass") {
presentationDefinition = presentation_definition_ferryboardingpass;
} else {
return res.status(400).type("text/plain").send("Invalid type parameter");
}

Expand Down
2 changes: 2 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import verifierRouter from "./routes/verifierRoutes.js";
import metadataRouter from "./routes/metadataroutes.js";
import codeFlowRouter from "./routes/codeFlowJwtRoutes.js";
import codeFlowRouterSDJWT from "./routes/codeFlowSdJwtRoutes.js";
import boardingPassRouter from "./routes/boardingPassRoutes.js";
import pidRouter from "./routes/pidroutes.js";
import passportRouter from "./routes/passportRoutes.js";
import educationalRouter from "./routes/educationalRoutes.js";
Expand All @@ -31,6 +32,7 @@ app.use("/", codeFlowRouterSDJWT);
app.use("/", pidRouter);
app.use("/", passportRouter);
app.use("/", educationalRouter);
app.use("/", boardingPassRouter);

// Start the server
app.listen(port, () => {
Expand Down

0 comments on commit d634446

Please sign in to comment.