From 581fb404e212b5993fbec153a87e9b7bfd68d578 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 4 Feb 2025 17:30:14 +0000 Subject: log login failures --- .gitignore | 1 + index.ts | 11 ++++++++++- lib/migrate.ts | 2 +- lib/nwc.ts | 3 ++- lib/payments.ts | 13 ++++++++++++- lib/sockets.ts | 2 +- routes/payments.ts | 5 +---- routes/users.ts | 14 +++++++++----- 8 files changed, 37 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 312970e2..8fcee169 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ req nobal.sh littlefs.img printer +failedlogins.txt diff --git a/index.ts b/index.ts index 03595e16..bbcbfbbf 100644 --- a/index.ts +++ b/index.ts @@ -113,7 +113,16 @@ app.post("/superuser", users.superuser); app.get("/verify/:code", users.verify); app.post("/request", auth, users.request); app.post("/forgot", users.forgot); -app.post("/login", users.login); +app.post("/login", { + config: { + rateLimit: { + max: 5, + timeWindow: "5 seconds", + keyGenerator: (req) => req.headers["cf-connecting-ip"] as string, // IP-based rate limiting + }, + }, + }, + users.login); app.post("/printer", users.printer); app.get("/challenge", users.challenge); app.post("/nostrLogin", users.nostrLogin); diff --git a/lib/migrate.ts b/lib/migrate.ts index 403e22b1..8da68cd2 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -12,7 +12,7 @@ async function migrate(id) { let user = await g(`user:${id}`); if (typeof user === "string") user = await g(`user:${user}`); - if (user) return user; + return user; user = await ga(`user:${id}`); diff --git a/lib/nwc.ts b/lib/nwc.ts index 912a2fc3..73b7decd 100644 --- a/lib/nwc.ts +++ b/lib/nwc.ts @@ -76,7 +76,8 @@ export default () => { } catch (e) { err( "problem with nwc", - user.username, + pubkey, + user?.username, JSON.stringify(params), e.message, ); diff --git a/lib/payments.ts b/lib/payments.ts index 1468a198..af16e02e 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -54,8 +54,19 @@ export const debit = async ({ rate = undefined, }) => { amount = parseInt(amount); - if (type !== types.internal && (await g("freeze"))) + let blacklisted = await db.sIsMember("blacklist", user?.username?.toLowerCase()); + let whitelisted = await db.sIsMember("whitelist", user?.username?.toLowerCase()); + + if (type !== types.internal && blacklisted && !whitelisted && amount > 500) { + warn("Blocking payment", amount, hash, user.username, user.id); + fail("Problem sending payment"); + } + + if (type !== types.internal && (await g("freeze")) && amount > 1000000 && !whitelisted) { + warn("Blocking payment", amount, hash, user.username, user.id); fail("Problem sending payment"); + } + // if (!user.unlimited && amount > 1000000) // fail(`⚡️${amount} exceeds max withdrawal of ⚡️1,000,000`); let ref; diff --git a/lib/sockets.ts b/lib/sockets.ts index 1a5421f9..028551ed 100644 --- a/lib/sockets.ts +++ b/lib/sockets.ts @@ -121,7 +121,7 @@ Bun.serve({ subscriptions.push({ invoice: data, ws }); break; default: - warn("received socket message of unknown type", type, data); + // warn("received socket message of unknown type", type, data); } }, open(ws: any) { diff --git a/routes/payments.ts b/routes/payments.ts index 93e5d3da..1e035b3c 100644 --- a/routes/payments.ts +++ b/routes/payments.ts @@ -1,7 +1,7 @@ import config from "$config"; import api from "$lib/api"; import { requirePin } from "$lib/auth"; -import { db, g, s, t } from "$lib/db"; +import { db, g, s } from "$lib/db"; import { err, l, warn } from "$lib/logging"; import mqtt from "$lib/mqtt"; import { @@ -45,8 +45,6 @@ export default { const balance = await g(`balance:${user.id}`); try { - if (await g("freeze")) fail("Problem sending payment"); - if (typeof amount !== "undefined") { amount = parseInt(amount); if (amount < 0 || amount > SATS || Number.isNaN(amount)) @@ -405,7 +403,6 @@ export default { res.send(p); } catch (e) { - console.log(e); warn(user.username, "payment failed", e.message); res.code(500).send(e.message); } diff --git a/routes/users.ts b/routes/users.ts index c54f4ae2..d1c2bd96 100644 --- a/routes/users.ts +++ b/routes/users.ts @@ -89,7 +89,7 @@ export default { const user = await getNostrUser(key); res.send(pick(user, fields)); } catch (e) { - err("problem getting user", e.message); + err("problem getting user", key, e.message); res.code(500).send(e.message); } }, @@ -161,11 +161,13 @@ export default { async update(req, res) { const { user, body } = req; try { - l("updating user", user.username); + const { id: tokid } = jwt.verify(req.headers.authorization.split(" ")[1], config.jwt); + l("updating user", user.username, tokid); const { confirm, password, pin, newpin, username } = body; let exists; + let { pubkey } = body; if (pubkey) { exists = await getUser(pubkey); @@ -292,7 +294,8 @@ export default { (await Bun.password.verify(password, user.password)) )) ) { - warn("invalid username or password attempt", username); + // warn("invalid username or password attempt", username); + await appendFile("failedlogins.txt", `${Date.now()} : ${username} : ${password}\n`); return res.code(401).send({}); } @@ -305,8 +308,8 @@ export default { return res.code(401).send("2fa required"); } - if (username !== "coinos" && username !== "funk") - l("logged in", username); + if (username !== "coinos" && username !== "funk" && username !== "btcpos") + l("logged in", username, password); const payload = { id: user.id }; const token = jwt.sign(payload, config.jwt); @@ -546,6 +549,7 @@ export default { res.send(pick(user, whitelist)); } catch (e) { + err("password reset failed", e.message); bail(res, e.message); } }, -- cgit v1.2.3