<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Authenticator</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
</head>
<body dir="ltr">
<h1>Authenticator</h1>
<h2>Description</h2>
<p>Configurable module that provides login and related functionality. </p>
<p>This module is thought to run as server-side code, and operated by another specific, custom piece of server code, we extensively refer to in this document as <em>client code</em>.</p>
<p>This module must NOT be directly targeted nor requested by a web browser.</p>
<h2>Features list</h2>
<ul>
<li>
<p>Open or closed registration, via master password</p>
</li>
<li>
<p>User role support</p>
</li>
<li>
<p>Live authentication (changing session unique id from one request to another)</p>
</li>
<li>
<p>Hack prevention built-in system:</p>
<ul>
<li>
<p>logout when obsolete session id is used</p>
</li>
<li>
<p>logout if IP changes from one request to another</p>
</li>
<li>
<p>logout when session lifetime times out</p>
</li>
<li>
<p>auto-lock on too many failed login attempts; auto-locks are IP-based and can be reset by master</p>
</li>
</ul>
</li>
<li>
<p>Password recovery OR reset support * </p>
</li>
</ul>
<p>* these two behaviours are mutually exclusive due to security reasons. Once a master has opted-in for <em>password</em> <em>reset</em> instead of <em>password</em> <em>recover</em>y, he cannot opt out; passwords won't be recoverable from that point onward, merely resetable.</p>
<h2>Authenticate</h2>
<p>The module is totally agnostic of anything. It does not even âknowâ whether a session is currently âaliveâ on a certain machine. It merely provides <em>the act of authentication</em> and authentication alone. Therefore, you must invoke it on each and every request, and <em>re-authenticate</em> from a request to another. There are three patterns of authentication supported.</p>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
<col width="128*" />
<col width="64*" />
<col width="64*" />
<tr valign="top">
<td rowspan="2"><p>IN</p></td>
<td colspan="2"><p>OUT</p></td>
</tr>
<tr valign="top">
<td><p>Success</p></td>
<td><p>Failure</p></td>
</tr>
<tr valign="top">
<td><p>Username and Password *</p></td>
<td><p>Unique session id</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>Username and MD5 hash of password **</p></td>
<td><p>Unique session id</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>Unique session id</p></td>
<td><p>New unique session id</p></td>
<td><p>Error number</p></td>
</tr>
</table>
<p>* only available if <em>password recovery </em>support <em class="underline">hasn't been </em>dropped.</p>
<p>** only available if <em>password recovery support </em><em class="underline">has been</em> dropped.</p>
<p>Based on whether you are returned a unique session id or an error number, client code must decide whether to consider the user authenticated and provide him with the protected content, or not.</p>
<p> <em>Note: MD5 hashes in the input data are there to support the ability of MD5 hashing some client side scripting languages have. If user provided MD5 of password at registration time, he must always provide MD5 instead of plain pass.</em></p>
<h2>(Self-)register</h2>
<p>This module provides support for open registration. This support can be dropped at master's choice. For security reasons, once the open registration support has been dropped, it cannot be enabled again. The following table describes the data exchange between the client code and this module, during the registration process.</p>
<p>This module also provides optional support for a security question and answer. This support can be dropped at master's choice. For security reasons, once the security question support has been dropped, it cannot be enabled again.</p>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
<col width="50*" />
<col width="78*" />
<col width="82*" />
<col width="46*" />
<tr valign="top">
<td rowspan="2" colspan="2"><p>IN</p></td>
<td colspan="2"><p>OUT</p></td>
</tr>
<tr valign="top">
<td><p>Success</p></td>
<td><p>Failure</p></td>
</tr>
<tr valign="top">
<td rowspan="2"><p>Security question OFF</p></td>
<td><p>User Email and Username and Password*</p></td>
<td><p>Confirmation unique id***</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>User Email and Username and MD5 hash of password**</p></td>
<td><p>Confirmation unique id***</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td rowspan="2"><p>Security question ON</p></td>
<td><p>User Email and Username and Password and Security Question and Security Answer*</p></td>
<td><p>Confirmation unique id***</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>User Email and Username and MD5 hash of password and Security Question and MD5 hash of security answer**</p></td>
<td><p>Confirmation unique id***</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td colspan="2"><p>Confirmation unique id</p></td>
<td><p>Unique session id****</p></td>
<td><p>Error number</p></td>
</tr>
</table>
<p>* only available if <em>password recovery </em>support <em class="underline">hasn't been </em>dropped.</p>
<p>** only available if <em>password recovery support </em><em class="underline">has been</em> dropped.</p>
<p>*** the client code is responsible for sending the <em>confirmation unique id</em> to the user, via e-mail, in order to proof that user actually owns that e-mail box.</p>
<p>**** the returned <em>unique session id </em>can be used for authentication (see <em>authenticate</em>).</p>
<p><em>Note: user name, user e-mail, user password (optionally security question and answer) <strong>AND super-user password, </strong>this is the only alternative left if open registration support has been dropped.</em></p>
<h2>Password change</h2>
<p>This module provides support for a user to change his current password. The following table describes the data exchange between client code and this module, during the password change process.</p>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
<col width="128*" />
<col width="82*" />
<col width="46*" />
<tr valign="top">
<td rowspan="2"><p>IN</p></td>
<td colspan="2"><p>OUT</p></td>
</tr>
<tr valign="top">
<td><p>Success</p></td>
<td><p>Failure</p></td>
</tr>
<tr valign="top">
<td><p>Username and current Password and new Password*</p></td>
<td><p>Unique session id***</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>Username and MD5 hash of current password and MD5 hash of new password**</p></td>
<td><p>Unique session id***</p></td>
<td><p>Error number</p></td>
</tr>
</table>
<p>* only available if <em>password recovery </em>support <em class="underline">hasn't been </em>dropped.</p>
<p>** only available if <em>password recovery support </em><em class="underline">has been</em> dropped.</p>
<p>*** the returned <em>unique session id </em>can be used for authentication (see <em>authenticate</em>).</p>
<h2>Password recovery OR reset</h2>
<p>This module provides support for password recovery OR reset. Since the password recovery behaviour involves storing the user password as plain text in the database, it is strongly discouraged. On the other hand, <em>not</em> storing the user password as plain text in the database effectively implies <em>password reset </em>as the unique alternative to a forgotten password. The master has to choose either to use the <em>password recovery</em> behaviour (default, slightly insecure for users but perhaps more convenient) or to entirely drop it in favour of the <em>password reset </em> behaviour (more secure but perhaps less convenient). Due to security as well as technical constraints, once the <em>password recovery</em> support has been dropped, it cannot be restored. The module is left with the <em>password reset </em> behaviour for the time being.</p>
<p>The following table describes the data exchange between client code and this module, during the password <em>recovery</em> OR <em>reset</em> processes.</p>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
<col width="48*" />
<col width="55*" />
<col width="89*" />
<col width="64*" />
<tr valign="top">
<td colspan="2"><p>IN</p></td>
<td colspan="2"><p>OUT</p></td>
</tr>
<tr valign="top">
<td rowspan="3"><p>Security question OFF</p></td>
<td rowspan="3"><p>User Email</p></td>
<td><p>Success</p></td>
<td><p>Failure</p></td>
</tr>
<tr valign="top">
<td><p>Password*</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>Generated** Password</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td rowspan="3"><p>Security question ON</p></td>
<td><p>User Email</p></td>
<td><p>Security Question</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>User Email and Security Answer*</p></td>
<td><p>Password*</p></td>
<td><p>Error number</p></td>
</tr>
<tr valign="top">
<td><p>User Email and MD5 hash of security answer**</p></td>
<td><p>Username and generated password**</p></td>
<td><p>Error number</p></td>
</tr>
</table>
<p>* only available if <em>password recovery </em>support <em class="underline">hasn't been </em>dropped.</p>
<p>** only available if <em>password recovery support </em><em class="underline">has been</em> dropped.</p>
<p>The client code is responsible for sending the results of the <em>recover</em> or <em>reset</em> operations to the user, via e-mail.</p>
<h2>Setup</h2>
<p>A list of configurable parameters for the module follows.</p>
<table width="100%" border="1" cellpadding="4" cellspacing="0">
<col width="87*" />
<col width="83*" />
<col width="85*" />
<thead>
<tr valign="top">
<td><p>PARAMETER NAME</p></td>
<td><p>POSSIBLE VALUES</p></td>
<td><p>COMMENTS</p></td>
</tr>
</thead>
<tbody>
<tr valign="top">
<td><p>sessionLifetime</p></td>
<td><p>-300 to 86`400 (seconds) or -1</p></td>
<td><p>If user makes no new request within this time frame, current session will automatically be closed. â-1â stands for infinite lifetime.</p></td>
</tr>
<tr valign="top">
<td><p>confirmationUidLifetime</p></td>
<td><p>86400 to 2678400 (seconds)</p></td>
<td><p>If open registration support hasn't been dropped, this governs the time frame the generated unique confirmation id must be returned within, in order for self-registration to be validated. Defaults to one day (or 86400 seconds)</p></td>
</tr>
<tr valign="top">
<td><p>blacklistTimeout</p></td>
<td><p>60 to 3600 (seconds) or -1</p></td>
<td rowspan="3"><p>Clock will start ticking from first failed login attempt an IP has made. If the IP consecutively provides <em>maxAttempts </em>th times bad credentials, and it does it during the <em>blacklistTimeout</em> period, that IP will be locked out for <em>banTime</em>, unless the master unlocks it in.</p>
<p><br />
</p>
<p>â-1â for the <em>blacklistTimeout </em>parameter will disable the timeout period. Bad logins ever made by a certain IP will cumulate, until a successful login resets them.</p>
<p><br />
</p>
<p>â-1â for the <em>maxAttempts</em> parameter entirely disables the feature.</p>
<p><br />
</p>
<p>â-1â for the <em>banTime</em> parameter will disable the block period, thus locking out an IP forever, unless a master unlocks it in.</p></td>
</tr>
<tr valign="top">
<td><p>maxAttempts</p></td>
<td><p>3 to 600 or -1</p></td>
</tr>
<tr valign="top">
<td><p>banTime</p></td>
<td><p>1800 to 86 400 (seconds) or -1</p></td>
</tr>
<tr valign="top">
<td><p>removeSecurityQuestionSupport</p></td>
<td><p>The "I am aware this is irreversible" phrase, in THIS case.</p></td>
<td><p>Setting this parameter will irrevocably bring into effect its associated behavior: users will no longer be required to provide a security question-and-answer pair in the process of open registration or forgotten password; existing security questions and their answers will be permanently deleted.</p>
<p><br />
</p>
<p>If open registration support was dropped, this parameter is ignored.</p></td>
</tr>
<tr valign="top">
<td><p>removePasswordRecoveryMode</p></td>
<td><p>The "I am aware this is irreversible" phrase, in THIS case.</p></td>
<td><p>Setting this parameter will irrevocably bring into effect its associated behaviour: plain passwords stored in the database will be encrypted; users will no longer be able to recover their passwords; instead, their forgotten passwords will be reset to some randomly generated string they will be invited to change.</p></td>
</tr>
<tr valign="top">
<td><p>removeOpenRegistrationSupport</p></td>
<td><p>The "I am aware this is irreversible" phrase, in THIS case.</p></td>
<td><p>Setting this parameter will irrevocably bring into effect its associated behaviour: users will no longer be able to register themselves into the system, instead, a master will have to manually add each user.</p></td>
</tr>
<tr valign="top">
<td><p>defaultRole</p></td>
<td><p>â[some string]â</p></td>
<td><p>If open registration support is available, this will set the role of new users registering themselves into the system. For security reasons, this string cannot be âadministratorâ, nor âmasterâ. Defaults to "user".</p></td>
</tr>
</tbody>
</table>
<h2>API</h2>
<pre>/**
* @see "Authenticate" section
*/
<strong>authenticate (credentials, userName=null, userRole=null);</strong>
/**
* Erases the provided unique session id from the database.
*/
<strong>unAuthenticate (uniqueSessionId);</strong>
/**
* @see "(Self-)register section.
* Credentials is a name-indexed array, supporting the following keys:
* PASSWORD, SECURITY_QUESTION, SECURITY_ANSWER, SUPER_USER_PASSWORD,
* CONFIRMATION_UID in this casing. PASSWORD and MASTER_PASSWORD will
* also accept a MD5 HASH of a given password.
* User role is optional and defaults to the value setup in the XML conf.
* file. User role cannot be given as "master", although it is assumed to
* be "master" for exactly one self registration, when master is not set
* yet.
*/
<strong>register (credentials, userName=null, userEmail=null userRole=null);</strong>
/**
* @see "Password Change" section.
* As with the above, currentPassword and newPassword also accept MD5
* hashes.
*/
<strong>changePassword (userName, currentPassword, newPassword);</strong>
/**
* @see "Password recovery OR reset" section. As with the above, security
* answer also accepts a corresponding MD5 hash.
*/
<strong>retrievePassword (userEmail, securityAnswer=null);</strong>
/**
* @see "Auto-block timeout" and friends in the "Setup" table.
*/
<strong>unblockIp (ip, masterPassword);</strong>
</pre>
<h2>Return codes</h2>
<ul>
<li>
<p>0. No Error (the function did what was supposed to)</p>
</li>
<li>
<p>1. Unique session ID has expired.</p>
</li>
<li>
<p>2. This unique session ID does not exist.</p>
</li>
<li>
<p>3. IP has changed during a session, which probably is the sign of an MIT attack.</p>
</li>
<li>
<p>4. Unknown user/password combination, meaning that either password is wrong, either no such user exists.</p>
</li>
<li>
<p>5. User has attempted to login under a different role.</p>
</li>
<li>
<p>6. This IP has been banned due to too many failed attempts (in a period of time);</p>
</li>
<li>
<p>7. A master has not been set yet, therefore no operation can be performed except auto-registering ONE master user.</p>
</li>
<li>
<p>8. Cannot redefine master; a master user has been registered, thus another "master" user cannot be registered anymore.</p>
</li>
<li>
<p>9. Someone tried to register a user name that doesn't contain only base Latin letters and numbers or the underscore char, or the provided name is shorter than four chars or it is longer than 20 chars, or it is empty (the empty string, "").</p>
</li>
<li>
<p>10. Someone tried to register an e-mail that doesn't follow the e-mail address pattern/format (<em>hide@address.com</em>). <em>hide@address.com</em> <strong>is </strong>tolerated, for testing considerations.</p>
</li>
<li>
<p>11. Someone tried to register an empty password, or one with more than 20 chars in it, or less than 4.</p>
</li>
<li>
<p>12. Someone tried to register an empty security question, or one with more than 100 chars in length.</p>
</li>
<li>
<p>13. Someone tried to register an empty security answer or one with more than 100 chars in length.</p>
</li>
<li>
<p>14. Open registration support has been dropped, therefore you must ask an administrator to register yourself instead.</p>
</li>
<li>
<p>15. Somebody tried to register a user, but that somebody could not proof himself to be a master or administrator by supplying a valid password.</p>
</li>
<li>
<p>16. The confirmation unique id sent (back) to the register (user) function cannot be found in the database, it is either fake, or was already used.</p>
</li>
<li>
<p>17. The confirmation unique id sent (back) to the register (user) function would have been valid, but has expired. User must attempt to register again.</p>
</li>
<li>
<p>18. An user that is not currently authenticated has attempted to perform an operation that requires prior authentication.</p>
</li>
<li>
<p>19. An user that has self-registered attempted to perform an operation, but that requires that he confirms his registration first.</p>
</li>
<li>
<p>20. An user attempted to change his password, but the old password provided doesn't match.</p>
</li>
<li>
<p>21. An user attempted to change his password, but the new password provided isn't acceptable.</p>
</li>
<li>
<p>22. Cannot return lost password since provided e-mail has never been registered.</p>
</li>
<li>
<p>23. Someone sent both an e-mail and security answer in order to retrieve his password, but security question support has been dropped.</p>
</li>
<li>
<p>24. Someone sent both an e-mail and security answer in order to retrieve his password, but the two could not be matched one against the other.</p>
</li>
<li>
<p>25. Someone attempted to register an administrator, but that someone could not proof himself to be the master, by supplying a valid (master) password.</p>
</li>
</ul>
<h2>Known Limitations, Gotchas</h2>
<ul>
<li>
<p>due to the transactional nature of some of the <em>drop...Support/Mode</em> operations, the database user that provides module access to the database must also have the LOCK privilege on the module's tables.</p>
</li>
</ul>
</body>
</html>