UNPKG

nostr-dm-magiclink-utils

Version:

A comprehensive Nostr utility library for magic link authentication via direct messages, supporting both ESM and CommonJS. Features NIP-01/04 compliant message encryption, multi-relay support, internationalization (i18n) with RTL support, and TypeScript-f

119 lines (95 loc) 3.23 kB
import express from 'express'; import { NostrCrypto, NostrEvent } from 'nostr-crypto-utils'; import { randomBytes } from 'crypto'; const app = express(); app.use(express.json()); // In-memory store for platform registrations (use a proper database in production) const platforms = new Map<string, { pubkey: string; delegatedEvent: NostrEvent; expiresAt: number; }>(); // Generate a secure platform ID const generatePlatformId = () => { return randomBytes(16).toString('hex'); }; // Initialize NostrCrypto const nostrCrypto = new NostrCrypto(); // Generate or load your service keys (in production, use secure key management) const SERVICE_PRIVKEY = process.env.SERVICE_PRIVKEY || nostrCrypto.generatePrivateKey(); const SERVICE_PUBKEY = nostrCrypto.getPublicKey(SERVICE_PRIVKEY); // Register a new platform app.post('/register', async (req, res) => { const { platformPubkey } = req.body; if (!platformPubkey) { return res.status(400).json({ error: 'Platform public key required' }); } try { // Generate delegation event valid for 30 days const expiresAt = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); // Create delegation event const delegationEvent = await nostrCrypto.createDelegationEvent({ delegator: SERVICE_PUBKEY, delegatee: platformPubkey, allowedEventKinds: [4], // Only allow DM events expiresAt }); // Sign the delegation event const signedEvent = await nostrCrypto.signEvent(delegationEvent, SERVICE_PRIVKEY); // Generate platform ID const platformId = generatePlatformId(); // Store platform details platforms.set(platformId, { pubkey: platformPubkey, delegatedEvent: signedEvent, expiresAt }); // Return platform credentials res.json({ platformId, servicePubkey: SERVICE_PUBKEY, delegationEvent: signedEvent, expiresAt }); } catch (error) { console.error('Failed to create delegation:', error); res.status(500).json({ error: 'Failed to create delegation' }); } }); // Revoke a platform's access app.post('/revoke', (req, res) => { const { platformId } = req.body; if (!platformId || !platforms.has(platformId)) { return res.status(404).json({ error: 'Platform not found' }); } platforms.delete(platformId); res.json({ success: true }); }); // Get platform status app.get('/platform/:platformId', (req, res) => { const { platformId } = req.params; const platform = platforms.get(platformId); if (!platform) { return res.status(404).json({ error: 'Platform not found' }); } res.json({ pubkey: platform.pubkey, expiresAt: platform.expiresAt, isExpired: platform.expiresAt < (Date.now() / 1000) }); }); // Cleanup expired tokens (run periodically) const cleanupExpiredTokens = () => { const now = Date.now() / 1000; for (const [platformId, platform] of platforms.entries()) { if (platform.expiresAt < now) { platforms.delete(platformId); } } }; // Run cleanup every hour setInterval(cleanupExpiredTokens, 60 * 60 * 1000); const port = process.env.PORT || 3001; app.listen(port, () => { console.log(`Delegation service running at http://localhost:${port}`); });