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...