Web Application Authentication Best Practices in 2022
Learn more about what to keep in mind to ensure data security for your web apps.
July 14, 2023
Countless web applications have been developed since they have a lot of advantages over on-premise software. Users can easily access these services through web browsers without having to install the program on their laptops, freeing them from geographical limitations. However, a huge amount of information, especially information needed for authentication, is exchanged between the user’s device and the server of web applications, making security more important than ever.
In the previous blog post, we listed down some password reset best practices. To make sure your application is as secure as it can be, we have compiled a list of best practices of developing web applications with secure authentication mechanisms.
(If you're looking for guides to implement authentication in your web applications, you can check out our latest guide here.)
The Basics of Securing the Authentication Process for Your Web Application
Use a Single Failure Message When Users Try to Log In
It is recommended to show a uniform failure message whether the user inputs the wrong username or password. With separate “invalid user” or “wrong password” messages, attackers can often guess whether an username exists or not. From there, they can then start guessing the password for that particular account.
Security Sockets Layer (SSL) is a protocol that allows encrypted communication between a client and a server. Websites and web applications without SSL certificates are like restaurants without the approval of food inspectors. You can still use the services but there’s no guarantee that everything will be peachy.
Once your website or web application installs and configures an SSL certificate, it can then use the HTTPS protocol to make sure that any private information of your users, such as login information, payment, and more, passed between a browser and a server is encrypted. Without HTTPS, hackers can easily eavesdrop and look at the data during data transmission.
Hash The Passwords "Slowly"
Securely storing sensitive user information is paramount as data breach can have horrific ramifications. It is always not recommended for developers to save users’ passwords in plain text as hackers can then effortlessly obtain all their credentials once they break into your database.
One approach to store passwords more securely is to hash the passwords by running an one-way function to convert the password into another representation through a mathematical algorithm. This is different from encryption as the password that has undergone hashing, also known as a hash, cannot be converted back into its original plain text form. Although traditional hashing methods were designed to be fast, password hashing should be slow to make the lives of attackers trying to brute-force a password much harder. Even though you can still see some applications using MD5 or SHA-1, these algorithms are not designed for hashing passwords. They are designed to be quick. Thus, hackers can brute-force them rather easily. Moreover, developers have found some vulnerabilities in them and therefore MD5 and SHA-1 are usually not recommended. OWASP recommends other password hashing algorithms, such as Argon2id, scrypt, bcrypt, and PBKDF2, which are specifically designed for securely storing passwords.
Season the Passwords With Some Salt Before They Get Hashed
Simply hashing the passwords is not enough as there are still a few ways, such as dictionary attack and brute-force attack, for hackers to decode hashes. To make it even more secure, you also need to salt the password by adding an extra string to it before hashing. Salting is important as it will require more computational power for hackers to expose the hash. All password hashing algorithms mentioned above recommended by OWASP have Salting included.
Enable Multi-Factor Authentication
Some of the industry’s largest players have required multi-factor authentication (MFA) for a reason. The good old username and password is not as secure as you think. In 2013, Deloitte claimed that more than 90% of user-generated passwords are vulnerable to hacking. Having that single layer of fragile protection can no longer protect sensitive user information.
Web applications now often implement MFA to add additional layers of cybersecurity. Most of the time, a minimum of two factors are needed to authenticate a user (this is also known as two-factor authentication or 2FA). Some passwordless authentication methods, such as fingerprint scan, facial recognition, OTP sent to WhatsAPP or Telegram, etc., have been included in the authentication process since these alternatives are more difficult for hackers to imitate.
Save Sensitive Information Separate From Regular Data
Sometimes, web application developers might store all user information, such as id, username, password, name, email, last_login_time, etc., in the same table. It might seem reasonable at the beginning, but this creates several problems when you try to grant different levels of access for different users or when you want to get only the non-confidential parts of the data.
A developer might simply type “SELECT * FROM users_info” when querying for data, but the sensitive data will then be exposed. This can be easily avoided by storing confidential information in a separate table or even going the extra mile to put it in another database for better protection.
Brain Overload? Let Authgear Take Care of Your Web App Authentication
For you to focus on app development rather than authentication
The Easily Forgotten Steps to Secure an Authentication Server for Your Web Application
✓ Choose and Set Up the Hashing Algorithm Properly
We mentioned that passwords must not be stored in plain text form; however, to correctly hash a password is not trivial.
The password algorithm “bcrypt” is a common choice. This is a good option but you must remember that there is a maximum length limit of 72 bytes (32 unicode characters). If you are using bcrypt in your application, you should enforce an input limit and not truncate the password silently in the backend.
The current best password hashing algorithm is Argon2 (Argon2id variant) as it provides a balanced approach to resisting both side-channel and GPU-based attacks. There are three different parameters that can be configured, namely the minimum memory size (m), the minimum number of iterations (t) and the degree of parallelism (p). You should test different parameters on your system to achieve a hash time between 500ms to 1 second to offer a balance between user experience and resistance to attacks.
✓ If JWT token is used, verify against the Key ID
While JWT tokens are not being recommended by many as auth tokens, there are various reasons people have to use it. However, you have to beware of the critical vulnerabilities that allow attackers to bypass the verification. To ensure the server uses the correct cipher and algorithm to verify the token, JWK (JSON web key) and the “kid” (Key ID) header should be used. The servers can always look up the key cipher and algorithm using the Key ID included in the JWT received.
✓ Ensure No Hardcoded Secrets or Backdoor
Due to developers’ mistakes or negligence, it is common as the team grows or when the system gets more complicated, some secrets will be hardcoded in the system.
While we perform audits or code reviews for our clients, another common problem is that authentication systems intentionally leave backdoors, such as granting superpower when a special value is set in the HTTP header whether it is for the easy debug / UAT reasons.
This is a serious problem because once the attacker has access to your source code, e.g. it got leaked, the security system is immediately compromised.
✕ Lack of Audit Log
When attacks happen, a detailed audit log of login and failure attempts is extremely useful for tracking down the attackers and blocking further attempts. The log is also a valuable tool to find out the system vulnerabilities that need to be patched.
✕ SSO Implemented Relying on Client Side
Another common problem we see is that the authentication via social platform OAuth 2.0 is entirely handled on the client-side, and then rely on the client-side to report the user ID without further verification. This opens up the risk of spoofing.
✓ Generate Random Numbers With a Cryptographic Strong Source
Computers generate random numbers by using seed values. The random sequence is possible to be reproduced if the seed value is known. These algorithms are called Pseudo-Random Number Generators (PRNGs). There are two types of PRNGs, statistical and cryptographic. Statistical PRNGs are useful in statistical applications; while cryptographic PRNGs should be used when security depends on the value being unpredictable.
For example, a random URL is created for a receipt that remains active for some period of time. It is crucial that the sequence in the URL is not predictable for the attacker; otherwise, it will be easy for the attacker to guess the URL of an active receipt.
Both algorithms can usually be found in different programming languages. For instance, Java provides “Random.nextInt()” for statistical PRNG and “SecureRandom” for cryptographic PRNG.
Integrate Your Web Application with Authgear for More Secure Authentication
Cybersecurity is no longer an afterthought as hackers are also developing new methods to steal credentials from users. In order to keep up with them, developers have to act proactively, but that can be quite exhausting.
With Authgear, we make sure that your web application’s authentication mechanisms are as secure as possible for your team to focus on developing core functionality. We will not only take care of the aforementioned security concerns for you but also help you provide better authentication experience and reduce costs. Contact us now for us to learn more about your web application and how Authgear can be of help to it.