recaptcha

main
alex 2024-02-04 15:50:46 +01:00
parent 8f79565472
commit a49d035e80
4 changed files with 94 additions and 6 deletions

View File

@ -28,4 +28,6 @@ RABBITMQ_USERNAME=
RABBITMQ_PASSWORD=
RABBITMQ_MAIL_QUEUE=
ACCOUNT_EXPORT_URL=
ACCOUNT_EXPORT_URL=
RECAPTCHA_SECRET_KEY=

View File

@ -33,11 +33,19 @@ import Session from "../models/session";
import Feedback from "../models/feedback";
import fs from "fs-extra";
import { channel } from "../rabbitmq/rabbitmq";
import verifyCaptcha from "../utils/recaptcha";
export async function SignUp(req: Request, res: Response) {
try {
let { companyName, username, accountName, password, language, rememberMe } =
req.body;
let {
companyName,
username,
accountName,
password,
language,
rememberMe,
recaptcha,
} = req.body;
// validate request
@ -51,11 +59,23 @@ export async function SignUp(req: Request, res: Response) {
!isUsernameValid(username) ||
!isAccountNameValid(accountName) ||
!isLanguageCodeValid(language) ||
rememberMe === undefined
rememberMe === undefined ||
!recaptcha
) {
return res.status(400).send({ err: "invalid request" });
}
// validate recaptcha
const recaptchaValid = await verifyCaptcha(
recaptcha,
req.headers["x-real-ip"] as string
);
if (!recaptchaValid) {
return res.status(400).send({ err: "invalid request" });
}
accountName = accountName.toLowerCase();
// check if user already exists
@ -129,7 +149,7 @@ export async function SignUp(req: Request, res: Response) {
export async function Login(req: Request, res: Response) {
try {
let { accountName, password, rememberMe } = req.body;
let { accountName, password, rememberMe, recaptcha } = req.body;
// validate request
@ -163,6 +183,17 @@ export async function Login(req: Request, res: Response) {
return res.status(200).send({ state: user.state });
}
// validate recaptcha
const recaptchaValid = await verifyCaptcha(
recaptcha,
req.headers["x-real-ip"] as string
);
if (!recaptchaValid) {
return res.status(400).send({ err: "invalid request" });
}
// decode password
const decodedPassword = decodeBase64(password);

56
src/utils/recaptcha.ts Normal file
View File

@ -0,0 +1,56 @@
import logger from "../logger/logger";
// crash if no recaptcha secret key are set
if (!process.env.RECAPTCHA_SECRET_KEY) {
throw new Error("no recaptcha secret key found!");
}
const encodedSecretKey = encodeURIComponent(process.env.RECAPTCHA_SECRET_KEY);
async function verifyCaptcha(token: string, ip?: string): Promise<boolean> {
return new Promise(async (resolve, reject) => {
if (typeof token !== "string" || token.trim() === "") {
reject("Invalid token");
return;
}
if (!encodedSecretKey) {
reject("captcha secret not set");
return;
}
let url;
if (!ip) {
url =
"https://www.google.com/recaptcha/api/siteverify?secret=" +
encodedSecretKey +
"&response=" +
encodeURIComponent(token);
} else {
url =
"https://www.google.com/recaptcha/api/siteverify?secret=" +
encodedSecretKey +
"&response=" +
encodeURIComponent(token) +
"&remoteip=" +
ip;
}
try {
const res = await fetch(url, { method: "POST" });
const json = await res.json();
if (json.success) {
resolve(true);
} else {
reject("captcha failed");
}
} catch (error) {
reject("Error verifying captcha");
logger.error("Error verifying captcha:", error);
}
});
}
export default verifyCaptcha;

View File

@ -1 +0,0 @@
{"user":{"user_id":"6d86ae13-05cb-4d3d-a9c2-112783d133b9","username":"Mikael cool","account_name":"mikael","calendar_max_future_booking_days":null,"calendar_min_earliest_booking_time":null,"calendar_using_primary_calendar":true,"language":"de","analytics_enabled":true}}