User Authentication Best Practices Checklist

User authentication is the functionality that every web application shared. We should have perfected that a long time ago, having implemented it so many times. And yet there are so many mistakes made all the time. Part of the reason for that is that the list of things that can go wrong is long. You can store passwords incorrectly, you can have a vulnerably password reset functionality, you can expose your session to a CSRF attack, your session can be hijacked, etc. So I’ll try to compile a list of best practices regarding user authentication. OWASP top 10 is always something you should read, every year. But that might not be enough. So, let’s start. I’ll try to be concise, but I’ll include as much of the related pitfalls as I can cover – e.g. what could go wrong with the user session after they login: Store passwords with bcrypt/scrypt/PBKDF2. No MD5 or SHA, as they are not good for password storing. Long salt (per user) is mandatory (the aforementioned algorithms have it built in). If you don’t and someone gets hold of your database, they’ll be able to extract the passwords of all your users. And then try these passwords on other websites. Use HTTPS. Period. (Otherwise user credentials can leak through unprotected networks). Force HTTPS if user opens a plain-text version. Mark cookies as secure. Makes cookie theft harder. Use CSRF protection (e.g. CSRF one-time tokens that are verified with each request). Frameworks have such functionality built-in. Disallow framing (X-Frame-Options: DENY). Otherwise your website may be included in another website in a hidden iframe and “abused” through...

Enabling Two-Factor Authentication For Your Web Application

It’s almost always a good idea to support two-factor authentication (2FA), especially for back-office systems. 2FA comes in many different forms, some of which include SMS, TOTP, or even hardware tokens. Enabling them requires a similar flow: The user goes to their profile page (skip this if you want to force 2fa upon registration) Clicks “Enable two-factor authentication” Enters some data to enable the particular 2FA method (phone number, TOTP verification code, etc.) Next time they login, in addition to the username and password, the login form requests the 2nd factor (verification code) and sends that along with the credentials I will focus on Google Authenticator, which uses a TOTP (Time-based one-time password) for generating a sequence of verification codes. The ideas is that the server and the client application share a secret key. Based on that key and on the current time, both come up with the same code. Of course, clocks are not perfectly synced, so there’s a window of a few codes that the server accepts as valid. Note that if you don’t trust Google’s app, you can implement your own client app using the same library below (though you can see the source code to make sure no shenanigans happen). How to implement that with Java (on the server)? Using the GoogleAuth library. The flow is as follows: The user goes to their profile page Clicks “Enable two-factor authentication” The server generates a secret key, stores it as part of the user profile and returns a URL to a QR code The user scans the QR code with their Google Authenticator app thus creating a...

Basic API Rate-Limiting

It is likely that you are developing some form of (web/RESTful) API, and in case it is publicly-facing (or even when it’s internal), you normally want to rate-limit it somehow. That is, to limit the number of requests performed over a period of time, in order to save resources and protect from abuse. This can probably be achieved on web-server/load balancer level with some clever configurations, but usually you want the rate limiter to be client-specific (i.e. each client of your API sohuld have a separate rate limit), and the way the client is identified varies. It’s probably still possible to do it on the load balancer, but I think it makes sense to have it on the application level. I’ll use spring-mvc for the example, but any web framework has a good way to plug an interceptor. So here’s an example of a spring-mvc interceptor: @Component public class RateLimitingInterceptor extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory.getLogger(RateLimitingInterceptor.class); @Value("${rate.limit.enabled}") private boolean enabled; @Value("${rate.limit.hourly.limit}") private int hourlyLimit; private Map<String, Optional<SimpleRateLimiter>> limiters = new ConcurrentHashMap<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!enabled) { return true; } String clientId = request.getHeader("Client-Id"); // let non-API requests pass if (clientId == null) { return true; } SimpleRateLimiter rateLimiter = getRateLimiter(clientId); boolean allowRequest = limiter.tryAcquire(); if (!allowRequest) { response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); } response.addHeader("X-RateLimit-Limit", String.valueOf(hourlyLimit)); return allowRequest; } private SimpleRateLimiter getRateLimiter(String clientId) { if (limiters.containsKey(clientId)) { return limiters.get(clientId); } else { synchronized(clientId.intern()) { // double-checked locking to avoid multiple-reinitializations if (limiters.containsKey(clientId)) { return limiters.get(clientId); } SimpleRateLimiter rateLimiter = createRateLimiter(clientId); limiters.put(clientId, rateLimiter); return rateLimiter; } } } @PreDestroy public void...