-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from fless-lab/secutiry/enhance-app-security
sec: bruteforce and api rate limit enhanced
- Loading branch information
Showing
6 changed files
with
60 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,52 @@ | ||
import Brute from 'express-brute'; | ||
import MongooseStore from 'express-brute-mongo'; | ||
import mongoose from 'mongoose'; | ||
import { RateLimiterMongo } from 'rate-limiter-flexible'; | ||
import { Request, Response, NextFunction } from 'express'; | ||
import config from '../../../config'; | ||
import { DB } from '../../../framework'; | ||
|
||
const store = new MongooseStore(function (ready) { | ||
mongoose.connect(config.db.uri, { | ||
dbName: config.db.name, | ||
}); | ||
ready(mongoose.connection.collection('bruteforce-store')); | ||
}); | ||
|
||
const bruteForce = new Brute(store, { | ||
freeRetries: config.bruteForce.freeRetries, // Number of allowed retries before applying restrictions | ||
minWait: config.bruteForce.minWait, // Minimum wait time (in milliseconds) | ||
maxWait: config.bruteForce.maxWait, // Maximum wait time (in milliseconds) | ||
lifetime: config.bruteForce.lifetime, // Lifetime (in seconds) | ||
failCallback: function (req, res, next, nextValidRequestDate) { | ||
let bruteForceLimiter: RateLimiterMongo | undefined; | ||
|
||
const setupRateLimiter = async (): Promise<void> => { | ||
try { | ||
await DB.mongo.init(config.db.uri, config.db.name); | ||
const mongoConn = await DB.mongo.getClient(); | ||
|
||
bruteForceLimiter = new RateLimiterMongo({ | ||
storeClient: mongoConn, | ||
points: config.bruteForce.freeRetries, // Nombre de tentatives autorisées | ||
duration: Math.ceil(config.bruteForce.lifetime / 1000), // Durée de vie en secondes | ||
blockDuration: Math.ceil(config.bruteForce.maxWait / 1000), // Durée de blocage en secondes | ||
}); | ||
|
||
console.log('Rate limiter configured.'); | ||
} catch (error) { | ||
console.error('Error setting up rate limiter:', error); | ||
} | ||
}; | ||
|
||
setupRateLimiter(); | ||
|
||
const bruteForceMiddleware = async ( | ||
req: Request, | ||
res: Response, | ||
next: NextFunction, | ||
): Promise<void> => { | ||
if (!bruteForceLimiter) { | ||
res.status(500).json({ | ||
message: 'Rate limiter not configured yet. Please try again later.', | ||
}); | ||
return; | ||
} | ||
|
||
try { | ||
await bruteForceLimiter.consume(req.ip as string); | ||
next(); | ||
} catch (rejRes: any) { | ||
const retrySecs = Math.ceil(rejRes.msBeforeNext / 1000) || 1; | ||
!config.runningProd && res.set('Retry-After', String(retrySecs)); //Send Retry-After only in dev mode | ||
res.status(429).json({ | ||
message: `Too many attempts, please try again after ${Math.ceil( | ||
(nextValidRequestDate.getTime() - Date.now()) / 60000, | ||
)} minutes.`, | ||
message: `Too many attempts, please try again after ${Math.ceil(rejRes.msBeforeNext / 60000)} minutes.`, | ||
}); | ||
}, | ||
}); | ||
} | ||
}; | ||
|
||
export default bruteForce; | ||
export default bruteForceMiddleware; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
export * from './client-authentication'; | ||
export { default as authenticateRequest } from './authenticate-request'; | ||
export { default as bruteForce } from './bruteforce'; | ||
export { default as bruteForceMiddleware } from './bruteforce'; | ||
export * from './rate-limiter'; | ||
export * from './validate'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters