From c114dc8831055d74187b9dfb4c9eeb558520237c Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 26 Jan 2023 00:35:39 +1100 Subject: [PATCH] fix: Rate limiter may reject requests that contain a session token (#8399) --- spec/RateLimit.spec.js | 21 +++++++++++++++++++++ src/middlewares.js | 17 +++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/spec/RateLimit.spec.js b/spec/RateLimit.spec.js index 60aff61381..10bc127719 100644 --- a/spec/RateLimit.spec.js +++ b/spec/RateLimit.spec.js @@ -19,6 +19,27 @@ describe('rate limit', () => { ); }); + it('can limit cloud functions with user session token', async () => { + await Parse.User.signUp('myUser', 'password'); + Parse.Cloud.define('test', () => 'Abc'); + await reconfigureServer({ + rateLimit: [ + { + requestPath: '/functions/*', + requestTimeWindow: 10000, + requestCount: 1, + errorResponseMessage: 'Too many requests', + includeInternalRequests: true, + }, + ], + }); + const response1 = await Parse.Cloud.run('test'); + expect(response1).toBe('Abc'); + await expectAsync(Parse.Cloud.run('test')).toBeRejectedWith( + new Parse.Error(Parse.Error.CONNECTION_FAILED, 'Too many requests') + ); + }); + it('can add global limit', async () => { Parse.Cloud.define('test', () => 'Abc'); await reconfigureServer({ diff --git a/src/middlewares.js b/src/middlewares.js index 46c4a32a43..788c9a3f62 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -276,7 +276,13 @@ const handleRateLimit = async (req, res, next) => { if (pathExp.test(req.url)) { await limit.handler(req, res, err => { if (err) { - throw err; + if (err.code === Parse.Error.CONNECTION_FAILED) { + throw err; + } + req.config.loggerController.error( + 'An unknown error occured when attempting to apply the rate limiter: ', + err + ); } }); } @@ -284,7 +290,7 @@ const handleRateLimit = async (req, res, next) => { ); } catch (error) { res.status(429); - res.json({ code: Parse.Error.CONNECTION_FAILED, error }); + res.json({ code: Parse.Error.CONNECTION_FAILED, error: error.message }); return; } next(); @@ -477,7 +483,10 @@ export const addRateLimit = (route, config) => { max: route.requestCount, message: route.errorResponseMessage || RateLimitOptions.errorResponseMessage.default, handler: (request, response, next, options) => { - throw options.message; + throw { + code: Parse.Error.CONNECTION_FAILED, + message: options.message, + }; }, skip: request => { if (request.ip === '127.0.0.1' && !route.includeInternalRequests) { @@ -498,7 +507,7 @@ export const addRateLimit = (route, config) => { } } } - return request.auth.isMaster; + return request.auth?.isMaster; }, keyGenerator: request => { return request.config.ip;