diff --git a/backend/src/lib/api.ts b/backend/src/lib/api.ts index 83b81cc..26e9075 100644 --- a/backend/src/lib/api.ts +++ b/backend/src/lib/api.ts @@ -98,6 +98,7 @@ app.post("/login/step/instance", async (req, res) => { prompt: "USERNAME", // change this if oidc is available instance: domain, method: deliveryProvider ? "SEND_CODE" : "RECV_CODE", + attempt: 0, }; // const oidcSupport = await doesInstanceSupportOIDC(domain); @@ -238,6 +239,13 @@ app.post("/login/step/verify", async (req, res) => { const { session_id, username, instance } = req.session.login; + if (req.session.login.attempt > 5) { + req.session.destroy(() => { + res.status(400).json({ success: false, error: "too_many_attempts" }); + }); + return; + } + const session = await prisma.authSession.findFirst({ where: { id: session_id, @@ -266,7 +274,11 @@ app.post("/login/step/verify", async (req, res) => { code = req.body.code; if (session.one_time_code !== code) { - return res.status(400).json({ success: false, error: "code_invalid" }); + req.session.login.attempt++; + req.session.save(() => { + res.status(400).json({ success: false, error: "code_invalid" }); + }); + return; } req.session.user = { sub: session.user_sub }; @@ -290,7 +302,12 @@ app.post("/login/step/verify", async (req, res) => { res.json({ success: true }); }); } else { - res.status(400).json({ success: false, error: data.error }); + if (req.session.login) { + req.session.login.attempt++; + } + req.session.save(() => { + res.status(400).json({ success: false, error: data.error }); + }); } }); break; diff --git a/backend/src/types/session-types.ts b/backend/src/types/session-types.ts index 1798635..3e3796d 100644 --- a/backend/src/types/session-types.ts +++ b/backend/src/types/session-types.ts @@ -15,6 +15,7 @@ declare module "express-session" { method: "SEND_CODE" | "RECV_CODE"; // what delivery to attempt username?: string; session_id?: string; + attempt: number; }; } }