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/forgot.ts22
-rw-r--r--src/api/routes/auth/generate-registration-tokens.ts23
-rw-r--r--src/api/routes/auth/location-metadata.ts2
-rw-r--r--src/api/routes/auth/login.ts23
-rw-r--r--src/api/routes/auth/logout.ts10
-rw-r--r--src/api/routes/auth/mfa/totp.ts8
-rw-r--r--src/api/routes/auth/mfa/webauthn.ts48
-rw-r--r--src/api/routes/auth/register.ts61
-rw-r--r--src/api/routes/auth/reset.ts11
-rw-r--r--src/api/routes/auth/verify/index.ts10
-rw-r--r--src/api/routes/auth/verify/resend.ts6
-rw-r--r--src/api/routes/auth/verify/view-backup-codes-challenge.ts2
12 files changed, 60 insertions, 166 deletions
diff --git a/src/api/routes/auth/forgot.ts b/src/api/routes/auth/forgot.ts
index 6fa86021..a17a2936 100644
--- a/src/api/routes/auth/forgot.ts
+++ b/src/api/routes/auth/forgot.ts
@@ -17,13 +17,7 @@
 */
 
 import { getIpAdress, route, verifyCaptcha } from "@spacebar/api";
-import {
-	Config,
-	Email,
-	FieldErrors,
-	ForgotPasswordSchema,
-	User,
-} from "@spacebar/util";
+import { Config, Email, FieldErrors, ForgotPasswordSchema, User } from "@spacebar/util";
 import { Request, Response, Router } from "express";
 import { HTTPError } from "lambert-server";
 const router = Router();
