Skip to content

Commit

Permalink
support for multiple mock pid personas
Browse files Browse the repository at this point in the history
  • Loading branch information
endimion committed May 30, 2024
1 parent 0b98398 commit 75969c8
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 47 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "SERVER_URL=https://0324-195-251-179-70.ngrok-free.app node server.js"
"dev": "SERVER_URL=https://4188-2a02-587-871c-8800-b93d-7a0e-92dc-f152.ngrok-free.app node server.js"
},
"author": "",
"license": "ISC",
Expand Down
90 changes: 63 additions & 27 deletions routes/pidroutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,59 @@ 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");


pidRouter.get(["/pre-offer-jwt-pid"], 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-pid/${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,
});
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-pid/${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,
});
});

//Presonals for Piloting
pidRouter.get(["/offer-pid-persona"], async (req, res) => {
const uuid = req.query.sessionId ? req.query.sessionId : uuidv4();
const personaId = req.query.personaId;
const preSessions = getPreCodeSessions();
if (preSessions.sessions.indexOf(uuid + "-persona=" + personaId) < 0) {
preSessions.sessions.push(uuid + "-persona=" + personaId);
preSessions.results.push({ sessionId: uuid, status: "pending" });
preSessions.personas.push(null);
preSessions.accessTokens.push(null);
}
let credentialOffer = `openid-credential-offer://?credential_offer_uri=${serverURL}/credential-offer-pre-jwt-pid/${uuid}?persona=${personaId}`; //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,
});
});

pidRouter.get(["/credential-offer-pre-jwt-pid/:id"], (req, res) => {
pidRouter.get(["/credential-offer-pre-jwt-pid/:id"], (req, res) => {
let persona = req.query.persona;
if (!persona) {
res.json({
credential_issuer: serverURL,
credentials: ["PID"],
Expand All @@ -72,9 +99,18 @@ pidRouter.get(["/pre-offer-jwt-pid"], async (req, res) => {
},
},
});
});



} else {
res.json({
credential_issuer: serverURL,
credentials: ["PID"],
grants: {
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": req.params.id + "-persona=" + persona,
user_pin_required: true,
},
},
});
}
});

export default pidRouter;
export default pidRouter;
129 changes: 112 additions & 17 deletions routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ router.get(["/credential-offer-pre-jwt/:id"], (req, res) => {
});
});

function getPersonaPart(inputString) {
const personaKey = "persona=";
const personaIndex = inputString.indexOf(personaKey);

if (personaIndex === -1) {
return null; // "persona=" not found in the string
}

// Split the string based on "persona="
const parts = inputString.split(personaKey);

// Return the part after "persona="
return parts[1] || null;
}

