fix authentication + public key linked to socket.io

This commit is contained in:
Sam Hadow 2025-02-16 23:59:05 +01:00
parent 156a39f7cb
commit 1816cd3cf1
7 changed files with 73 additions and 19 deletions

View File

@ -16,6 +16,13 @@ const routes = require(__dirname + '/routes');
// session (used for login challenge)
const session = require('express-session');
const SQLiteStore = require('connect-sqlite3')(session);
const sessionMiddleware = session({
store: new SQLiteStore,
secret: process.env.COOKIE_SECRET || "toto",
resave: false,
saveUninitialized: true,
cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } // 1 week
});
// configure app
app.set("port", port);
@ -23,24 +30,24 @@ app.set('view engine', 'pug');
app.set('views', __dirname + '/views');
app.use(cookieParser());
app.use(express.json());
app.use(session({
store: new SQLiteStore,
secret: process.env.COOKIE_SECRET || "toto",
resave: false,
saveUninitialized: true,
cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } // 1 week
}));
app.use(sessionMiddleware);
app.use("/", routes);
// bootstrap
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'));
// socket.io
io.engine.use(sessionMiddleware);
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('disconnect', () => {
console.log('User disconnected');
});
const session = socket.request.session;
console.log('A user connected');
socket.on('disconnect', () => {
console.log('User disconnected');
});
socket.on('chat message', (msg) => {
console.log('message: ' + msg + ', sender: ' + session.id);
console.log(session.publicKey);
});
});

View File

@ -18,7 +18,6 @@ const authentication = {
msg
);
if (verified) {
console.log('Signature verified successfully with public key:', pemPubKey);
return pemPubKey;
}
} catch (err) {

View File

@ -36,13 +36,19 @@ const accountController = {
const { signature } = req.body;
const publicKeys = await database.getPublicKeys();
const msg = new TextEncoder().encode(req.session.randomNumber);
const sig = new TextEncoder().encode(signature);
let validKey = authentication.verifySignature(msg, sig, publicKeys);
const sig = Buffer.from(signature, 'base64');
let validKey = await authentication.verifySignature(msg, sig, publicKeys);
if (validKey !== null) {
req.session.publicKey = validKey;
socket.auth = { validKey };
socket.connect();
return res.status(200).json({ message: "Challenge solved successfully" });
req.session.save((err) => {
if (err) {
console.error("Error saving session:", err);
return res.status(500).json({ error: "Session save error" });
}
socket.auth = { validKey };
socket.connect();
return res.status(200).json({ message: "Challenge solved successfully" });
});
} else {
return res.status(400).json({ error: "Challenge failed" });
}

View File

@ -3,6 +3,7 @@ const path = require('path');
const mainController = {
root: (req, res) => {
let pubKey = req.session.publicKey;
console.log(pubKey);
let isLoggedIn = typeof pubKey !== 'undefined';
res.render('index', {isLoggedIn, pubKey});
},

View File

@ -3,7 +3,8 @@ import { io } from "socket.io-client";
const URL = "http://localhost:3333";
const socket = io(URL, {
autoConnect: false,
transports: ['websocket', 'polling']
transports: ['websocket', 'polling'],
withCredentials: true
});
// log during dev

View File

@ -45,6 +45,9 @@ html(lang="en-US")
.btn-group.mr-2(role="group", aria-label="logout")
a#logout.btn.btn-secondary(href="./account/logout") logout
p#pubkey #{pubKey}
ul#messages
form#form(action="")
@ -52,3 +55,4 @@ html(lang="en-US")
button Send

View File

@ -29,9 +29,45 @@ describe('authentication module', () => {
const result = await authentication.verifySignature(encodedData, signature, publicKeys);
expect(result).toBe(pemKey);
let fakeKey = `-----BEGIN PUBLIC KEY-----MCowBQYDK2VwAyEAmrBLT6lyiFh/eUticsIFNY6AkjXuQPqj0Qvb99pCJJk=-----END PUBLIC KEY-----`
let fakeKey = `-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmrBLT6lyiFh/eUticsIFNY6AkjXuQPqj0Qvb99pCJJk=\n-----END PUBLIC KEY-----`
const result2 = await authentication.verifySignature(encodedData, signature, [fakeKey,]);
expect(result2).toBe(null);
});
it('encoding and decoding test', async () => {
const testkey = '-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEILXfcMirlUiI/o/r+8rK7ZIP0fyAMynxYzJXCI6BJHPk\n-----END PRIVATE KEY-----';
const base64 = testkey.replace(`-----BEGIN PRIVATE KEY-----`, '').replace(`-----END PRIVATE KEY-----`, '').trim();
const derBuffer = Buffer.from(base64, 'base64');
let privkey = await crypto.subtle.importKey(
"pkcs8",
derBuffer,
{
name: "Ed25519",
},
true,
["sign"],
);
const msg2 = '12f4b99e3784ac2e8b95427533a3dbc4';
const encoder2 = new TextEncoder();
const encodedData2 = encoder2.encode(msg2);
const signature2 = await crypto.subtle.sign(
{
name: "Ed25519",
},
privkey,
encodedData2,
);
const signatureBase64 = Buffer.from(signature2).toString('base64');
const sig = Buffer.from(signatureBase64, 'base64');
let pemKey2 = '-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEALrj4A3Vftz5TgWXEHi5KG+HD+uQLGB3bGc4TprDi9kE=\n-----END PUBLIC KEY-----'
const publicKeys2 = [pemKey2,];
const result3 = await authentication.verifySignature(encodedData2, sig, publicKeys2);
expect(result3).toBe(pemKey2);
});
});
});