@@ -47,10 +41,7 @@ router.post(
 
 		const config = Config.get();
 
-		if (
-			config.passwordReset.requireCaptcha &&
-			config.security.captcha.enabled
-		) {
+		if (config.passwordReset.requireCaptcha && config.security.captcha.enabled) {
 			const { sitekey, service } = config.security.captcha;
 			if (!captcha_key) {
 				return res.status(400).json({
@@ -87,8 +78,7 @@ router.post(
 		if (!user.email)
 			throw FieldErrors({
 				login: {
-					message:
-						"This account does not have an email address associated with it.",
+					message: "This account does not have an email address associated with it.",
 					code: "NO_EMAIL",
 				},
 			});
@@ -110,12 +100,10 @@ router.post(
 				return res.sendStatus(204);
 			})
 			.catch((e) => {
-				console.error(
-					`Failed to send password reset email to ${user.username}#${user.discriminator}: ${e}`,
-				);
+				console.error(`Failed to send password reset email to ${user.username}#${user.discriminator}: ${e}`);
 				throw new HTTPError("Failed to send password reset email", 500);
 			});
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts
index 80fdaed1..e13e26f1 100644
--- a/src/api/routes/auth/generate-registration-tokens.ts
+++ b/src/api/routes/auth/generate-registration-tokens.ts
@@ -29,13 +29,11 @@ router.get(
 		query: {
 			count: {
 				type: "number",
-				description:
-					"The number of registration tokens to generate. Defaults to 1.",
+				description: "The number of registration tokens to generate. Defaults to 1.",
 			},
 			length: {
 				type: "number",
-				description:
-					"The length of each registration token. Defaults to 255.",
+				description: "The length of each registration token. Defaults to 255.",
 			},
 		},
 		right: "OPERATOR",
@@ -43,18 +41,14 @@ router.get(
 	}),
 	async (req: Request, res: Response) => {
 		const count = req.query.count ? parseInt(req.query.count as string) : 1;
-		const length = req.query.length
-			? parseInt(req.query.length as string)
-			: 255;
+		const length = req.query.length ? parseInt(req.query.length as string) : 255;
 
 		const tokens: ValidRegistrationToken[] = [];
 
 		for (let i = 0; i < count; i++) {
 			const token = ValidRegistrationToken.create({
 				token: random(length),
-				expires_at:
-					Date.now() +
-					Config.get().security.defaultRegistrationTokenExpiration,
+				expires_at: Date.now() + Config.get().security.defaultRegistrationTokenExpiration,
 			});
 			tokens.push(token);
 		}
@@ -67,16 +61,11 @@ router.get(
 		});
 
 		const ret = req.query.include_url
-			? tokens.map(
-					(x) =>
-						`${Config.get().general.frontPage}/register?token=${
-							x.token
-						}`,
-			  )
+			? tokens.map((x) => `${Config.get().general.frontPage}/register?token=${x.token}`)
 			: tokens.map((x) => x.token);
 
 		if (req.query.plain) return res.send(ret.join("\n"));
 
 		return res.json({ tokens: ret });
-	},
+	}
 );
diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts
index 28293e59..f1625702 100644
--- a/src/api/routes/auth/location-metadata.ts
+++ b/src/api/routes/auth/location-metadata.ts
@@ -38,7 +38,7 @@ router.get(
 			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 a2100333..5563597f 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -47,8 +47,7 @@ router.post(
 		},
 	}),
 	async (req: Request, res: Response) => {
-		const { login, password, captcha_key, undelete } =
-			req.body as LoginSchema;
+		const { login, password, captcha_key, undelete } = req.body as LoginSchema;
 
 		const config = Config.get();
 
@@ -101,10 +100,7 @@ router.post(
 		});
 
 		// the salt is saved in the password refer to bcrypt docs
-		const same_password = await bcrypt.compare(
-			password,
-			user.data.hash || "",
-		);
+		const same_password = await bcrypt.compare(password, user.data.hash || "");
 		if (!same_password) {
 			throw FieldErrors({
 				login: {
@@ -123,8 +119,7 @@ router.post(
 			throw FieldErrors({
 				login: {
 					code: "ACCOUNT_LOGIN_VERIFICATION_EMAIL",
-					message:
-						"Email verification is required, please check your email.",
+					message: "Email verification is required, please check your email.",
 				},
 			});
 		}
@@ -153,9 +148,7 @@ router.post(
 			const challenge = JSON.stringify({
 				publicKey: {
 					...options,
-					challenge: Buffer.from(options.challenge).toString(
-						"base64",
-					),
+					challenge: Buffer.from(options.challenge).toString("base64"),
 					allowCredentials: user.security_keys.map((x) => ({
 						id: x.key_id,
 						type: "public-key",
@@ -179,10 +172,8 @@ router.post(
 
 		if (undelete) {
 			// undelete refers to un'disable' here
-			if (user.disabled)
-				await User.update({ id: user.id }, { disabled: false });
-			if (user.deleted)
-				await User.update({ id: user.id }, { deleted: false });
+			if (user.disabled) await User.update({ id: user.id }, { disabled: false });
+			if (user.deleted) await User.update({ id: user.id }, { deleted: false });
 		} else {
 			if (user.deleted)
 				return res.status(400).json({
@@ -203,7 +194,7 @@ router.post(
 		// https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png
 
 		res.json({ token, settings: { ...user.settings, index: undefined } });
-	},
+	}
 );
 
 /**
diff --git a/src/api/routes/auth/logout.ts b/src/api/routes/auth/logout.ts
index 94a3e474..9686f5cb 100644
--- a/src/api/routes/auth/logout.ts
+++ b/src/api/routes/auth/logout.ts
@@ -31,16 +31,12 @@ router.post(
 	}),
 	async (req: Request, res: Response) => {
 		if (req.body.provider != null || req.body.voip_provider != null) {
-			console.log(
-				`[LOGOUT]: provider or voip provider not null!`,
-				req.body,
-			);
+			console.log(`[LOGOUT]: provider or voip provider not null!`, req.body);
 		} else {
 			delete req.body.provider;
 			delete req.body.voip_provider;
-			if (Object.keys(req.body).length != 0)
-				console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body);
+			if (Object.keys(req.body).length != 0) console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body);
 		}
 		res.status(204).send();
-	},
+	}
 );
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 4df408f9..956993b3 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -59,11 +59,7 @@ router.post(
 
 		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,
-				);
+			if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
 		} else {
 			backup.consumed = true;
 			await backup.save();
@@ -75,7 +71,7 @@ router.post(
 			token: await generateToken(user.id),
 			settings: { ...user.settings, index: undefined },
 		});
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/mfa/webauthn.ts b/src/api/routes/auth/mfa/webauthn.ts
index b58d2944..c1a7ddb9 100644
--- a/src/api/routes/auth/mfa/webauthn.ts
+++ b/src/api/routes/auth/mfa/webauthn.ts
@@ -17,14 +17,7 @@
 */
 
 import { route } from "@spacebar/api";
-import {
-	generateToken,
-	SecurityKey,
-	User,
-	verifyWebAuthnToken,
-	WebAuthn,
-	WebAuthnTotpSchema,
-} from "@spacebar/util";
+import { generateToken, SecurityKey, User, verifyWebAuthnToken, WebAuthn, WebAuthnTotpSchema } from "@spacebar/util";
 import { Request, Response, Router } from "express";
 import { ExpectedAssertionResult } from "fido2-lib";
 import { HTTPError } from "lambert-server";
@@ -65,46 +58,33 @@ router.post(
 		});
 
 		const ret = await verifyWebAuthnToken(ticket);
-		if (!ret)
-			throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+		if (!ret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
 
 		await User.update({ id: user.id }, { totp_last_ticket: "" });
 
 		const clientAttestationResponse = JSON.parse(code);
 
-		if (!clientAttestationResponse.rawId)
-			throw new HTTPError("Missing rawId", 400);
+		if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400);
 
-		clientAttestationResponse.rawId = toArrayBuffer(
-			Buffer.from(clientAttestationResponse.rawId, "base64url"),
-		);
+		clientAttestationResponse.rawId = toArrayBuffer(Buffer.from(clientAttestationResponse.rawId, "base64url"));
 
 		const securityKey = await SecurityKey.findOneOrFail({
 			where: {
-				key_id: Buffer.from(
-					clientAttestationResponse.rawId,
-					"base64url",
-				).toString("base64"),
+				key_id: Buffer.from(clientAttestationResponse.rawId, "base64url").toString("base64"),
 			},
 		});
 
 		const assertionExpectations: ExpectedAssertionResult = JSON.parse(
-			Buffer.from(
-				clientAttestationResponse.response.clientDataJSON,
-				"base64",
-			).toString(),
+			Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString()
 		);
 
-		const authnResult = await WebAuthn.fido2.assertionResult(
-			clientAttestationResponse,
-			{
-				...assertionExpectations,
-				factor: "second",
-				publicKey: securityKey.public_key,
-				prevCounter: securityKey.counter,
-				userHandle: securityKey.key_id,
-			},
-		);
+		const authnResult = await WebAuthn.fido2.assertionResult(clientAttestationResponse, {
+			...assertionExpectations,
+			factor: "second",
+			publicKey: securityKey.public_key,
+			prevCounter: securityKey.counter,
+			userHandle: securityKey.key_id,
+		});
 
 		const counter = authnResult.authnrData.get("counter");
 
@@ -116,7 +96,7 @@ router.post(
 			token: await generateToken(user.id),
 			user_settings: user.settings,
 		});
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index de1cbd3d..dc72a3ca 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -16,13 +16,7 @@
 	along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-import {
-	IPAnalysis,
-	getIpAdress,
-	isProxy,
-	route,
-	verifyCaptcha,
-} from "@spacebar/api";
+import { IPAnalysis, getIpAdress, isProxy, route, verifyCaptcha } from "@spacebar/api";
 import {
 	Config,
 	FieldErrors,
@@ -65,13 +59,9 @@ router.post(
 				});
 				await regToken.remove();
 				regTokenUsed = true;
-				console.log(
-					`[REGISTER] Registration token ${token} used for registration!`,
-				);
+				console.log(`[REGISTER] Registration token ${token} used for registration!`);
 			} else {
-				console.log(
-					`[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`,
-				);
+				console.log(`[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`);
 			}
 		}
 
@@ -104,11 +94,7 @@ router.post(
 			});
 		}
 
-		if (
-			!regTokenUsed &&
-			register.requireCaptcha &&
-			security.captcha.enabled
-		) {
+		if (!regTokenUsed && register.requireCaptcha && security.captcha.enabled) {
 			const { sitekey, service } = security.captcha;
 			if (!body.captcha_key) {
 				return res?.status(400).json({
@@ -139,9 +125,7 @@ router.post(
 				throw FieldErrors({
 					email: {
 						code: "EMAIL_ALREADY_REGISTERED",
-						message: req.t(
-							"auth:register.EMAIL_ALREADY_REGISTERED",
-						),
+						message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
 					},
 				});
 			}
@@ -176,9 +160,7 @@ router.post(
 				throw FieldErrors({
 					email: {
 						code: "EMAIL_ALREADY_REGISTERED",
-						message: req.t(
-							"auth:register.EMAIL_ALREADY_REGISTERED",
-						),
+						message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
 					},
 				});
 			}
@@ -198,14 +180,9 @@ router.post(
 					message: req.t("common:field.BASE_TYPE_REQUIRED"),
 				},
 			});
-		} else if (
-			register.dateOfBirth.required &&
-			register.dateOfBirth.minimum
-		) {
+		} else if (register.dateOfBirth.required && register.dateOfBirth.minimum) {
 			const minimum = new Date();
-			minimum.setFullYear(
-				minimum.getFullYear() - register.dateOfBirth.minimum,
-			);
+			minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum);
 			body.date_of_birth = new Date(body.date_of_birth as Date);
 
 			// higher is younger
@@ -228,10 +205,7 @@ router.post(
 				throw FieldErrors({
 					password: {
 						code: "PASSWORD_REQUIREMENTS_MIN_LENGTH",
-						message: req.t(
-							"auth:register.PASSWORD_REQUIREMENTS_MIN_LENGTH",
-							{ min: min },
-						),
+						message: req.t("auth:register.PASSWORD_REQUIREMENTS_MIN_LENGTH", { min: min }),
 					},
 				});
 			}
@@ -249,8 +223,7 @@ router.post(
 		if (
 			!regTokenUsed &&
 			!body.invite &&
-			(register.requireInvite ||
-				(register.guestsRequireInvite && !register.email))
+			(register.requireInvite || (register.guestsRequireInvite && !register.email))
 		) {
 			// require invite to register -> e.g. for organizations to send invites to their employees
 			throw FieldErrors({
@@ -266,18 +239,14 @@ router.post(
 			limits.absoluteRate.register.enabled &&
 			(await User.count({
 				where: {
-					created_at: MoreThan(
-						new Date(
-							Date.now() - limits.absoluteRate.register.window,
-						),
-					),
+					created_at: MoreThan(new Date(Date.now() - limits.absoluteRate.register.window)),
 				},
 			})) >= limits.absoluteRate.register.limit
 		) {
 			console.log(
-				`Global register ratelimit exceeded for ${getIpAdress(req)}, ${
-					req.body.username
-				}, ${req.body.invite || "No invite given"}`,
+				`Global register ratelimit exceeded for ${getIpAdress(req)}, ${req.body.username}, ${
+					req.body.invite || "No invite given"
+				}`
 			);
 			throw FieldErrors({
 				email: {
@@ -295,7 +264,7 @@ router.post(
 		}
 
 		return res.json({ token: await generateToken(user.id) });
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/reset.ts b/src/api/routes/auth/reset.ts
index b3ca1e9e..746363cc 100644
--- a/src/api/routes/auth/reset.ts
+++ b/src/api/routes/auth/reset.ts
@@ -17,14 +17,7 @@
 */
 
 import { route } from "@spacebar/api";
-import {
-	checkToken,
-	Email,
-	FieldErrors,
-	generateToken,
-	PasswordResetSchema,
-	User,
-} from "@spacebar/util";
+import { checkToken, Email, FieldErrors, generateToken, PasswordResetSchema, User } from "@spacebar/util";
 import bcrypt from "bcrypt";
 import { Request, Response, Router } from "express";
 
@@ -76,7 +69,7 @@ router.post(
 		await Email.sendPasswordChanged(user, user.email!);
 
 		res.json({ token: await generateToken(user.id) });
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/verify/index.ts b/src/api/routes/auth/verify/index.ts
index 49f74277..49f3398e 100644
--- a/src/api/routes/auth/verify/index.ts
+++ b/src/api/routes/auth/verify/index.ts
@@ -17,13 +17,7 @@
 */
 
 import { getIpAdress, route, verifyCaptcha } from "@spacebar/api";
-import {
-	checkToken,
-	Config,
-	FieldErrors,
-	generateToken,
-	User,
-} from "@spacebar/util";
+import { checkToken, Config, FieldErrors, generateToken, User } from "@spacebar/util";
 import { Request, Response, Router } from "express";
 const router = Router();
 
@@ -97,7 +91,7 @@ router.post(
 		await User.update({ id: user.id }, { verified: true });
 
 		return res.json(await getToken(user));
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/verify/resend.ts b/src/api/routes/auth/verify/resend.ts
index 701f0ea8..ced7c578 100644
--- a/src/api/routes/auth/verify/resend.ts
+++ b/src/api/routes/auth/verify/resend.ts
@@ -52,12 +52,10 @@ router.post(
 				return res.sendStatus(204);
 			})
 			.catch((e) => {
-				console.error(
-					`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`,
-				);
+				console.error(`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`);
 				throw new HTTPError("Failed to send verification email", 500);
 			});
-	},
+	}
 );
 
 export default router;
diff --git a/src/api/routes/auth/verify/view-backup-codes-challenge.ts b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
index 5407de82..59c98f00 100644
--- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts
+++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
@@ -52,7 +52,7 @@ router.post(
 			nonce: "NoncePlaceholder",
 			regenerate_nonce: "RegenNoncePlaceholder",
 		});
-	},
+	}
 );
 
 export default router;