recaptcha
parent
8f79565472
commit
a49d035e80
|
@ -29,3 +29,5 @@ RABBITMQ_PASSWORD=
|
||||||
RABBITMQ_MAIL_QUEUE=
|
RABBITMQ_MAIL_QUEUE=
|
||||||
|
|
||||||
ACCOUNT_EXPORT_URL=
|
ACCOUNT_EXPORT_URL=
|
||||||
|
|
||||||
|
RECAPTCHA_SECRET_KEY=
|
|
@ -33,11 +33,19 @@ import Session from "../models/session";
|
||||||
import Feedback from "../models/feedback";
|
import Feedback from "../models/feedback";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import { channel } from "../rabbitmq/rabbitmq";
|
import { channel } from "../rabbitmq/rabbitmq";
|
||||||
|
import verifyCaptcha from "../utils/recaptcha";
|
||||||
|
|
||||||
export async function SignUp(req: Request, res: Response) {
|
export async function SignUp(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
let { companyName, username, accountName, password, language, rememberMe } =
|
let {
|
||||||
req.body;
|
companyName,
|
||||||
|
username,
|
||||||
|
accountName,
|
||||||
|
password,
|
||||||
|
language,
|
||||||
|
rememberMe,
|
||||||
|
recaptcha,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
// validate request
|
// validate request
|
||||||
|
|
||||||
|
@ -51,11 +59,23 @@ export async function SignUp(req: Request, res: Response) {
|
||||||
!isUsernameValid(username) ||
|
!isUsernameValid(username) ||
|
||||||
!isAccountNameValid(accountName) ||
|
!isAccountNameValid(accountName) ||
|
||||||
!isLanguageCodeValid(language) ||
|
!isLanguageCodeValid(language) ||
|
||||||
rememberMe === undefined
|
rememberMe === undefined ||
|
||||||
|
!recaptcha
|
||||||
) {
|
) {
|
||||||
return res.status(400).send({ err: "invalid request" });
|
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();
|
accountName = accountName.toLowerCase();
|
||||||
|
|
||||||
// check if user already exists
|
// 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) {
|
export async function Login(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
let { accountName, password, rememberMe } = req.body;
|
let { accountName, password, rememberMe, recaptcha } = req.body;
|
||||||
|
|
||||||
// validate request
|
// validate request
|
||||||
|
|
||||||
|
@ -163,6 +183,17 @@ export async function Login(req: Request, res: Response) {
|
||||||
return res.status(200).send({ state: user.state });
|
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
|
// decode password
|
||||||
|
|
||||||
const decodedPassword = decodeBase64(password);
|
const decodedPassword = decodeBase64(password);
|
||||||
|
|
|
@ -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;
|
|
@ -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}}
|
|
Loading…
Reference in New Issue