From 5d2ab3f55435124395d8474512b99e779c1f0adc Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 14 Jun 2023 19:31:18 +0800 Subject: [PATCH 1/2] create another rate limiter for auth api with 4 rpm --- packages/api/src/server.ts | 63 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index e0e38baa9..5837ae153 100755 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -48,6 +48,7 @@ import { webhooksServiceRouter } from './routers/svc/webhooks' import { textToSpeechRouter } from './routers/text_to_speech' import { userRouter } from './routers/user_router' import { sentryConfig } from './sentry' +import { getClaimsByToken } from './utils/auth' import { corsConfig } from './utils/corsConfig' import { buildLogger, buildLoggerTransport } from './utils/logger' @@ -97,32 +98,30 @@ export const createApp = (): { app.use(json({ limit: '100mb' })) app.use(urlencoded({ limit: '100mb', extended: true })) - if (!env.dev.isLocal) { - const apiLimiter = rateLimit({ - windowMs: 60 * 1000, // 1 minute - max: 100, - // async (req) => { - // // 100 RPM for an authenticated request, 5 for a non-authenticated request - // // const token = await getClaimsByToken( - // // // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - // // req.header('authorization') ?? req.cookies['auth'] - // // ) - // return 100 // token ? 100 : 10 - // }, - standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers - legacyHeaders: false, // Disable the `X-RateLimit-*` headers - keyGenerator: (req) => { - return ( - req.header('authorization') || - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - (req.cookies['auth'] as string) || - req.ip - ) - }, - }) - // Apply the rate limiting middleware to API calls only - app.use('/api/', apiLimiter) - } + const apiLimiter = rateLimit({ + windowMs: 60 * 1000, // 1 minute + max: async (req) => { + // 100 RPM for an authenticated request, 5 for a non-authenticated request + const token = await getClaimsByToken( + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + req.header('authorization') ?? req.cookies['auth'] + ) + return token ? 100 : 5 + }, + keyGenerator: (req) => { + return ( + req.header('authorization') || + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + (req.cookies['auth'] as string) || + req.ip + ) + }, + // skip preflight requests and test requests + skip: (req) => req.method === 'OPTIONS' || env.dev.isLocal, + }) + + // Apply the rate limiting middleware to API calls only + app.use('/api/', apiLimiter) // set client info in the request context app.use(httpContext.middleware) @@ -137,11 +136,19 @@ export const createApp = (): { // respond healthy to auto-scaler. app.get('/_ah/health', (req, res) => res.sendStatus(200)) - app.use('/api/auth', authRouter()) + // 5 RPM for auth requests + const authLimiter = rateLimit({ + windowMs: 60 * 1000, // 1 minute + max: 5, + // skip preflight requests and test requests + skip: (req) => req.method === 'OPTIONS' || env.dev.isLocal, + }) + + app.use('/api/auth', authLimiter, authRouter()) + app.use('/api/mobile-auth', authLimiter, mobileAuthRouter()) app.use('/api/page', pageRouter()) app.use('/api/user', userRouter()) app.use('/api/article', articleRouter()) - app.use('/api/mobile-auth', mobileAuthRouter()) app.use('/api/text-to-speech', textToSpeechRouter()) app.use('/api/notification', notificationRouter()) app.use('/api/integration', integrationRouter()) From a621ca24bf53290944862d429a335f7a62c4ae1c Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 14 Jun 2023 20:07:17 +0800 Subject: [PATCH 2/2] fix test --- packages/api/test/routers/integrations.test.ts | 1 - packages/thumbnail-handler/test/index.test.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/api/test/routers/integrations.test.ts b/packages/api/test/routers/integrations.test.ts index 4843ebf70..458e97d47 100644 --- a/packages/api/test/routers/integrations.test.ts +++ b/packages/api/test/routers/integrations.test.ts @@ -395,7 +395,6 @@ describe('Integrations routers', () => { after(async () => { sinon.restore() - nock.cleanAll() await deleteTestIntegrations(user.id, [integration.id]) }) diff --git a/packages/thumbnail-handler/test/index.test.ts b/packages/thumbnail-handler/test/index.test.ts index 575cfc87d..0eacbca11 100644 --- a/packages/thumbnail-handler/test/index.test.ts +++ b/packages/thumbnail-handler/test/index.test.ts @@ -23,8 +23,5 @@ describe('findThumbnail', () => { const thumbnail = await findThumbnail(content) expect(thumbnail).to.eql('https://omnivore.app/large_and_square.png') - - // clean up - nock.cleanAll() }) })