Buscar este blog

viernes, 26 de febrero de 2016

HTML Login Form - Disable autocomplete and password remember

Most users use the autocomplete a password remember options of their browsers. In this way, if you try to login in a site where you previously were logged, the browser autocompletes the login, and then suggests the password.
But recently, in one critical web app, we have a requirement to disable this behaviour. What seemed a simple task, resulted in a small head ache.

We start with this basic login page.
<body>
 <div th:if="${param.error}">
  Invalid username and password.
 </div>
 
 <div th:if="${param.logout}">
  You have been logged out.
 </div>
 
 <form th:action="@{/login}" method="post">
  <div><label> User Name : <input type="text" name="username"/> </label></div>
  <div><label> Password: <input type="password" name="password"/> </label></div>
  <div><input type="submit" value="Sign In"/></div>
 </form>
</body>

In this page, the browser will ask you if you want to remember the password. Any way, the next time you visit this page, the browser will autocomplete the login field.

Step 1, disable autocomplete

If you only need to disable autocomplete (but you can afford the browser ask for password remember) there is a HTML attribute which should work... autocomplete="off"
<body>
 <div th:if="${param.error}">
  Invalid username and password.
 </div>
 
 <div th:if="${param.logout}">
  You have been logged out.
 </div>
 
 <form th:action="@{/login}" method="post" autocomplete="off">
  <div><label> User Name : <input type="text" name="username"/> </label></div>
  <div><label> Password: <input type="password" name="password"/> </label></div>
  <div><input type="submit" value="Sign In"/></div>
 </form>
</body>

Step 2, disable password remember

If you want to force the browser to not ask for password remember, this is a bit more complex. After a lot of  test, the solution I found was to create a hidden form with hidden fields. The user fills a fake form, and when she presses the submit button, these fields and the submit event are transferred to the true login form.
<body>
 <script type="text/javascript">         
  var copyFields = function() {
   document.getElementById('username').value = document.getElementById('usernameFake').value;
   document.getElementById('password').value = document.getElementById('passwordFake').value; 
  }
  
  var submitRealForm = function() {
   copyFields();
   document.getElementById('realLoginForm').submit();
   return false;
  }
 </script>
 
 <div th:if="${param.error}">
  Invalid username and password.
 </div>
 
 <div th:if="${param.logout}">
  You have been logged out.
 </div>
 
  
 <form id="realLoginForm" th:action="@{/login}" method="post" autocomplete="off" style="display:none">
  <input id="username" type="hidden" name="username"/>
  <input id="password" type="hidden" name="password"/>       
 </form>
  
 
 <div class="simulateForm">
  <div><label> User Name : <input id="usernameFake" type="text" /> </label></div>
  <div><label> Password: <input id="passwordFake" type="password"/> </label></div>
  <div> <button type="button" onclick="submitRealForm()">Click Me!</button></div>
 </div>
</body>


Step 3, caputre enter in password

When the user are inside an HTML form and she presses enter key, the browser send a click event to the first button in this form.
With the solution I made, when user press enter, nothing happens. To solve this problem, with javascript you can listen this event and trigger the submit manually.
<body>
 <script type="text/javascript">         
  var copyFields = function() {
   document.getElementById('username').value = document.getElementById('usernameFake').value;
   document.getElementById('password').value = document.getElementById('passwordFake').value; 
  }
  
  var submitRealForm = function() {
   copyFields();
   document.getElementById('realLoginForm').submit();
   return false;
  }
  
  var submitFormOnEnter = function(event) {
   if (event.keyCode == 13) {
    submitRealForm();
   }
  }
 </script>
 
 <div th:if="${param.error}">
  Invalid username and password.
 </div>
 
 <div th:if="${param.logout}">
  You have been logged out.
 </div>
 
  
 <form id="realLoginForm" th:action="@{/login}" method="post" autocomplete="off" style="display:none">
  <input id="username" type="hidden" name="username"/>
  <input id="password" type="hidden" name="password"/>       
 </form>
  
 
 <div class="simulateForm">
  <div><label> User Name : <input id="usernameFake" type="text" onkeydown="submitFormOnEnter(event)"/> </label></div>
  <div><label> Password: <input id="passwordFake" type="password" onkeydown="submitFormOnEnter(event)"/> </label></div>
  <div> <button type="button" onclick="submitRealForm()">Click Me!</button></div>
 </div>
</body>

Note.
This example is based on the Spring Security getting started (https://spring.io/guides/gs/securing-web/). Their source code is in https://github.com/spring-guides/gs-securing-web, I just played with de login.html page.

No hay comentarios:

Publicar un comentario