Skip to content

Commit

Permalink
Merge pull request #3 from proofcarryingdata/feat/server-verification
Browse files Browse the repository at this point in the history
Server-side PCD verification
  • Loading branch information
cedoor authored Sep 4, 2023
2 parents c5b0bb5 + e56c43f commit df1d2f4
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 80 deletions.
93 changes: 50 additions & 43 deletions apps/client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,82 @@
import { deserialize, EdDSAPCDPackage, init as initEdDSAPCD, verify } from "@pcd/eddsa-pcd"
import { EdDSAPCDPackage } from "@pcd/eddsa-pcd"
import { getWithoutProvingUrl, openPassportPopup, usePassportPopupMessages } from "@pcd/passport-interface"
import { useCallback, useEffect, useState } from "react"

/**
* This component consumes a message signed with an EdDSA key. If you have provided a valid signature,
* it uses the color as the background of the web app page. This background is preserved as long as
* you do not consume a signature on a different colour.
* This page allows users to get an EdDSA PCD containing a color as a message signed by
* the issuer. If the signature is valid the color is stored in the server and the background color
* of this page will be changed.
*/
export default function App() {
const [passportPCDString] = usePassportPopupMessages()
const [bgColor, setBgColor] = useState<string>()

// Get the latest color stored in the server.
useEffect(() => {
// Get the color extracted from the latest valid message signed with an EdDSA key.
const getLatestConsumedColor = async () => {
const response = await fetch(`http://localhost:${process.env.SERVER_PORT}/color/get`, {
;(async () => {
const response = await fetch(`http://localhost:${process.env.SERVER_PORT}/color`, {
method: "GET",
mode: "cors"
})

if (!!response.ok) {
const body = await response.json()
setBgColor(body.color)
if (response.status === 404) {
return
}
}

getLatestConsumedColor()
}, [])
if (!response.ok) {
alert("Some error occurred")
return
}

useEffect(() => {
// Update the background color accordingly to color change.
const appElement = document.getElementById("app")!
const { color } = await response.json()

appElement.style.backgroundColor = `#${bgColor}`
}, [bgColor])
setBgColor(color)
})()
}, [])

// Store the color in the server if its PCD is valid
// and then updates the background color of this page.
useEffect(() => {
;(async () => {
await initEdDSAPCD()

if (passportPCDString) {
const { pcd: serializedPCD } = JSON.parse(passportPCDString)

const pcd = await deserialize(serializedPCD)

if (await verify(pcd)) {
// Get PCD claim (color).
const color = pcd.claim.message[0].toString(16)

// Store consumed color on the server.
await fetch(`http://localhost:${process.env.SERVER_PORT}/color/set`, {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
color: color
})
const { pcd } = JSON.parse(passportPCDString)

const response = await fetch(`http://localhost:${process.env.SERVER_PORT}/color`, {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
pcd
})
})

alert(`The signature is valid, #${color} will be used as a background color!`)
if (!response.ok) {
alert("Some error occurred")
return
}

const { color } = await response.json()

setBgColor(color)
} else {
alert(`The signature is not valid!`)
if (bgColor === color) {
alert("The color is the same as the current one")
return
}

setBgColor(color)
}
})()
}, [passportPCDString])

// Update the background color.
useEffect(() => {
const appElement = document.getElementById("app")!

appElement.style.backgroundColor = bgColor
}, [bgColor])

// Get the EdDSA PCD with the color signed by the issuer.
const getEdDSAPCD = useCallback(() => {
const url = getWithoutProvingUrl(
process.env.PCDPASS_URL as string,
Expand All @@ -80,5 +87,5 @@ export default function App() {
openPassportPopup("/popup", url)
}, [])

return <button onClick={getEdDSAPCD}>Get PCD signature</button>
return <button onClick={getEdDSAPCD}>Get a PCD signature with your color</button>
}
2 changes: 2 additions & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "server",
"type": "module",
"version": "0.1.0",
"main": "src/index.ts",
"packageManager": "[email protected]",
Expand All @@ -8,6 +9,7 @@
"start": "ts-node --esm src/index.ts"
},
"dependencies": {
"@pcd/eddsa-pcd": "^0.1.1",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2"
Expand Down
91 changes: 54 additions & 37 deletions apps/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,77 @@
import express, { Express, Request, Response } from 'express';
import dotenv from "dotenv"
import { deserialize, init as initEdDSAPCD, verify } from "@pcd/eddsa-pcd"
import cors from "cors"
import dotenv from "dotenv"
import express, { Express, Request, Response } from "express"

dotenv.config({ path: `${process.cwd()}/../../.env` })

const app: Express = express();
const port = process.env.SERVER_PORT || 3000;
// The PCD package must be initialized before using its methods.
await initEdDSAPCD()

const app: Express = express()
const port = process.env.SERVER_PORT || 3000

// Middlewares.
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(cors())

app.get('/', (req: Request, res: Response) => {
res.send('Express + TypeScript Server');
});
app.get("/", (_req: Request, res: Response) => {
res.send("Express + TypeScript Server")
})

// Store a color on a NodeJS environment variable.
app.post('/color/set', (req: Request, res: Response) => {
try {
if (!req.body.color) {
console.error(`[ERROR] No color specified!`)
app.post("/color", async (req: Request, res: Response) => {
try {
if (!req.body.pcd) {
console.error(`[ERROR] No PCD specified`)

res.status(400).send()
return
}

const pcd = await deserialize(req.body.pcd)

res.status(400).send()
} else {
// Set the color on NodeJS `COLOR` environment variable.
process.env['COLOR'] = req.body.color;
if (!(await verify(pcd))) {
console.error(`[ERROR] PCD is not valid`)

console.debug(`[OKAY] color has been set to ${process.env.COLOR}`)
res.status(401).send()
return
}

res.status(200).send()
// Set the color on NodeJS `COLOR` environment variable.
process.env.COLOR = `#${pcd.claim.message[0].toString(16)}`

console.debug(`[OKAY] color has been set to ${process.env.COLOR}`)

res.json({ color: process.env.COLOR }).status(200).send()
} catch (error: any) {
console.error(`[ERROR] ${error}`)

res.send(500)
}
} catch (error: any) {
console.error(`[ERROR] ${error}`)
res.send(500)
}
});
})

// Get the color stored on the NodeJS environment variable.
app.get('/color/get', (req: Request, res: Response) => {
try {
if (!process.env.COLOR) {
console.error(`[ERROR] No color has been saved yet!`)
app.get("/color", (_req: Request, res: Response) => {
try {
if (!process.env.COLOR) {
console.error(`[ERROR] No color has been stored yet`)

res.status(404).send()
return
}

console.debug(`[OKAY] color ${process.env.COLOR} has been successfully sent`)

res.status(404).send()
} else {
console.debug(`[OKAY] color ${process.env.COLOR} has been successfully sent`)
res.json({ color: process.env.COLOR }).status(200)
} catch (error: any) {
console.error(`[ERROR] ${error}`)

res.json({ color: process.env.COLOR }).status(200);
res.send(500)
}
} catch (error: any) {
console.error(`[ERROR] ${error}`)
res.send(500)
}
});
})

app.listen(port, () => {
console.log(`⚡️[server]: Server is running at http://localhost:${port}`);
});
console.log(`⚡️[server]: Server is running at http://localhost:${port}`)
})
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6116,6 +6116,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "server@workspace:apps/server"
dependencies:
"@pcd/eddsa-pcd": ^0.1.1
"@types/cors": ^2.8.13
"@types/dotenv": ^8.2.0
"@types/express": ^4.17.17
Expand Down

0 comments on commit df1d2f4

Please sign in to comment.