From c268df21375cd670b3d13403db1e8a8281d52068 Mon Sep 17 00:00:00 2001 From: dholms Date: Sat, 3 Feb 2024 15:41:06 -0600 Subject: [PATCH] add rate limits to email routes --- .../atproto/server/requestAccountDelete.ts | 12 ++++++ .../server/requestEmailConfirmation.ts | 12 ++++++ .../com/atproto/server/requestEmailUpdate.ts | 12 ++++++ .../atproto/server/requestPasswordReset.ts | 38 +++++++++++++------ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/packages/pds/src/api/com/atproto/server/requestAccountDelete.ts b/packages/pds/src/api/com/atproto/server/requestAccountDelete.ts index ca895852f4f..34de7c362e2 100644 --- a/packages/pds/src/api/com/atproto/server/requestAccountDelete.ts +++ b/packages/pds/src/api/com/atproto/server/requestAccountDelete.ts @@ -1,9 +1,21 @@ import { InvalidRequestError } from '@atproto/xrpc-server' +import { DAY, HOUR } from '@atproto/common' import { Server } from '../../../../lexicon' import AppContext from '../../../../context' export default function (server: Server, ctx: AppContext) { server.com.atproto.server.requestAccountDelete({ + rateLimit: [ + { + durationMs: DAY, + points: 10, + calcKey: ({ auth }) => auth.credentials.did, + }, + { + durationMs: HOUR, + points: 10, + }, + ], auth: ctx.authVerifier.accessCheckTakedown, handler: async ({ auth }) => { const did = auth.credentials.did diff --git a/packages/pds/src/api/com/atproto/server/requestEmailConfirmation.ts b/packages/pds/src/api/com/atproto/server/requestEmailConfirmation.ts index 97b2e53cc7a..d88ee1e7eb0 100644 --- a/packages/pds/src/api/com/atproto/server/requestEmailConfirmation.ts +++ b/packages/pds/src/api/com/atproto/server/requestEmailConfirmation.ts @@ -1,9 +1,21 @@ import { InvalidRequestError } from '@atproto/xrpc-server' +import { DAY, HOUR } from '@atproto/common' import { Server } from '../../../../lexicon' import AppContext from '../../../../context' export default function (server: Server, ctx: AppContext) { server.com.atproto.server.requestEmailConfirmation({ + rateLimit: [ + { + durationMs: DAY, + points: 10, + calcKey: ({ auth }) => auth.credentials.did, + }, + { + durationMs: HOUR, + points: 10, + }, + ], auth: ctx.authVerifier.accessCheckTakedown, handler: async ({ auth }) => { const did = auth.credentials.did diff --git a/packages/pds/src/api/com/atproto/server/requestEmailUpdate.ts b/packages/pds/src/api/com/atproto/server/requestEmailUpdate.ts index 5402fa6b887..07ff13cf016 100644 --- a/packages/pds/src/api/com/atproto/server/requestEmailUpdate.ts +++ b/packages/pds/src/api/com/atproto/server/requestEmailUpdate.ts @@ -1,9 +1,21 @@ import { InvalidRequestError } from '@atproto/xrpc-server' +import { DAY, HOUR } from '@atproto/common' import { Server } from '../../../../lexicon' import AppContext from '../../../../context' export default function (server: Server, ctx: AppContext) { server.com.atproto.server.requestEmailUpdate({ + rateLimit: [ + { + durationMs: DAY, + points: 10, + calcKey: ({ auth }) => auth.credentials.did, + }, + { + durationMs: HOUR, + points: 10, + }, + ], auth: ctx.authVerifier.accessCheckTakedown, handler: async ({ auth }) => { const did = auth.credentials.did diff --git a/packages/pds/src/api/com/atproto/server/requestPasswordReset.ts b/packages/pds/src/api/com/atproto/server/requestPasswordReset.ts index 61b17ebb9a9..fe4d5297b99 100644 --- a/packages/pds/src/api/com/atproto/server/requestPasswordReset.ts +++ b/packages/pds/src/api/com/atproto/server/requestPasswordReset.ts @@ -1,20 +1,34 @@ +import { DAY, HOUR } from '@atproto/common' import AppContext from '../../../../context' import { Server } from '../../../../lexicon' export default function (server: Server, ctx: AppContext) { - server.com.atproto.server.requestPasswordReset(async ({ input }) => { - const email = input.body.email.toLowerCase() + server.com.atproto.server.requestPasswordReset({ + rateLimit: [ + { + durationMs: DAY, + points: 10, + calcKey: ({ input }) => input.body.email.toLowerCase(), + }, + { + durationMs: HOUR, + points: 10, + }, + ], + handler: async ({ input }) => { + const email = input.body.email.toLowerCase() - const user = await ctx.services.account(ctx.db).getAccountByEmail(email) + const user = await ctx.services.account(ctx.db).getAccountByEmail(email) - if (user) { - const token = await ctx.services - .account(ctx.db) - .createEmailToken(user.did, 'reset_password') - await ctx.mailer.sendResetPassword( - { handle: user.handle, token }, - { to: user.email }, - ) - } + if (user) { + const token = await ctx.services + .account(ctx.db) + .createEmailToken(user.did, 'reset_password') + await ctx.mailer.sendResetPassword( + { handle: user.handle, token }, + { to: user.email }, + ) + } + }, }) }