I'm trying to put a DDP rate limiter on the number of login attempts coming in from the client to the server. I've gone through the official documentation but I'm unable to verify if any of it actually works.
I've added the package: ddp-rate-limiter
My server code is:
Meteor.startup(function() {
var preventBruteForeLogin= {
type: 'method',
name: 'Meteor.loginWithPassword'
}
DDPRateLimiter.addRule(preventBruteForeLogin, 1, 2000);
DDPRateLimiter.setErrorMessage("slow down");
});
My understanding with the above is that it has added a rate limiting rule on Meteor.loginWithPassword
method that it only allows one attempt every 2 seconds. However, given the little information available in the documentation and elsewhere on the net, I'm unable to figure out if it's actually working or if I've done it wrong. I've also gone through MC's blog on this and frankly I don't understand the coffee script code.
Can someone guide me through this?
Firstly according to the Meteor docs
By default, there are rules added to the DDPRateLimiter that rate limit logins, new user registration and password reset calls to a limit of 5 requests per 10 seconds per session.
If you want to remove, or replace default limits you should call Accounts.removeDefaultRateLimit()
somewhere in your server side code.
Next you should create method similar to this one below
Meteor.methods({
'meteor.login' ({ username, password }) {
Meteor.loginWithPassword({ user: username, password })
}
})
Then on your server side you should limit just created method.
if (Meteor.isServer) {
DDPRateLimiter.setErrorMessage(({ timeToReset }) => {
const time = Math.ceil(timeToReset / 1000)
return 'Try again after ' + time + ' seconds.'
})
DDPRateLimiter.addRule({
type: 'method',
name: 'meteor.login',
connectionId () {
return true
},
numRequests: 1,
timeInterval: 10000
})
}
This one will limit meteor.login
method to one call in 10 seconds using DDP connection id. When you call the method on your client side you can get remaining time using callback error object.
Personally, I do the rate limiting using a slightly changed method from themeteorchef guide. I suggest you to the same, because it is much easier to implement when you build app with more methods to limit and for me, it is more readable. It is written using ES6 syntax. I recommend to read a little bit about it and start using it(you don't have to install additional packages etc.). I am sure that you will quickly like it.
We found that using wrapping Meteor.loginWithPassword()
method in another method may cause security problems with sending password as plain text. Accounts package comes with Accounts._hashPassword(password)
method which returns hashed version of our password. We should use it when we call our meteor.login
method. It may be done like below
Meteor.call('meteor.login', username, Accounts._hashPassword(password), function (err) {
//asyncCallback
})