summary refs log tree commit diff
path: root/src/api/routes/auth
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/routes/auth')
-rw-r--r--src/api/routes/auth/location-metadata.ts15
-rw-r--r--src/api/routes/auth/login.ts41
-rw-r--r--src/api/routes/auth/mfa/totp.ts22
-rw-r--r--src/api/routes/auth/register.ts34
4 files changed, 75 insertions, 37 deletions
diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts
index f4c2bd16..b8caf579 100644
--- a/src/api/routes/auth/location-metadata.ts
+++ b/src/api/routes/auth/location-metadata.ts
@@ -1,13 +1,12 @@
-import { Router, Request, Response } from "express";
-import { route } from "@fosscord/api";
-import { getIpAdress, IPAnalysis } from "@fosscord/api";
+import { getIpAdress, IPAnalysis, route } from "@fosscord/api";
+import { Request, Response, Router } from "express";
 const router = Router();
 
-router.get("/",route({}), async (req: Request, res: Response) => {
-    //TODO
-    //Note: It's most likely related to legal. At the moment Discord hasn't finished this too
-    const country_code = (await IPAnalysis(getIpAdress(req))).country_code;
-	res.json({ consent_required: false, country_code: country_code, promotional_email_opt_in: { required: true, pre_checked: false}});
+router.get("/", route({}), async (req: Request, res: Response) => {
+	//TODO
+	//Note: It's most likely related to legal. At the moment Discord hasn't finished this too
+	const country_code = (await IPAnalysis(getIpAdress(req))).country_code;
+	res.json({ consent_required: false, country_code: country_code, promotional_email_opt_in: { required: true, pre_checked: false } });
 });
 
 export default router;
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index 9fc5924d..f5415a56 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -1,8 +1,16 @@
-import { Request, Response, Router } from "express";
-import { route } from "@fosscord/api";
-import bcrypt from "bcrypt";
-import { Config, User, generateToken, adjustEmail, FieldErrors, LoginSchema } from "@fosscord/util";
+import { route, getIpAdress } from "@fosscord/api";
+import { adjustEmail, Config, FieldErrors, generateToken, LoginSchema, User } from "@fosscord/util";
 import crypto from "crypto";
+import { Request, Response, Router } from "express";
+import fetch from "node-fetch";
+
+let bcrypt: any;
+try {
+	bcrypt = require("bcrypt");
+} catch {
+	bcrypt = require("bcryptjs");
+	console.log("Warning: using bcryptjs because bcrypt is not installed! Performance will be affected.");
+}
 
 const router: Router = Router();
 export default router;
@@ -10,12 +18,13 @@ export default router;
 router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => {
 	const { login, password, captcha_key, undelete } = req.body as LoginSchema;
 	const email = adjustEmail(login);
+	const ip = getIpAdress(req);
 
 	const config = Config.get();
 
 	if (config.login.requireCaptcha && config.security.captcha.enabled) {
+		const { sitekey, secret, service } = config.security.captcha;
 		if (!captcha_key) {
-			const { sitekey, service } = config.security.captcha;
 			return res.status(400).json({
 				captcha_key: ["captcha-required"],
 				captcha_sitekey: sitekey,
@@ -23,7 +32,21 @@ router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Respo
 			});
 		}
 
-		// TODO: check captcha
+
+		let captchaUrl = "";
+		if (service === "recaptcha") {
+			captchaUrl = `https://www.google.com/recaptcha/api/siteverify=${sitekey}?secret=${secret}&response=${captcha_key}&remoteip=${ip}`;
+		} else if (service === "hcaptcha") {
+			captchaUrl = `https://hcaptcha.com/siteverify?sitekey=${sitekey}&secret=${secret}&response=${captcha_key}&remoteip=${ip}`;
+		}
+		const response: { success: boolean; "error-codes": string[] } = await (await fetch(captchaUrl, { method: "POST" })).json();
+		if (!response.success) {
+			return res.status(400).json({
+				captcha_key: response["error-codes"],
+				captcha_sitekey: sitekey,
+				captcha_service: service
+			});
+		}
 	}
 
 	const user = await User.findOneOrFail({
@@ -57,9 +80,9 @@ router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Respo
 		return res.json({
 			ticket: ticket,
 			mfa: true,
-			sms: false,	// TODO
-			token: null,
-		})
+			sms: false, // TODO
+			token: null
+		});
 	}
 
 	const token = await generateToken(user.id);
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 421dbafa..9938569e 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -1,8 +1,8 @@
-import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateToken, TotpSchema, User } from "@fosscord/util";
-import { verifyToken } from "node-2fa";
+import { BackupCode, generateToken, TotpSchema, User } from "@fosscord/util";
+import { Request, Response, Router } from "express";
 import { HTTPError } from "lambert-server";
+import { verifyToken } from "node-2fa";
 const router = Router();
 
 router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
@@ -10,23 +10,17 @@ router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Respon
 
 	const user = await User.findOneOrFail({
 		where: {
-			totp_last_ticket: ticket,
+			totp_last_ticket: ticket
 		},
-		select: [
-			"id",
-			"totp_secret",
-			"settings",
-		],
+		select: ["id", "totp_secret", "settings"]
 	});
 
 	const backup = await BackupCode.findOne({ where: { code: code, expired: false, consumed: false, user: { id: user.id } } });
 
 	if (!backup) {
 		const ret = verifyToken(user.totp_secret!, code);
-		if (!ret || ret.delta != 0)
-			throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
-	}
-	else {
+		if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+	} else {
 		backup.consumed = true;
 		await backup.save();
 	}
@@ -35,7 +29,7 @@ router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Respon
 
 	return res.json({
 		token: await generateToken(user.id),
-		user_settings: user.settings,
+		user_settings: user.settings
 	});
 });
 
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index 09366a12..7ff691d0 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -1,8 +1,15 @@
+import { getIpAdress, IPAnalysis, isProxy, route } from "@fosscord/api";
+import { adjustEmail, Config, FieldErrors, generateToken, HTTPError, Invite, RegisterSchema, User } from "@fosscord/util";
 import { Request, Response, Router } from "express";
