Skip to content

Commit d1112c4

Browse files
committed
JS docs update
1 parent 96653f3 commit d1112c4

File tree

15 files changed

+5012
-0
lines changed

15 files changed

+5012
-0
lines changed

content/docs/js-sdk/api-reference.mdx

Lines changed: 472 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
---
2+
title: Backend Verification
3+
description: Server-side proof verification patterns and best practices
4+
---
5+
6+
## Overview
7+
8+
Backend verification is the process of cryptographically validating proofs received from the Reclaim Protocol after users complete verification. This ensures the authenticity and integrity of the verified data before using it in your application.
9+
10+
<Callout type="success">
11+
**Why Backend Verification is Critical**
12+
13+
Always verify proofs on your backend before trusting the data. Client-side verification alone can be bypassed, but cryptographic verification on your server ensures authenticity.
14+
</Callout>
15+
16+
## Quick Start
17+
18+
For complete backend verification implementations, see:
19+
20+
- **[Node.js / Express Setup →](/js-sdk/recommended-setup/nodejs)** - Complete backend with Express.js
21+
- **[Next.js Setup →](/js-sdk/recommended-setup/nextjs)** - API routes and verification
22+
- **[Python Setup →](/js-sdk/recommended-setup/python)** - FastAPI and Django examples
23+
24+
## Verification Process
25+
26+
### 1. Receive Proof
27+
28+
Proofs are sent to your callback URL as URL-encoded JSON:
29+
30+
```javascript
31+
// Express.js
32+
app.use(express.text({ type: '*/*', limit: '50mb' }));
33+
34+
app.post('/api/reclaim/callback', async (req, res) => {
35+
const decodedBody = decodeURIComponent(req.body);
36+
const proof = JSON.parse(decodedBody);
37+
// ...
38+
});
39+
```
40+
41+
### 2. Verify Proof
42+
43+
Use the `verifyProof()` function to cryptographically verify:
44+
45+
```javascript
46+
import { verifyProof } from '@reclaimprotocol/js-sdk';
47+
48+
const isValid = await verifyProof(proof);
49+
50+
if (isValid) {
51+
console.log('✅ Proof is valid');
52+
// Process verified data
53+
} else {
54+
console.log('❌ Proof verification failed');
55+
// Reject the proof
56+
}
57+
```
58+
59+
### 3. Extract Data
60+
61+
Once verified, extract the data you need:
62+
63+
```javascript
64+
if (isValid) {
65+
const verifiedData = {
66+
identifier: proof.identifier,
67+
provider: JSON.parse(proof.claimData.context).extractedParameters.providerName,
68+
timestamp: new Date(proof.timestampS * 1000),
69+
// Extract more fields based on your provider
70+
};
71+
72+
// YOUR BUSINESS LOGIC HERE
73+
// - Save to database
74+
// - Update user status
75+
// - Trigger workflows
76+
}
77+
```
78+
79+
## Complete Example (Node.js)
80+
81+
```javascript
82+
const express = require('express');
83+
const { ReclaimProofRequest, verifyProof } = require('@reclaimprotocol/js-sdk');
84+
85+
const app = express();
86+
app.use(express.text({ type: '*/*', limit: '50mb' }));
87+
88+
// Callback endpoint
89+
app.post('/api/reclaim/callback', async (req, res) => {
90+
try {
91+
// Parse proof
92+
const decodedBody = decodeURIComponent(req.body);
93+
const proof = JSON.parse(decodedBody);
94+
95+
console.log('📨 Received proof:', proof.identifier);
96+
97+
// Verify proof
98+
const isValid = await verifyProof(proof);
99+
100+
if (!isValid) {
101+
console.error('❌ Proof verification failed');
102+
return res.status(400).json({ error: 'Invalid proof' });
103+
}
104+
105+
console.log('✅ Proof verified successfully');
106+
107+
// Extract verified data
108+
const context = JSON.parse(proof.claimData.context);
109+
const verifiedData = {
110+
proofId: proof.identifier,
111+
provider: context.extractedParameters.providerName,
112+
verifiedAt: new Date(proof.timestampS * 1000),
113+
};
114+
115+
// Save to database (example)
116+
// await db.verifications.create(verifiedData);
117+
118+
// Update user status (example)
119+
// await db.users.update({ verified: true });
120+
121+
return res.json({ success: true });
122+
} catch (error) {
123+
console.error('❌ Error processing proof:', error);
124+
return res.status(500).json({ error: 'Internal server error' });
125+
}
126+
});
127+
128+
app.listen(3000, () => {
129+
console.log('Server running on port 3000');
130+
});
131+
```
132+
133+
## Complete Example (Python)
134+
135+
```python
136+
from fastapi import FastAPI, Request
137+
from reclaim_python_sdk import verify_proof, Proof
138+
import json
139+
from urllib.parse import unquote
140+
141+
app = FastAPI()
142+
143+
@app.post("/api/reclaim/callback")
144+
async def receive_proofs(request: Request):
145+
try:
146+
# Parse proof
147+
body = await request.body()
148+
body_str = body.decode('utf-8')
149+
body_str = unquote(body_str)
150+
parsed_data = json.loads(body_str)
151+
152+
print(f"📨 Received proof: {parsed_data.get('identifier')}")
153+
154+
# Convert to Proof object
155+
proof = Proof.from_json(parsed_data)
156+
157+
# Verify proof
158+
is_valid = await verify_proof(proof)
159+
160+
if not is_valid:
161+
print("❌ Proof verification failed")
162+
return {"error": "Invalid proof"}, 400
163+
164+
print("✅ Proof verified successfully")
165+
166+
# Extract verified data
167+
verified_data = {
168+
"proof_id": proof.identifier,
169+
"provider": proof.claimData.provider,
170+
"verified_at": datetime.fromtimestamp(proof.timestampS)
171+
}
172+
173+
# Save to database (example)
174+
# await db.verifications.create(verified_data)
175+
176+
return {"success": True}
177+
178+
except Exception as error:
179+
print(f"❌ Error: {error}")
180+
return {"error": "Internal server error"}, 500
181+
```
182+
183+
## Proof Structure
184+
185+
Understanding the proof object structure:
186+
187+
```typescript
188+
{
189+
identifier: string; // Unique proof ID
190+
claimData: {
191+
provider: string; // Provider name
192+
parameters: string; // JSON string of parameters
193+
context: string; // JSON string with metadata
194+
};
195+
signatures: string[]; // Cryptographic signatures
196+
witnesses: [{ // Witness attestations
197+
address: string;
198+
signature: string;
199+
}];
200+
timestampS: number; // Unix timestamp (seconds)
201+
}
202+
```
203+
204+
## Security Best Practices
205+
206+
<Callout type="warning">
207+
**Critical Security Requirements**
208+
209+
1. **Always verify on backend** - Never trust client-side verification alone
210+
2. **Validate proof structure** - Check all required fields exist
211+
3. **Store proofs securely** - Use encrypted database storage
212+
4. **Check timestamps** - Reject old proofs (set expiration time)
213+
5. **Rate limit callbacks** - Prevent spam/DOS attacks
214+
6. **Use HTTPS** - Secure data in transit
215+
</Callout>
216+
217+
### Timestamp Validation
218+
219+
```javascript
220+
const MAX_AGE_SECONDS = 300; // 5 minutes
221+
222+
const isValid = await verifyProof(proof);
223+
const proofAge = Date.now() / 1000 - proof.timestampS;
224+
225+
if (isValid && proofAge <= MAX_AGE_SECONDS) {
226+
// Proof is valid and recent
227+
} else if (proofAge > MAX_AGE_SECONDS) {
228+
console.log('⚠️ Proof is too old');
229+
}
230+
```
231+
232+
### Proof Deduplication
233+
234+
```javascript
235+
// Check if proof was already processed
236+
const existingProof = await db.proofs.findOne({
237+
identifier: proof.identifier
238+
});
239+
240+
if (existingProof) {
241+
console.log('⚠️ Proof already processed');
242+
return res.status(409).json({ error: 'Proof already processed' });
243+
}
244+
245+
// Process and save new proof
246+
await db.proofs.create({ identifier: proof.identifier, ... });
247+
```
248+
249+
## Database Integration
250+
251+
### Save Verified Proofs
252+
253+
```javascript
254+
// Mongoose/MongoDB example
255+
const Verification = mongoose.model('Verification', {
256+
proofId: { type: String, unique: true },
257+
userId: String,
258+
provider: String,
259+
verifiedAt: Date,
260+
proofData: Object
261+
});
262+
263+
// In callback
264+
if (isValid) {
265+
await Verification.create({
266+
proofId: proof.identifier,
267+
userId: extractUserId(proof),
268+
provider: extractProvider(proof),
269+
verifiedAt: new Date(proof.timestampS * 1000),
270+
proofData: proof
271+
});
272+
}
273+
```
274+
275+
## Error Handling
276+
277+
```javascript
278+
app.post('/api/reclaim/callback', async (req, res) => {
279+
try {
280+
const proof = parseProof(req.body);
281+
282+
// Validate structure
283+
if (!proof || !proof.identifier || !proof.claimData) {
284+
return res.status(400).json({ error: 'Invalid proof structure' });
285+
}
286+
287+
// Verify cryptographically
288+
const isValid = await verifyProof(proof);
289+
290+
if (!isValid) {
291+
return res.status(400).json({ error: 'Proof verification failed' });
292+
}
293+
294+
// Process proof
295+
// ...
296+
297+
res.json({ success: true });
298+
} catch (error) {
299+
if (error instanceof SyntaxError) {
300+
return res.status(400).json({ error: 'Invalid JSON' });
301+
}
302+
303+
console.error('Error:', error);
304+
res.status(500).json({ error: 'Internal server error' });
305+
}
306+
});
307+
```
308+
309+
## Testing
310+
311+
### Manual Testing
312+
313+
```bash
314+
# Test your callback endpoint
315+
curl -X POST https://yourapp.com/api/reclaim/callback \
316+
-H "Content-Type: application/x-www-form-urlencoded" \
317+
-d '{"identifier":"test","claimData":{},"signatures":[],"witnesses":[],"timestampS":1234567890}'
318+
```
319+
320+
### Automated Testing
321+
322+
```javascript
323+
// Jest example
324+
describe('Proof Verification', () => {
325+
it('should verify valid proof', async () => {
326+
const mockProof = {
327+
identifier: 'test-proof-id',
328+
claimData: { ... },
329+
signatures: ['...'],
330+
witnesses: [{ ... }],
331+
timestampS: Date.now() / 1000
332+
};
333+
334+
const response = await request(app)
335+
.post('/api/reclaim/callback')
336+
.send(encodeURIComponent(JSON.stringify(mockProof)));
337+
338+
expect(response.status).toBe(200);
339+
});
340+
});
341+
```
342+
343+
## Next Steps
344+
345+
For complete implementation examples:
346+
347+
- **[Node.js Setup →](/js-sdk/recommended-setup/nodejs)** - Full Express.js backend
348+
- **[Next.js Setup →](/js-sdk/recommended-setup/nextjs)** - API routes implementation
349+
- **[Python Setup →](/js-sdk/recommended-setup/python)** - FastAPI/Django examples
350+
- **[API Reference →](/js-sdk/api-reference)** - Complete SDK documentation
351+
- **[Troubleshooting →](/js-sdk/troubleshooting)** - Common issues
352+
353+
## Need Help?
354+
355+
- 💬 [Community Discord](https://discord.gg/reclaim)
356+
- 🐛 [GitHub Issues](https://github.com/reclaimprotocol/reclaim-js-sdk/issues)

0 commit comments

Comments
 (0)