-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
164 lines (133 loc) · 4.61 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
const express = require("express");
const { auth, resolver, loaders } = require("@iden3/js-iden3-auth");
const getRawBody = require("raw-body");
const { Server } = require("socket.io");
const cors = require("cors");
const path = require("path");
const { humanReadableAuthReason, proofRequest } = require("./proofRequest");
require("dotenv").config();
const app = express();
const port = 8080;
app.use(
cors({
origin: process.env.FRONTEND_URL,
})
);
app.get("/", (req, res) => {
res.send(
`Welcome to your backend Polygon ID verifier server! There are ${
Object.keys(apiPath).length
} routes available: ${Object.values(apiPath).join(" and ")}.`
);
});
const server = app.listen(port, () => {
console.log(`server running on port ${port}`);
});
const io = new Server(server, {
cors: {
origin: process.env.FRONTEND_URL,
},
});
// save auth qr requests
const authRequests = new Map();
const apiPath = {
getAuthQr: "/api/get-auth-qr",
handleVerification: "/api/verification-callback",
};
app.get(apiPath.getAuthQr, (req, res) => {
getAuthQr(req, res);
});
app.post(apiPath.handleVerification, (req, res) => {
handleVerification(req, res);
});
const STATUS = {
IN_PROGRESS: "IN_PROGRESS",
ERROR: "ERROR",
DONE: "DONE",
};
const socketMessage = (fn, status, data) => ({
fn,
status,
data,
});
// GetQR returns auth request
async function getAuthQr(req, res) {
const sessionId = req.query.sessionId;
console.log(`getAuthQr for ${sessionId}`);
io.sockets.emit(
sessionId,
socketMessage("getAuthQr", STATUS.IN_PROGRESS, sessionId)
);
const uri = `${process.env.HOSTED_SERVER_URL}${apiPath.handleVerification}?sessionId=${sessionId}`;
// Generate request for basic authentication
// https://0xpolygonid.github.io/tutorials/verifier/verification-library/request-api-guide/#createauthorizationrequest
const request = auth.createAuthorizationRequest(
humanReadableAuthReason,
process.env.VERIFIER_DID,
uri
);
request.id = sessionId;
request.thid = sessionId;
const scope = request.body.scope ?? [];
request.body.scope = [...scope, proofRequest];
// store this session's auth request
authRequests.set(sessionId, request);
io.sockets.emit(sessionId, socketMessage("getAuthQr", STATUS.DONE, request));
return res.status(200).set("Content-Type", "application/json").send(request);
}
// handleVerification verifies the proof after get-auth-qr callbacks
async function handleVerification(req, res) {
const sessionId = req.query.sessionId;
// get this session's auth request for verification
const authRequest = authRequests.get(sessionId);
console.log(`handleVerification for ${sessionId}`);
io.sockets.emit(
sessionId,
socketMessage("handleVerification", STATUS.IN_PROGRESS, authRequest)
);
// get JWZ token params from the post request
const raw = await getRawBody(req);
const tokenStr = raw.toString().trim();
// The CredentialAtomicQuerySigValidator contract is used to verify any credential-related zk proof
// generated by the user using the credentialAtomicQuerySigV2OnChain circuit.
// https://0xpolygonid.github.io/tutorials/contracts/overview/#blockchain-addresses
const mumbaiContractAddress = "0x1a4cC30f2aA0377b0c3bc9848766D90cb4404124";
const keyDIR = "./keys";
const amoyStateResolver = new resolver.EthStateResolver(
process.env.RPC_URL_AMOY,
mumbaiContractAddress
);
const resolvers = {
["polygon:amoy"]: amoyStateResolver,
};
const verifier = await auth.Verifier.newVerifier({
stateResolver: resolvers,
circuitsDir: path.join(__dirname, keyDIR),
ipfsGatewayURL: "https://ipfs.io",
});
try {
const opts = {
AcceptedStateTransitionDelay: 5 * 60 * 1000, // up to a 5 minute delay accepted by the Verifier
};
authResponse = await verifier.fullVerify(tokenStr, authRequest, opts);
const userId = authResponse.from;
io.sockets.emit(
sessionId,
socketMessage("handleVerification", STATUS.DONE, authResponse)
);
return res
.status(200)
.set("Content-Type", "application/json")
.send("User " + userId + " succesfully authenticated");
} catch (error) {
console.log(
"Error handling verification: Double check the value of your RPC_URL_MUMBAI in the .env file. Are you using a valid api key for Polygon Mumbai from your RPC provider? Visit https://alchemy.com/?r=zU2MTQwNTU5Mzc2M and create a new app with Polygon Mumbai"
);
console.log("handleVerification error", sessionId, error);
io.sockets.emit(
sessionId,
socketMessage("handleVerification", STATUS.ERROR, error)
);
return res.status(500).send(error);
}
}