0

I've just built an API in node.

I'm calling this API in my angular app to do basics like login and register, for example:

self.register = function(username, password) {
  return $http.post(API + '/auth/register', {
      username: username,
      password: password
    })
}

So my question is, anyone could see that API URL, so whats stopping them from 'bashing' it to create users at there will. (Note API is a constant in my JS file). The same goes for the login, whats to stop someone from brute force trying millions of username and password combinations.

And what would you recommend in securing this?

Thanks.

userMod2
  • 8,312
  • 13
  • 63
  • 115
  • Possible duplicate of [Block request for multiple unsuccessful logins for a period of time](http://stackoverflow.com/questions/30369529/block-request-for-multiple-unsuccessful-logins-for-a-period-of-time) – Neil McGuigan Dec 16 '15 at 19:56

4 Answers4

5

You can use some DDoS protection, for example put nginx proxy in front of your nodejs API and use e.g. limit_req module: http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

For brute force you can implement some lock-out logic, that after number of errors will block account for some time, e.g. 15-30 minutes or even will require an admin action.

For APIs that require to be logged in you can use token protection. The token should be issued when authentication API is called and set via HTTP only secure cookie in response. Then you can pass this token in API request headers and before each protected API execution in nodejs just check if it's valid and reject the call if it's not.

scareddragon
  • 435
  • 2
  • 7
  • 1
    Also in case you're using Express with Node.js consider the modules Helmet (https://github.com/helmetjs/helmet) or Lusca (https://github.com/krakenjs/lusca). that will help secure the HTTP headers of the requests. – pgrodrigues Dec 16 '15 at 16:04
1

+1 on scareddragon.

If you live in the cloud there is a better, cloud-based alternative to using nginx - using a cloud WAF (web application firewall) as your DDoS mitigation layer. For example check out Incapsula and CloudFlare.

If DDoS is a serious concern for you and you're willing to pay for defense against it, this is one concern I would definitely leave to experts.

orange77
  • 933
  • 8
  • 12
1

You are asking about registration abuse and login protection, basically:

  1. How to mitigate account creation automation?
  2. How to mitigate user/password guessing?

Thankfully, these are mostly solved issues.

To avoid registration “bashing”, you need to disrupt the automation. This can be achieved by various approaches, from loose to strict:

  1. If the API is only intended to be accessed by a specific app/browser, you can filter-out all other visitors
  2. Rate-limit registration by session/IP
  3. Require passing a CAPTCHA
  4. Validate E-Mail address
  5. Require a private sensitive detail as proof of identity (e.g., phone-number, credit-card)

What’s nice about this, is that 1-3 are tasks that can be easily offloaded to a modern Web Application Firewall without any additional server-side coding or additional load.

For "Login Protection", in addition to the above-mentioned methods 1-3, there are two more that are recommended:

  1. Two-Factor Authentication (2FA) - This basically means that in addition to his “regular” password, the user needs to enter another token of authentication. This token can be generated by TOTP (see Google Authenticator), or a code sent by the server via SMS, Email, Phone call, etc.

  2. API Keys - This is considered safer, because API Keys are usually very long unique strings that have very good entropy (compared to user/pass combos). More about API Keys here.

Before I go, a small remark: I saw some previous comments referring to DDoS, and I can’t stress this enough – YOU CANNOT MITIGATE DDOS BY YOURSELF. But that’s for a different thread.

Good luck!

ZigZag_IL
  • 134
  • 3
1

It is better to limit rates on reverse-proxy, load balancer or any other entry point by IP.

IF you wish to do it in nodejs, I'd recommend rate-limiter-flexible

const { RateLimiterRedis } = require('rate-limiter-flexible');
const Redis = require('ioredis');

const redisClient = new Redis({
  options: {
    enableOfflineQueue: false
  }
});

const opts = {
  redis: redisClient,
  points: 5, // 5 points
  duration: 15 * 60, // Per 15 minutes
  blockDuration: 15 * 60, // block for 15 minutes if more than points consumed 
};

const rateLimiter = new RateLimiterRedis(opts);

self.register = async function(username, password) {
  let blocked = false;
  try {
    await rateLimiter.consume(clientIP, 1);
  } catch() {
    blocked = true;
  }

  if (blocked) {
    return false;
  }

  return $http.post(API + '/auth/register', {
      username: username,
      password: password
    })
}
Animir
  • 1,121
  • 10
  • 23