diff options
| author | Adam Soltys <[email protected]> | 2024-12-29 18:20:20 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-12-29 18:20:20 -0800 |
| commit | 8b019c4583bfd6676ea39ef16e9606316d269538 (patch) | |
| tree | 5caeba943e0db465b31f56418509f4acdd139c21 /routes | |
| parent | fb75896a4000fa689a940d86f61824a65e13454e (diff) | |
| download | coinos-server-8b019c4583bfd6676ea39ef16e9606316d269538.tar.gz coinos-server-8b019c4583bfd6676ea39ef16e9606316d269538.zip | |
nostr login
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/users.ts | 40 |
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; |
