fix: Rate limiter may reject requests that contain a session token (#8399)

This commit is contained in:
Daniel
2023-01-26 00:35:39 +11:00
committed by GitHub
parent 8f7a8f4c9d
commit c114dc8831
2 changed files with 34 additions and 4 deletions

View File

@@ -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 () => { it('can add global limit', async () => {
Parse.Cloud.define('test', () => 'Abc'); Parse.Cloud.define('test', () => 'Abc');
await reconfigureServer({ await reconfigureServer({

View File

@@ -276,7 +276,13 @@ const handleRateLimit = async (req, res, next) => {
if (pathExp.test(req.url)) { if (pathExp.test(req.url)) {
await limit.handler(req, res, err => { await limit.handler(req, res, err => {
if (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) { } catch (error) {
res.status(429); res.status(429);
res.json({ code: Parse.Error.CONNECTION_FAILED, error }); res.json({ code: Parse.Error.CONNECTION_FAILED, error: error.message });
return; return;
} }
next(); next();
@@ -477,7 +483,10 @@ export const addRateLimit = (route, config) => {
max: route.requestCount, max: route.requestCount,
message: route.errorResponseMessage || RateLimitOptions.errorResponseMessage.default, message: route.errorResponseMessage || RateLimitOptions.errorResponseMessage.default,
handler: (request, response, next, options) => { handler: (request, response, next, options) => {
throw options.message; throw {
code: Parse.Error.CONNECTION_FAILED,
message: options.message,
};
}, },
skip: request => { skip: request => {
if (request.ip === '127.0.0.1' && !route.includeInternalRequests) { 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 => { keyGenerator: request => {
return request.config.ip; return request.config.ip;