aboutsummaryrefslogtreecommitdiffstats
path: root/routes
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-12-29 18:20:20 -0800
committerAdam Soltys <[email protected]>2024-12-29 18:20:20 -0800
commit8b019c4583bfd6676ea39ef16e9606316d269538 (patch)
tree5caeba943e0db465b31f56418509f4acdd139c21 /routes
parentfb75896a4000fa689a940d86f61824a65e13454e (diff)
downloadcoinos-server-8b019c4583bfd6676ea39ef16e9606316d269538.tar.gz
coinos-server-8b019c4583bfd6676ea39ef16e9606316d269538.zip
nostr login
Diffstat (limited to 'routes')
-rw-r--r--routes/users.ts40
1 files changed, 39 insertions, 1 deletions
diff --git a/routes/users.ts b/routes/users.ts
index 5c5f1a6f..87797cce 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -15,7 +15,7 @@ import whitelist from "$lib/whitelist";
import rpc from "@coinos/rpc";
import { $ } from "bun";
import jwt from "jsonwebtoken";
-import { nip19 } from "nostr-tools";
+import { nip19, verifyEvent } from "nostr-tools";
import { authenticator } from "otplib";
import { v4 } from "uuid";
@@ -355,6 +355,44 @@ export default {
}
},
+ async challenge(_, res) {
+ const id = v4();
+ await db.set(`challenge:${id}`, id, { EX: 300 });
+ res.send({ id });
+ },
+
+ async nostrLogin(req, res) {
+ try {
+ const { event, id, twofa } = req.body;
+ const challenge = await g(`challenge:${id}`);
+ if (!challenge) fail("Invalid or expired login challenge");
+
+ if (!verifyEvent(event) || event.content !== id)
+ fail("Invalid signature or challenge mismatch.");
+
+ let user = await getUser(event.pubkey);
+ const { username } = user;
+ l("logging in", username, req.headers["cf-connecting-ip"]);
+
+ if (
+ user.twofa &&
+ (typeof twofa === "undefined" ||
+ !authenticator.check(twofa, user.otpsecret))
+ ) {
+ return res.code(401).send("2fa required");
+ }
+
+ const payload = { id: user.id };
+ const token = jwt.sign(payload, config.jwt);
+ res.cookie("token", token, { expires: new Date(Date.now() + 432000000) });
+ user = pick(user, whitelist);
+ res.send({ user, token });
+ } catch (e) {
+ err("login error", e.message, req.socket.remoteAddress);
+ res.code(401).send({});
+ }
+ },
+
async subscriptions(req, res) {
try {
const { user } = req;