-import { Config, generateToken, Invite, FieldErrors, User, adjustEmail, trimSpecial, RegisterSchema } from "@fosscord/util";
-import { route, getIpAdress, IPAnalysis, isProxy } from "@fosscord/api";
-import bcrypt from "bcrypt";
-import { HTTPError } from "@fosscord/util";
+import fetch from "node-fetch";
+
+let bcrypt: any;
+try {
+	bcrypt = require("bcrypt");
+} catch {
+	bcrypt = require("bcryptjs");
+	console.log("Warning: using bcryptjs because bcrypt is not installed! Performance will be affected.");
+}
 
 const router: Router = Router();
 
@@ -38,8 +45,9 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
 	}
 
 	if (register.requireCaptcha && security.captcha.enabled) {
+		const { sitekey, secret, service } = security.captcha;
+
 		if (!body.captcha_key) {
-			const { sitekey, service } = security.captcha;
 			return res?.status(400).json({
 				captcha_key: ["captcha-required"],
 				captcha_sitekey: sitekey,
@@ -47,7 +55,21 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
 			});
 		}
 
-		// TODO: check captcha
+
+		let captchaUrl = "";
+		if (service === "recaptcha") {
+			captchaUrl = `https://www.google.com/recaptcha/api/siteverify=${sitekey}?secret=${secret}&response=${body.captcha_key}&remoteip=${ip}`;
+		} else if (service === "hcaptcha") {
+			captchaUrl = `https://hcaptcha.com/siteverify?sitekey=${sitekey}&secret=${secret}&response=${body.captcha_key}&remoteip=${ip}`;
+		}
+		const response: { success: boolean; "error-codes": string[] } = await (await fetch(captchaUrl, { method: "POST" })).json();
+		if (!response.success) {
+			return res.status(400).json({
+				captcha_key: response["error-codes"],
+				captcha_sitekey: sitekey,
+				captcha_service: service
+			});
+		}
 	}
 
 	if (!register.allowMultipleAccounts) {