router.post("/token_endpoint", async (req, res) => {
//pre-auth code flow
const grantType = req.body.grant_type;
Expand All @@ -137,6 +152,8 @@ router.post("/token_endpoint", async (req, res) => {
// console.log(userPin);
// console.log("---------");

let generatedAccessToken = buildAccessToken(serverURL, privateKey);

if (grantType == "urn:ietf:params:oauth:grant-type:pre-authorized_code") {
console.log("pre-auth code flow");
const preSessions = getPreCodeSessions();
Expand All @@ -146,6 +163,15 @@ router.post("/token_endpoint", async (req, res) => {
`credential for session ${preAuthorizedCode} has been issued`
);
preSessions.results[index].status = "success";
preSessions.accessTokens[index] = generatedAccessToken;

let personaId = getPersonaPart(preAuthorizedCode);
if (personaId) {
preSessions.personas[index] = personaId;
} else {
preSessions.personas[index] = null;
}

// console.log("pre-auth code flow" + preSessions.results[index].status);
}
} else {
Expand All @@ -161,7 +187,7 @@ router.post("/token_endpoint", async (req, res) => {
}
//TODO return error if code flow validation fails and is not a pre-auth flow
res.json({
access_token: buildAccessToken(serverURL, privateKey),
access_token: generatedAccessToken,
refresh_token: generateRefreshToken(),
token_type: "bearer",
expires_in: 86400,
Expand All @@ -178,7 +204,7 @@ router.post("/credential", async (req, res) => {
// Accessing the body data
const requestBody = req.body;
const format = requestBody.format;
const requestedCredentials = requestBody.types || requestBody.credential_definition.type;
const requestedCredentials = requestBody.credential_definition.type; //removed requestBody.types to conform to RFC001
//TODO valiate bearer header
let decodedWithHeader;
let decodedHeaderSubjectDID;
Expand All @@ -193,6 +219,79 @@ router.post("/credential", async (req, res) => {
if (format === "jwt_vc") {
let payload = {};
if (requestedCredentials != null && requestedCredentials[0] === "PID") {
//get persona if existing from accessToken
const preSessions = getPreCodeSessions();
let persona = getPersonaFromAccessToken(
token,
preSessions.personas,
preSessions.accessTokens
);

let credentialSubject = {
id: decodedHeaderSubjectDID,
family_name: "Doe",
given_name: "John",
birth_date: "1990-01-01",
age_over_18: true,
issuance_date: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expiry_date: new Date(
Math.floor(Date.now() + 60 / 1000) * 1000
).toISOString(),
issuing_authority: "https://authority.example.com",
issuing_country: "GR",
};
if (persona === "1") {
credentialSubject = {
id: decodedHeaderSubjectDID,
family_name: "Conti",
given_name: "Mario",
birth_date: "1988-11-12",
age_over_18: true,
issuance_date: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expiry_date: new Date(
Math.floor(Date.now() + 60 / 1000) * 1000
).toISOString(),
issuing_authority: "https://authority.example.com",
issuing_country: "IT",
};
} else if (persona === "2") {
credentialSubject = {
id: decodedHeaderSubjectDID,
family_name: "Matkalainen",
given_name: "Hannah",
birth_date: "2005-02-07",
age_over_18: true,
issuance_date: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expiry_date: new Date(
Math.floor(Date.now() + 60 / 1000) * 1000
).toISOString(),
issuing_authority: "https://authority.example.com",
issuing_country: "FI",
};
} else if (persona === "3") {
credentialSubject = {
id: decodedHeaderSubjectDID,
family_name: "Fischer",
given_name: "Felix",
birth_date: "1953-01-23",
age_over_18: true,
issuance_date: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expiry_date: new Date(
Math.floor(Date.now() + 60 / 1000) * 1000
).toISOString(),
issuing_authority: "https://authority.example.com",
issuing_country: "FI",
};
}

payload = {
iss: serverURL,
sub: decodedHeaderSubjectDID || "",
Expand All @@ -201,21 +300,7 @@ router.post("/credential", async (req, res) => {
// nbf: Math.floor(Date.now() / 1000),
jti: "urn:did:1904a925-38bd-4eda-b682-4b5e3ca9d4bc",
vc: {
credentialSubject: {
id: decodedHeaderSubjectDID,
family_name: "Doe",
given_name: "John",
birth_date: "1990-01-01",
age_over_18: true,
issuance_date: new Date(
Math.floor(Date.now() / 1000) * 1000
).toISOString(),
expiry_date: new Date(
Math.floor(Date.now() + 60 / 1000) * 1000
).toISOString(),
issuing_authority: "https://authority.example.com",
issuing_country: "GR",
},
credentialSubject: credentialSubject,
expirationDate: new Date(
(Math.floor(Date.now() / 1000) + 60 * 60) * 1000
).toISOString(),
Expand Down Expand Up @@ -638,6 +723,16 @@ function checkIfExistsIssuanceStatus(
return null;
}

function getPersonaFromAccessToken(accessToken, personas, accessTokens) {
let persona = null;
for (let i = 0; i < accessTokens.length; i++) {
if (accessTokens[i] === accessToken) {
persona = personas[i];
}
}
return persona;
}

async function validatePKCE(sessions, code, code_verifier, issuanceResults) {
for (let i = 0; i < sessions.length; i++) {
let element = sessions[i];
Expand Down
6 changes: 4 additions & 2 deletions services/cacheService.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
let sessions = [];
let issuanceResults = [];
let personas = [];
let accesTokens = [];

let walletCodeSessions = [];
let issuerCodeSessions = [];
Expand All @@ -10,6 +12,8 @@ export function getPreCodeSessions() {
return {
sessions: sessions,
results: issuanceResults,
personas: personas,
accessTokens: accesTokens,
};
}

Expand All @@ -21,5 +25,3 @@ export function getAuthCodeSessions() {
results: codeFlowRequestsResults,
};
}


0 comments on commit 75969c8

Please sign in to comment.