import dotenv from 'dotenv'; import jwt from 'jsonwebtoken'; import argon2 from 'argon2'; dotenv.config(); export default class AuthHandler { ips = new Map() #secret constructor() { this.#secret = process.env.JWT_SECRET; } isLoggedInUser(req, res) { const token = req.cookies.auth_token; if (!token) { return false; } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; return true; } catch (err) { return false; } } getRequestEmail(req, res) { const token = req.cookies?.auth_token; if (!token) return res.status(401).send({ error: "No auth token" }); try { const payload = jwt.verify(token, process.env.JWT_SECRET); const email = payload.email; return email } catch (e) { console.error("Error getting profile: ", e) throw new Error("Error getting email: invalid auth token") } } async getProfile(req, res) { try { let email = global.auth.getRequestEmail(req, res) const user = await db.members.getByEmail(email); const connections = await db.MEMBER_IN_NETWORK.getByMember(user.id); const userOrgs = await Promise.all(connections.map(async (c) => { const network = await db.networks.get(c.network_id); delete network.stripe_account_id; delete network.stripe_access_token; return network; })); res.send({ id: user.id, email: user.email, first_name: user.first_name, last_name: user.last_name, networks: userOrgs, apps: user.apps }); } catch (e) { console.error("Error getting profile: ", e) res.status(401).send({ error: "Invalid token" }); } } async login(req, res) { const { email, password } = req.body; let foundUser = await global.db.members.getByEmail(email) if(!foundUser) { res.status(400).json({ error: 'Incorrect email.' }); return; } const storedHash = foundUser.password const valid = await argon2.verify(storedHash, password); if (!valid) { res.status(400).json({ error: 'Incorrect password.' }); } else { const payload = { email: foundUser.email }; console.log("login: ", payload) const secret = process.env.JWT_SECRET; const options = { expiresIn: "2h" }; const token = jwt.sign(payload, secret, options); res.cookie("auth_token", token, { httpOnly: true, // cannot be accessed by JS secure: process.env.ENV === "production", // only over HTTPS sameSite: "lax", // like SameSiteLaxMode maxAge: 60 * 24 * 60 * 60 * 1000, // 60 days path: "/", // available on entire site domain: process.env.ENV === "production" ? "." + process.env.BASE_URL : undefined }); res.redirect("/") } } logout(req, res) { res.cookie('auth_token', '', { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', maxAge: 0, // expire immediately path: '/', domain: process.env.ENV === "production" ? "." + process.env.BASE_URL : undefined }); res.redirect("/") } }