Users and other systems can log into Phoenix via the Session API. To prevent excessive login attempts from bots, the Session API can now require clients to provide a Google reCAPTCHA code after a certain number of failed logins within a given time frame.
Google reCAPTCHA (official site) is a way of preventing bots from hammering login forms. It is far less annoying than the old-style CAPTCHA (where you had to try to read and type in an obscure bit of text) but still annoying enough that we only want to require users to fill it in if they have failed to login several times in a row (see "Configuration variables", below).
API clients (such as our login forms) make a POST to /api/session, containing the values "username" and "password". The username can be a username or an email address. Note that a very small percentage of email addresses are duplicated (0.008% on ATD). The login is currently passed through to the D6 core function user_load(), which will load the first user it finds with a matching username/email and password. On dev environments with all the users set to have the same email address and password, it is better to log in with a unique username instead.
Successful logins will receive a 200 response.
Unsuccessful logins will receive a 403 response and an error message in the returned json object's "err_desc" field.
After a certain number of failed logins within a certain time period (see the "Configuration variables" section, below), the API will require users to supply a reCAPTCHA code for subsequent login requests within the defined time period. In these cases, the API will return a 403 response code and the json body will contain "captcha_required: 1, captcha_site_key: xxx", where xxx is the Google reCAPATCHA site key for the current domain (see "Site keys" below). The client must then display a reCAPTCHA element within the login form, using the given site key. The reCAPTCHA code will automatically add a hidden input to its parent form called "g-recaptcha-response", containing the result of the user's interaction with the reCAPTCHA element. When a POST is made to /api/session and the API determines that a reCAPTCHA code is required, the value of the "g-recaptcha-response" is verified with Google. If both the reCAPTCHA value and the login details are correct then the login will succeed (response code 200), otherwise the login will fail (response code 403) and the json body's "err_desc" field will contain a message explaining why.
The following variables are used to configure the use of Google reCAPTCHA on our sites:
login_captcha_enabledIf TRUE, Google reCAPTCHA will be enabled.FALSElogin_seconds_before_captchaThe number of seconds considered when looking for the number of recent failed logins.30login_fails_before_captchaThe number of failed logins in the last login_seconds_before_captcha before the user must enter a reCAPTCHA code along with their next login attempt.3login_failed_delay_secondsThe delay in seconds to wait before responding to an unsuccessful login attempt. Set to a number low enough so as not to annoy people, but high enough to prevent bots from hammering us with hundreds of login attempts per second.1
For example, if the login_seconds_before_captcha is 30 and login_fails_before_captcha is 3, users are allowed 3 failed logins within a 30 second window, before they are requried to enter a reCAPTCHA code with their next login attempt. This prevents bots from submitting large numbers of login attempts, whilst ensuring users aren't constantly having to enter reCAPTCHA codes.
Note that it can take a few minutes for variables changes to be reflected in Redis, so changes may not be immediate.
A new database table "api_login" has been created log information about API-based login attempts. The database structure can be found here.
This small module provides functions for getting the current site's reCAPTCHA site key and verifying that a submitted reCAPTCHA response is valid.
Google reCAPTCHA site keys
These reCAPTCHA keys have been set up using the Google account listed here.
The keys for each domain are set up to work with our live, staging and local domain names for each domain.
These are stored in the d6 database table "domain_recaptcha_keys" (statements used to create this table and data here).