0

Hey i am creating a rest api using webflux for learning purpose and i am stuck with bcrypt password matches at login page.

My login request is taking extra time and when i dig little more I found that matches function is a heavy task and time consuming and i am afraid that it could effect the entire applications performance

Below is my code

.filter(user -> {
    long s = System.currentTimeMillis();
    boolean matches = bCryptPasswordEncoder.matches(loginRequest.getPassword(), user.getPassword());
    long e = System.currentTimeMillis();
    System.out.println(e-s);
    return matches;
})

My whole api response time is 70 ms and the time diff is printing 62, 63 it means matches is slowing down my entire application. what if i got 50 login request at a time. I wonder what is the proper way of doing this in non-blocking way.

Muhammad Ilyas
  • 200
  • 2
  • 12
  • 1
    if you are using spring security, then why are you doing the password matching yourself, and not using the frameworks built in login features? also, 70ms is quite fast. You don't want fast password matching because that can be used by malicious actors to try passwords fast. BCrypt is what is known as a "slow" algorithm, and should be tuned to match passwords every second on the running system to prevent password spray attacks. – Toerktumlare Aug 03 '20 at 21:21
  • you can read more about passwords here https://docs.spring.io/spring-security/site/docs/current/reference/html5/#authentication-password-storage-history – Toerktumlare Aug 03 '20 at 21:27
  • But my question is if the matching is taking time and since we are on limited thread it could pause the thread for 60 ms and other request may suffer. Am i wrong? – Muhammad Ilyas Aug 04 '20 at 03:39
  • Depending on the implementation then maybe, if that is the case then it should be placed on its own scheduler. There is no way to know for sure unless you do a load test. Thats why i still recommend you use the built in login implementation och dont try to build your own. – Toerktumlare Aug 04 '20 at 07:53

1 Answers1

3

An operation "blocks" when the CPU is essentially idle, waiting for something else to complete before it can do any more work. This could be a network request, disk access, time delay, etc.

What you have here isn't this, so it's not a blocking operation. You instead have a CPU-intensive operation, which is the point of BCrypt (in a nutshell, checking whether a password is valid is deliberately hard to prevent brute-forcing attacks.)

There's no way to speed this up for "free" (otherwise you've broken BCrypt), but there's a few approaches you can take depending on the situation. From "least work" to "most work":

  • It's 70ms, which for testing / learning purposes is fine. Don't get stuck into the details, and just accept it in this situation.
  • Parallelise the flux by calling parallel() and subscribeOn(Schedulers.parallel()) to enable your reactive chain to use all CPU cores. This is probably the most that makes sense for a "learning & development" scenario.
  • Throw more hardware at the problem if it's an issue, such as containerising and using Kubernetes or similar to auto-scale based on demand.
  • Farm the BCrypt work out to a separate microservice, auto-scale that as necessary, and then deal with the password checking in a non-blocking fashion by calling that microservice (and using flatMap().)
Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • if i use paraller then there is still limit because reactor create threads which is equal to core like a 4 core processor. then what if 100 people request at the same time? – Muhammad Ilyas Aug 08 '20 at 12:30
  • @MuhammadIlyas Then, assuming you parallelise it across 4 cores, then a back of the envelope calculation shows that's going to take a couple of seconds for all of those login requests to execute. Not the end of the world - but if you're genuinely seeing that volume of traffic, you'd probably want to upgrade your hosting hardware anyway. As said in the answer, there's no easy way around it. Assuming you don't want to ditch BCrypt not use a less CPU-intensive setting, the only option you're feasibly left with is to throw more hardware at the problem somehow. – Michael Berry Aug 08 '20 at 14:20