From 5416198c329817cbd63305c5755a905d63f1fa64 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 30 Sep 2024 18:19:44 +0900
Subject: [PATCH] wip
---
.../src/server/api/SigninApiService.ts | 37 +++++++++++++++++++
packages/frontend/src/components/MkSignin.vue | 13 +++++++
2 files changed, 50 insertions(+)
diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts
index edac9b3beb..2ccc75da00 100644
--- a/packages/backend/src/server/api/SigninApiService.ts
+++ b/packages/backend/src/server/api/SigninApiService.ts
@@ -9,6 +9,7 @@ import * as OTPAuth from 'otpauth';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type {
+ MiMeta,
SigninsRepository,
UserProfilesRepository,
UsersRepository,
@@ -20,6 +21,8 @@ import { IdService } from '@/core/IdService.js';
import { bindThis } from '@/decorators.js';
import { WebAuthnService } from '@/core/WebAuthnService.js';
import { UserAuthService } from '@/core/UserAuthService.js';
+import { CaptchaService } from '@/core/CaptchaService.js';
+import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
import { RateLimiterService } from './RateLimiterService.js';
import { SigninService } from './SigninService.js';
import type { AuthenticationResponseJSON } from '@simplewebauthn/types';
@@ -31,6 +34,9 @@ export class SigninApiService {
@Inject(DI.config)
private config: Config,
+ @Inject(DI.meta)
+ private meta: MiMeta,
+
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@@ -45,6 +51,7 @@ export class SigninApiService {
private signinService: SigninService,
private userAuthService: UserAuthService,
private webAuthnService: WebAuthnService,
+ private captchaService: CaptchaService,
) {
}
@@ -56,6 +63,10 @@ export class SigninApiService {
password: string;
token?: string;
credential?: AuthenticationResponseJSON;
+ 'hcaptcha-response'?: string;
+ 'g-recaptcha-response'?: string;
+ 'turnstile-response'?: string;
+ 'm-captcha-response'?: string;
};
}>,
reply: FastifyReply,
@@ -139,6 +150,32 @@ export class SigninApiService {
};
if (!profile.twoFactorEnabled) {
+ if (process.env.NODE_ENV !== 'test') {
+ if (this.meta.enableHcaptcha && this.meta.hcaptchaSecretKey) {
+ await this.captchaService.verifyHcaptcha(this.meta.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => {
+ throw new FastifyReplyError(400, err);
+ });
+ }
+
+ if (this.meta.enableMcaptcha && this.meta.mcaptchaSecretKey && this.meta.mcaptchaSitekey && this.meta.mcaptchaInstanceUrl) {
+ await this.captchaService.verifyMcaptcha(this.meta.mcaptchaSecretKey, this.meta.mcaptchaSitekey, this.meta.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => {
+ throw new FastifyReplyError(400, err);
+ });
+ }
+
+ if (this.meta.enableRecaptcha && this.meta.recaptchaSecretKey) {
+ await this.captchaService.verifyRecaptcha(this.meta.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => {
+ throw new FastifyReplyError(400, err);
+ });
+ }
+
+ if (this.meta.enableTurnstile && this.meta.turnstileSecretKey) {
+ await this.captchaService.verifyTurnstile(this.meta.turnstileSecretKey, body['turnstile-response']).catch(err => {
+ throw new FastifyReplyError(400, err);
+ });
+ }
+ }
+
if (same) {
return this.signinService.signin(request, reply, user);
} else {
diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue
index 7942a84d66..6880d78026 100644
--- a/packages/frontend/src/components/MkSignin.vue
+++ b/packages/frontend/src/components/MkSignin.vue
@@ -32,6 +32,10 @@ SPDX-License-Identifier: AGPL-3.0-only
+