diff --git a/apps/web/app/middleware/bucket.ts b/apps/web/app/middleware/bucket.ts index 6f8443fcc1..4d6aa91af0 100644 --- a/apps/web/app/middleware/bucket.ts +++ b/apps/web/app/middleware/bucket.ts @@ -1,16 +1,31 @@ import { rateLimit } from "@/app/middleware/rateLimit"; import { CLIENT_SIDE_API_RATE_LIMIT, + FORGET_PASSWORD_RATE_LIMIT, LOGIN_RATE_LIMIT, + RESET_PASSWORD_RATE_LIMIT, SHARE_RATE_LIMIT, SIGNUP_RATE_LIMIT, SYNC_USER_IDENTIFICATION_RATE_LIMIT, + VERIFY_EMAIL_RATE_LIMIT, } from "@formbricks/lib/constants"; export const signUpLimiter = rateLimit({ interval: SIGNUP_RATE_LIMIT.interval, allowedPerInterval: SIGNUP_RATE_LIMIT.allowedPerInterval, }); +export const forgetPasswordLimiter = rateLimit({ + interval: FORGET_PASSWORD_RATE_LIMIT.interval, + allowedPerInterval: FORGET_PASSWORD_RATE_LIMIT.allowedPerInterval, +}); +export const resetPasswordLimiter = rateLimit({ + interval: RESET_PASSWORD_RATE_LIMIT.interval, + allowedPerInterval: RESET_PASSWORD_RATE_LIMIT.allowedPerInterval, +}); +export const verifyEmailLimiter = rateLimit({ + interval: VERIFY_EMAIL_RATE_LIMIT.interval, + allowedPerInterval: VERIFY_EMAIL_RATE_LIMIT.allowedPerInterval, +}); export const loginLimiter = rateLimit({ interval: LOGIN_RATE_LIMIT.interval, allowedPerInterval: LOGIN_RATE_LIMIT.allowedPerInterval, diff --git a/apps/web/app/middleware/endpointValidator.ts b/apps/web/app/middleware/endpointValidator.ts index c5d0cd8c82..6f7917f6fd 100644 --- a/apps/web/app/middleware/endpointValidator.ts +++ b/apps/web/app/middleware/endpointValidator.ts @@ -2,6 +2,12 @@ export const loginRoute = (url: string) => url === "/api/auth/callback/credentia export const signupRoute = (url: string) => url === "/api/v1/users"; +export const resetPasswordRoute = (url: string) => url === "/api/v1/users/reset-password"; + +export const forgetPasswordRoute = (url: string) => url === "/api/v1/users/forgot-password"; + +export const verifyEmailRoute = (url: string) => url === "/api/v1/users/verification-email"; + export const clientSideApiRoute = (url: string): boolean => { if (url.includes("/api/packages/")) return true; if (url.includes("/api/v1/js/actions")) return true; diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index cdb7fd0011..098fa14c7b 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -1,17 +1,23 @@ import { clientSideApiEndpointsLimiter, + forgetPasswordLimiter, loginLimiter, + resetPasswordLimiter, shareUrlLimiter, signUpLimiter, syncUserIdentificationLimiter, + verifyEmailLimiter, } from "@/app/middleware/bucket"; import { clientSideApiRoute, + forgetPasswordRoute, isAuthProtectedRoute, isSyncWithUserIdentificationEndpoint, loginRoute, + resetPasswordRoute, shareUrlRoute, signupRoute, + verifyEmailRoute, } from "@/app/middleware/endpointValidator"; import { getToken } from "next-auth/jwt"; import { NextResponse } from "next/server"; @@ -50,6 +56,12 @@ export const middleware = async (request: NextRequest) => { await loginLimiter(`login-${ip}`); } else if (signupRoute(request.nextUrl.pathname)) { await signUpLimiter(`signup-${ip}`); + } else if (forgetPasswordRoute(request.nextUrl.pathname)) { + await forgetPasswordLimiter(`forget-password-${ip}`); + } else if (verifyEmailRoute(request.nextUrl.pathname)) { + await verifyEmailLimiter(`verify-email-${ip}`); + } else if (resetPasswordRoute(request.nextUrl.pathname)) { + await resetPasswordLimiter(`reset-password-${ip}`); } else if (clientSideApiRoute(request.nextUrl.pathname)) { await clientSideApiEndpointsLimiter(`client-side-api-${ip}`); @@ -74,6 +86,9 @@ export const config = { matcher: [ "/api/auth/callback/credentials", "/api/v1/users", + "/api/v1/users/forgot-password", + "/api/v1/users/verification-email", + "/api/v1/users/reset-password", "/api/(.*)/client/:path*", "/api/v1/js/actions", "/api/v1/client/storage", diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts index da1b192fc7..f709e5f820 100644 --- a/packages/lib/constants.ts +++ b/packages/lib/constants.ts @@ -153,7 +153,18 @@ export const SHARE_RATE_LIMIT = { interval: 60 * 60, // 60 minutes allowedPerInterval: 30, }; - +export const FORGET_PASSWORD_RATE_LIMIT = { + interval: 60 * 60, // 60 minutes + allowedPerInterval: 5, // Limit to 5 requests per hour +}; +export const RESET_PASSWORD_RATE_LIMIT = { + interval: 60 * 60, // 60 minutes + allowedPerInterval: 5, // Limit to 5 requests per hour +}; +export const VERIFY_EMAIL_RATE_LIMIT = { + interval: 60 * 60, // 60 minutes + allowedPerInterval: 10, // Limit to 10 requests per hour +}; export const SYNC_USER_IDENTIFICATION_RATE_LIMIT = { interval: 60, // 1 minute allowedPerInterval: 5,