The code below still works as of June 2023, but for the best developer experience, use my fullstack template instead - fullstack-polygon-id-vc-gated-dapp - It includes both the server and frontend and is everything you need to set up a KYCAgeCredential VC gated dapp with Polygon ID.
(use above repo)
This repo contains the server code you'll need to set up a VC (Verifiable Credential) gated website with Polygon ID. Complete local server setup below, then hook this verification server up to a frontend so you can limit access based on holding a VC that satisifies your requirements.
- Part 1: VC Verifier Server
- github repo: this page!
- server hosted: https://vc-birthday-server.onrender.com
- Part 2: Frontend
- github repo: https://github.com/oceans404/vc-gated-website
- website: https://birthday-gated-website.on.fleek.co
-
Allows Socket.io polling to emit session specific events back to connected clients
-
Generates a Query Based Request in the form of a QR code that the user can scan to prove they own a credential that satisfies certain requirements. It also specifies the callback endpoint for verification
-
Reports Verification of the proof sent by the user from their Polygon ID Wallet via callback
git clone https://github.com/oceans404/vc-verifier
cd vc-verifier
npm i
In your .env file,
cp .env.sample .env;
- Update the
RPC_URL_MUMBAI
to a Polygon Mumbai RPC endpoint. I used Alchemy's - Optionally update the
VERIFIER_DID
to your DID - Don't change
HOSTED_SERVER_URL
orCLIENT_URL
yet
node index.js
If you don't have ngrok already set up, install ngrok via homebrew or download. Login (I used github login) to create a free account and add your account's config token to the command line.
After ngrok is set up, start a tunnel to port 3000 to expose your server to the internet beyond only being available to your laptop on localhost:3000. This is necessary because the Polygon ID mobile wallet app will use a verfication uri you provide and needs to be able to send the verification result to this exposed public endpoint.
ngrok http 3000
You'll see a forwarding address in the logs
Forwarding https://abc-your-forwarding-address-def.ngrok-free.app -> http://localhost:3000
HOSTED_SERVER_URL="https://abc-your-forwarding-address-def.ngrok-free.app"
6. Optionally customize your own proof request by changing the credentialSubject in proofRequest.js
ex 1: User must have Taylor Swift's exact birthday - December 13, 1989
{
birthday: {
$eq: 19891213,
},
};
ex 2: User's KYCAgeCredential documentType must be greater than 420
{
documentType: {
$gt: 420,
},
};
default: proofRequest
If you don't customize proofRequest.js
, this server will send a verification request for an KYCAgeCredential proof with a birthday before January 1, 2023 to the credentialAtomicQuerySigV2 circuit. This circuit is specified by the circuitId in vcHelpers/KYCAgeCredential.js
, set to credentialAtomicQuerySigV2.
{
birthday: {
// users must be born before this year
// birthday is less than Jan 1, 2023
$lt: 20230101,
},
};
![proof](https://private-user-images.githubusercontent.com/91382964/243771439-ab18d8a6-ca14-4503-b7cf-c4bac8ccd869.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxMDA0NTksIm5iZiI6MTcyNDEwMDE1OSwicGF0aCI6Ii85MTM4Mjk2NC8yNDM3NzE0MzktYWIxOGQ4YTYtY2ExNC00NTAzLWI3Y2YtYzRiYWM4Y2NkODY5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE5VDIwNDIzOVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJiZmE5OWQwMzIxNzhmMTFjMzE3YmFiYjc3NWY4Nzk1ZDBhN2YxY2IzZThiNTgyOGJlMWY2OTNlMGUzMTA2YzMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.DLb4oRNk5BAfjt8wgIQgxszKrdwyl4jWCch5ObzGd0Y)
The credentialAtomicQuerySigV2 circuit
- Verifies that the prover (your user) is owner of a VC with the KYCAgeCredential type
- Verifies that the identity is the subject of the claim
- Verifies that the claim was signed by the issuer
- Verifies that the claim schema matches the one in the query
- Verifies that the claim is not revoked by the issuer and is not expired
- Verifies that the query posed by the verifier is satisfied by the claim. The check,
$lt: 20230101
, written in Query Language verifies that thebirthday
credentialSubject is less than 20230101 or that the user's birthday is before Jan 1, 2023. In human terms, the user "Must be born before this year."
If all these are satisfied by the verifier, an authResponse with fields for did_doc and scope containing the valid proof will be returned via the handleVerification callback function. ๐
You are currently running the server on localhost and forwarding to ngrok to expose it to the internet.
If you'd like to host the server, you can use something like Render, documented by me here. Connect your repo, then make sure to add all your environment variables from .env. Update the HOSTED_SERVER_URL environment variable to match the server domain created by Render. Mine is https://vc-birthday-server.onrender.com
![Screenshot 2023-06-06 at 11 11 06 AM](https://private-user-images.githubusercontent.com/91382964/243789027-dff0176b-1bb2-4c1f-b97c-7c2b50c03737.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxMDA0NTksIm5iZiI6MTcyNDEwMDE1OSwicGF0aCI6Ii85MTM4Mjk2NC8yNDM3ODkwMjctZGZmMDE3NmItMWJiMi00YzFmLWI5N2MtN2MyYjUwYzAzNzM3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE5VDIwNDIzOVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTZhZDAyNjYzNGI4OGI3OWY4ZWQ4MjU4ZTFjYzdmNTE4MDc3MjZjNjg1ZDVhZDkwOGU0ZjIyZDg4MTA0ZWQ1YjEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Ys4y6uWSuIreJMvjIWxJK4q8qrhmTcOgQbwzyKooRjQ)
Note: You'll run into CORS errors if you try to hit the server from any frontend other than the one matching the CLIENT_URL environment variable you set. For example, once you host your frontend using Vercel or Fleek, and you're no longer connecting from localhost:8080, you'll have to update the CLIENT_URL variable on Render to match.
https://github.com/oceans404/vc-verifier/blob/main/.env.sample#L1
This repo covers server setup. Next hook the server up to a frontend using this code:
- frontend github repo: https://github.com/oceans404/vc-gated-website
- hosted frontend website: https://birthday-gated-website.on.fleek.co
- additional instructions on how to get a KYCAgeCredential Verifiable Credential and interact with the frontend: https://www.notion.so/oceans404/How-to-get-a-KYCAgeCredential-Verifiable-Credential-f3d34e7c98ec4147b6b2fae79066c4f6?pvs=4
The keys folder holds the authV2, credentialAtomicQueryMTPV2, and credentialAtomicQuerySigV2 public verification keys necessary to verify a zero-knowledge proof. You can optionally verify these keys by following instructions here
Here's the corresponding Iden3 circuit code