Files
DLE/backend/server.js

196 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import express from 'express';
import cors from 'cors';
import session from 'express-session';
import { SiweMessage, generateNonce } from 'siwe';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
// Конфигурация CORS для работы с frontend
app.use(cors({
origin: ['http://localhost:5174', 'http://127.0.0.1:5173', 'http://localhost:5173'],
credentials: true,
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Accept']
}));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Настройка сессий
app.use(session({
name: 'siwe-dapp',
secret: "siwe-dapp-secret",
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
sameSite: 'lax',
maxAge: 24 * 60 * 60 * 1000 // 24 часа
}
}));
// Логирование запросов
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
// Генерация nonce
app.get('/nonce', (req, res) => {
try {
req.session.nonce = generateNonce();
console.log('Сгенерирован новый nonce:', req.session.nonce);
res.setHeader('Content-Type', 'application/json');
res.status(200).json({ nonce: req.session.nonce });
} catch (error) {
console.error('Ошибка генерации nonce:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
// Верификация сообщения
app.post('/verify', async (req, res) => {
try {
const { signature, message } = req.body;
console.log('Получен запрос на верификацию:', {
signature: signature?.slice(0, 20) + '...',
message,
sessionNonce: req.session.nonce
});
if (!req.session.nonce) {
console.error('Сессия не содержит nonce');
throw new Error('Invalid session');
}
if (!signature || !message) {
console.error('Отсутствует подпись или сообщение');
throw new Error('Invalid signature or message');
}
// Создаем и верифицируем SIWE сообщение
console.log('Начинаем парсинг SIWE сообщения...');
const siweMessage = new SiweMessage(message);
console.log('Парсинг успешен:', {
domain: siweMessage.domain,
address: siweMessage.address,
nonce: siweMessage.nonce
});
const { success, data: fields } = await siweMessage.verify({
signature,
domain: siweMessage.domain,
nonce: req.session.nonce
});
console.log('Результат верификации:', { success, fields });
if (!success) {
throw new Error('Signature verification failed');
}
// Сохраняем сессию
req.session.authenticated = true;
req.session.siwe = fields;
console.log('Сессия сохранена:', {
authenticated: true,
address: fields.address
});
req.session.save(() => {
console.log('Session saved successfully');
res.status(200).json({
success: true,
address: fields.address
});
});
} catch (error) {
console.error('Ошибка верификации:', error);
req.session.authenticated = false;
req.session.nonce = null;
req.session.siwe = null;
res.status(400).json({
error: 'Verification failed',
message: error.message
});
}
});
// Получение сессии
app.get('/session', (req, res) => {
try {
res.json({
authenticated: !!req.session.authenticated,
address: req.session.siwe?.address
});
} catch (error) {
console.error('Ошибка получения сессии:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
// Выход
app.get('/signout', (req, res) => {
try {
req.session.destroy((err) => {
if (err) {
console.error('Ошибка при удалении сессии:', err);
return res.status(500).json({ error: 'Failed to destroy session' });
}
res.status(200).json({ success: true });
});
} catch (error) {
console.error('Ошибка выхода:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
// Базовый маршрут
app.get('/', (req, res) => {
res.json({
status: 'ok',
endpoints: {
nonce: 'GET /nonce',
verify: 'POST /verify',
session: 'GET /session',
signout: 'GET /signout'
}
});
});
// Обработка 404
app.use((req, res) => {
console.log(`404: ${req.method} ${req.url}`);
res.status(404).json({
error: 'Not Found',
message: `Endpoint ${req.method} ${req.url} не существует`
});
});
// Обработка ошибок
app.use((err, req, res, next) => {
console.error('Ошибка сервера:', err);
res.status(500).json({
error: 'Internal Server Error',
message: err.message
});
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`SIWE сервер запущен на порту ${PORT}`);
console.log('Доступные эндпоинты:');
console.log(' GET / - Информация о сервере');
console.log(' GET /nonce - Получить nonce');
console.log(' POST /verify - Верифицировать сообщение');
console.log(' GET /session - Получить текущую сессию');
console.log(' GET /signout - Выйти из системы');
});