diff options
| author | Johann150 <johann.galle@protonmail.com> | 2022-05-28 05:06:47 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-28 12:06:47 +0900 |
| commit | 161659de5cd7633161b0788799b641ff6b7e55f9 (patch) | |
| tree | 8dff8d5a7ae31a20d38e32ca6dcaa1b34eb95850 /packages/backend/src/server/api/private | |
| parent | enhance: clearly link documentation (diff) | |
| download | misskey-161659de5cd7633161b0788799b641ff6b7e55f9.tar.gz misskey-161659de5cd7633161b0788799b641ff6b7e55f9.tar.bz2 misskey-161659de5cd7633161b0788799b641ff6b7e55f9.zip | |
enhance: replace signin CAPTCHA with rate limit (#8740)
* enhance: rate limit works without signed in user
* fix: make limit key required for limiter
As before the fallback limiter key will be set from the endpoint name.
* enhance: use limiter for signin
* Revert "CAPTCHA求めるのは2fa認証が無効になっているときだけにした"
This reverts commit 02a43a310f6ad0cc9e9beccc26e51ab5b339e15f.
* Revert "feat: make captcha required when signin to improve security"
This reverts commit b21b0580058c14532ff3f4033e2a9147643bfca6.
* fix undefined reference
* fix: better error message
* enhance: only handle prefix of IPv6
Diffstat (limited to 'packages/backend/src/server/api/private')
| -rw-r--r-- | packages/backend/src/server/api/private/signin.ts | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 0024b8ce3e..b304550e29 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -1,25 +1,21 @@ -import { randomBytes } from 'node:crypto'; import Koa from 'koa'; import bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; -import { IsNull } from 'typeorm'; +import signin from '../common/signin.js'; import config from '@/config/index.js'; import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '@/models/index.js'; import { ILocalUser } from '@/models/entities/user.js'; import { genId } from '@/misc/gen-id.js'; -import { fetchMeta } from '@/misc/fetch-meta.js'; -import { verifyHcaptcha, verifyRecaptcha } from '@/misc/captcha.js'; import { verifyLogin, hash } from '../2fa.js'; -import signin from '../common/signin.js'; +import { randomBytes } from 'node:crypto'; +import { IsNull } from 'typeorm'; +import { limiter } from '../limiter.js'; export default async (ctx: Koa.Context) => { ctx.set('Access-Control-Allow-Origin', config.url); ctx.set('Access-Control-Allow-Credentials', 'true'); const body = ctx.request.body as any; - - const instance = await fetchMeta(true); - const username = body['username']; const password = body['password']; const token = body['token']; @@ -29,6 +25,21 @@ export default async (ctx: Koa.Context) => { ctx.body = { error }; } + try { + // not more than 1 attempt per second and not more than 10 attempts per hour + await limiter({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, ctx.ip); + } catch (err) { + ctx.status = 429; + ctx.body = { + error: { + message: 'Too many failed attempts to sign in. Try again later.', + code: 'TOO_MANY_AUTHENTICATION_FAILURES', + id: '22d05606-fbcf-421a-a2db-b32610dcfd1b', + }, + }; + return; + } + if (typeof username !== 'string') { ctx.status = 400; return; @@ -84,18 +95,6 @@ export default async (ctx: Koa.Context) => { } if (!profile.twoFactorEnabled) { - if (instance.enableHcaptcha && instance.hcaptchaSecretKey) { - await verifyHcaptcha(instance.hcaptchaSecretKey, body['hcaptcha-response']).catch(e => { - ctx.throw(400, e); - }); - } - - if (instance.enableRecaptcha && instance.recaptchaSecretKey) { - await verifyRecaptcha(instance.recaptchaSecretKey, body['g-recaptcha-response']).catch(e => { - ctx.throw(400, e); - }); - } - if (same) { signin(ctx, user); return; @@ -172,7 +171,7 @@ export default async (ctx: Koa.Context) => { body.credentialId .replace(/-/g, '+') .replace(/_/g, '/'), - 'base64', + 'base64' ).toString('hex'), }); |