As I mentioned in the previous posts, handling user registration and login is an important part of this project. The easiest way to do this is to save the password in plain text and check it with the stored record. However, this method is not acceptable nowadays. There are several concerns with it. For example, the site administrators can read all the data in the database, but they should not be able to see users’ passwords. We need to protect users’ privacy. Also, if a plain password is sent over the network, it could be leaked and become a target of a man-in-the-middle attack. Therefore, handling user credentials safely is a very important topic.

Feature requirements

  • Register a unique user (username and password).
  • The password needs to be encrypted in the database and should be verifiable in the future.
  • Users should be able to log in using their username and password.
  • Logged-in users can stay signed in automatically for 30 days.
  • All user-related APIs need to verify the user’s credentials.
  • Prevent brute-force login attacks.

Option 1

  1. The frontend uses MD5 to encrypt the user password before sending it to the backend for storage.
  2. Prevent the same user from registering twice.
  3. Generate a session ID for frontend use (as a cookie) and save it in the backend session table.
  4. Implement session ID (cookie) validation in user-related APIs.
  5. Use Google reCAPTCHA in the registration and login process.

Option 2

  1. Enable forced HTTPS on the frontend, and send the plain password directly to the backend. The backend uses PBKDF2 with salt to encrypt the password and save it in the database.
  2. Prevent the same user from registering twice.
  3. Generate a session ID for frontend use (as a cookie) and save it in the backend session table.
  4. Implement session ID (cookie) validation in user-related APIs.
  5. Use Google reCAPTCHA in the registration and login process.

Using HTTPS is a fundamental measure to protect user data. Unlike HTTP, HTTPS encrypts all data in transit using TLS (Transport Layer Security), which prevents attackers from intercepting or tampering with sensitive information such as passwords or session tokens. Even on public Wi-Fi, encrypted communication ensures that data remains confidential and intact. Additionally, HTTPS uses digital certificates issued by trusted Certificate Authorities (CAs) to verify the server’s identity, preventing users from connecting to fake or malicious websites. Modern browsers also label HTTP sites as “Not Secure,” which can damage user trust. Therefore, HTTPS is not only a basic security requirement but also a key factor in improving user experience and search engine ranking.

PBKDF2 (Password-Based Key Derivation Function 2) is a cryptographic algorithm designed to transform a password into a secure cryptographic key. When combined with a random salt, it becomes highly effective at securely storing passwords.

Prevents rainbow table attacks
Salt is random for each user, so even if two users have the same password, the resulting hash is different.
This makes precomputed rainbow tables useless.

Brute-force resistance
PBKDF2 performs many iterations (e.g., 100,000+), making each password guess computationally expensive.
Attackers must perform these iterations for every guess, drastically reducing the speed of cracking.

Standardized and trusted
Recommended by NIST and defined in RFC 8018.
Widely implemented and audited across many systems and libraries (e.g., Java, Python, OpenSSL).

Comparsion

  • MD5 is not enough safety nowadays, hacks could brute force it to get the real password.
  • Using HTTP to transport the password (even an encrypted password) could be captured by the man-in-the-middle attack.
  • PBKDF2 + salt with HTTPS is safe, so we choose the option.

Some findings and thoughts

Although the solution can achieve the goal, it still lacks some important considerations if it is to become a real product. These issues need to be addressed in the future. For example:

  • Limit login attempts and support IP blacklisting
  • Prevent the misuse of stolen cookies
  • Use more advanced password encryption algorithms
  • Handle situations where users forget their username or password
  • Support changing the password or email address
  • Implement two-factor authentication
  • Prevent plain passwords from being logged in application logs
  • JWT or OAuth2 would be more suitable for a production product