Koha/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt
Jonathan Druart cfc484b173 Bug 18314: Account lockout
To prevent brute force attacks on Koha accounts, staff and opac, we need to
implement an account lockout process to Koha.

After a number of failed login attempts a users account would become locked.
The user would then need to use the reset password functionality to send a reset
token to their email account. After a successful password reset the lockout flag
would be removed.

The number of failed login attempts before lockout is configurable using a new
system preference 'FailedLoginAttempts'.

How does it work?
When a patron enter an invalid password, the borrowers.login_attempts value
for this patron is incremented. When this value reach the value of the
pref FailedLoginAttempts, the password comparison is not done and the
authentication is rejected.
This login_attempts field is reset when a patron correctly logs in. When
the account is locked the patron has to reset his/her password using
the OpacResetPassword feature or ask a staff member to generate a new
password.
If the pref is not set (0, or '') the feature is considered as disabled,
but the failed login attempts are stored anyway.

Test plan:
0/ Apply patch and execute the update DB entry
1/ Switch on the feature by setting FailedLoginAttempts to 3
2/ Use an invalid password to login at the staff or OPAC interface
3/ After the third consecutive failures, you will be asked to reset your
password if OpacResetPassword is set, or contact a staff member
4/ Switch on OpacResetPassword and reset your password
5/ Confirm that you are able to login
6/ Play with the different combinations

QA details: The trick happens in C4::Auth::checkpw, to make things clear
I had to create a return value (note the awesome name: @return) and
replace the 3 successives if statements with elsif. Indeed if one of
the condition is reached, it will return inside the given block.

Signed-off-by: Jonathan Field <jonathan.field@ptfs-europe.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
2017-05-12 10:58:44 -04:00

121 lines
4.1 KiB
Text

[% USE Koha %]
[% USE Branches %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo;
[% IF ( nopermission ) %]Access denied[% END %]
[% IF ( timed_out ) %]Session timed out[% END %]
[% IF ( different_ip ) %]IP address change[% END %]
[% IF too_many_login_attempts %]This account has been locked.
[% ELSIF invalid_username_or_password %]Invalid username or password[% END %]
[% IF ( loginprompt ) %]Log in to Koha[% END %]
</title>
[% INCLUDE 'doc-head-close.inc' %]
</head>
<body id="main_auth" class="main">
<div id="doc" class="yui-t7">
<div id="bd">
<div id="login">
<h1><a href="http://koha-community.org">Koha</a></h1>
[% IF ( nopermission ) %]
<div id="login_error">
<strong>Error:</strong>
You do not have permission to access this page.
</div>
<p><strong>Log in as a different user</strong></p></h2>
[% END %]
[% IF ( timed_out ) %]
<div id="login_error"><strong>Error: </strong>Session timed out.<br /> Please log in again</div>
[% END %]
[% IF ( different_ip ) %]
<div id="login_error"><strong>Error: </strong>IP address has changed. Please log in again </div>
[% END %]
[% IF ( wrongip ) %]
<div id="login_error"><strong>Error: </strong>Autolocation is switched on and you are logging in with an IP address that doesn't match your library. </div>
[% END %]
[% IF too_many_login_attempts %]
<div id="login_error"><strong>Error: </strong>This account has been locked!</div>
[% ELSIF invalid_username_or_password %]
<div id="login_error"><strong>Error: </strong>Invalid username or password</div>
[% END %]
<!-- login prompt time-->
<form action="[% script_name %]" method="post" name="loginform" id="loginform">
<input type="hidden" name="koha_login_context" value="intranet" />
[% FOREACH INPUT IN INPUTS %]
<input type="hidden" name="[% INPUT.name |html %]" value="[% INPUT.value |html %]" />
[% END %]
<p><label for="userid">Username:</label>
<input type="text" name="userid" id="userid" class="input focus" value="[% userid %]" size="20" tabindex="1" />
</p>
<p><label for="password">Password:</label>
<input type="password" name="password" id="password" class="input" value="" size="20" tabindex="2" />
</p>
[% UNLESS IndependentBranches %]
<p>
<label for="branch">Library:</label>
<select name="branch" id="branch" class="input" tabindex="3">
<option value="">My library</option>
[% FOREACH l IN Branches.all( unfiltered => 1 ) %]
<option value="[% l.branchcode %]">[% l.branchname %]</option>
[% END %]
</select>
</p>
[% END %]
<!-- <p><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="3" />Remember me</label></p> -->
<p class="submit"><input id="submit" type="submit" value="Login" tabindex="4" /></p>
</form>
[% IF ( casAuthentication ) %]
<h4>Cas login</h4>
[% IF ( invalidCasLogin ) %]
<!-- This is what is displayed if cas login has failed -->
<p>Sorry, the CAS login failed.</p>
[% END %]
[% IF ( casServerUrl ) %]
<p><a href="[% casServerUrl %]">If you have a CAS account, please click here to login</a>.<p>
[% END %]
[% IF ( casServersLoop ) %]
<p>If you have a CAS account, please choose against which one you would like to authenticate:</p>
<ul>
[% FOREACH casServer IN casServersLoop %]
<li><a href="[% casServer.value %]">[% casServer.name %]</a></li>
[% END %]
[% END %]
[% END %]
[% IF ( nopermission ) %]
<p><a href="javascript:window.history.back()">[Previous page]</a>
<a href="/">[Main page]</a></p>
[% END %]
<!--<ul> -->
<!-- <li><a href="/cgi-bin/koha/lostpassword.pl" title="Password lost and found">Lost your password?</a></li> -->
<!-- </ul> -->
</div>
</div>
[% MACRO jsinclude BLOCK %]
<script type="text/javascript">
$(document).ready( function() {
if ( document.location.hash ) {
$( '#loginform' ).append( '<input name="auth_forwarded_hash" type="hidden" value="' + document.location.hash + '"/>' );
}
});
</script>
[% END %]
<!-- the main div is closed in intranet-bottom.inc -->
[% INCLUDE 'intranet-bottom.inc' %]