This question is specifically about a problem that I am having with our site's attempt to compensate for Chrome's insistence on performing autofill when it should not.
Please note: this question is not specifically about the autofill issue, which is well-documented over the course of several years. For example, here are some useful pages that cover that issue:
Disabling Chrome Autofill
https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
Chrome autofills username into random text input
https://bugs.chromium.org/p/chromium/issues/detail?id=914451#c53
https://github.com/alphagov/accessible-autocomplete/issues/325
Over the years we have used several solutions similar to the ones documented in the above articles, especially the first article.
As developers have developed workarounds, the Chrome team works to disable the workarounds. At present I don't know of any workaround that is effective any more. The Chromium team apparently believes that any form with a password field is a login form, and it does not want to easily allow the ability to edit passwords, while retaining the automatic obfuscation feature.
In any case, I re-iterate that I am not specifically focusing on the autofill problem, but rather some issues I am having countering it.
We have successfully countered the issue on some of our edit pages, but don't have a complete solution, due to the following issue, which is the heart of this question.
The issue is that because the fields in question are email adddress (username) and password, there is other javascript on the page, which is fairly complex. The purpose of that javascript is to help the user with such functions as the following:
Make sure that the entry meets certain basic validations.
Make sure that an email address is not already used in our database.
Make sure that the entry does not violate certain other policies, such as using first name, last name, etc. as a password.
Quite a ways back one of our measures that was in part to counter browser autofill was to make the email address and password fields hidden, and only displayed after the user clicks a button with a label like "Change Email Address". This had some beneficial user impact that I will not detail, but also stopped Chrome from autofilling.
Recently however, Chrome has started autofilling even the hidden fields. So when the button was clicked and the fields revealed, there was data populated into the email address. However, the data populated was the userid rather than an email address, because we allow logging using either userid or email address, and with certain Chrome settings, the userid was saved.
The next step in dealing with this "feature" was to add a line of jquery to clear the contents of that field when the button is clicked, and if the button is not clicked, to have the update routine ignore the bogus autofill.
The actual problem that is happening is that somehow, it appears that Chrome is inserting the value back into the DOM. Other works seems to show that Chrome will perversely and continually attempt to perform the autofill every time the DOM changes.
So here is the sequence of apparent events that I have not yet solved:
User visits his profile page.
Chrome autofills the hidden username.
User clicks "Change Email Address"
jquery uses val('') to clear the contents of the field.
There is an onblur validation on the email address field that should not be triggered yet, because the field is not blurred. In fact, the cursor is not yet even placed into the field--the user has to do that. The reason we know the validation occurs is because immediately we get an error message about the invalid email address because it is a userid format rather than an email address format.
There are two "impossible" things going on here.
A validation is occurring that seems there is no way it could be triggered.
We have cleared the field using jquery. But the the validation (which should not be happening) is still seeing the original autofilled and invalid content.
A theory that might explain this is that when the field is displayed, the focus quickly goes into that field before the javascript has had time to actually clear the DOM, and that the focus leaves the field before the eye can see that it went into the field, thus triggering the validation, again before the jquery has had its effect.
So the theory might be that the sequence of events is gain focus, lose focus, trigger the onblur validation, clear the field. This would produce the observed effect.
So the question specifics are the following:
What is causing the focus to be gained and lost?
Why is this happening before the clearing of the field, which happens when the fields are made visible?
Yet a further theory might be "javascript handles events not in the order that it appears, but rather some other predetermined order". I have seen some information about that, but I don't know how to control this to solve the problem.
Here are some code snippets. You will note that a number of the previously-working autofill blocking tactics are still in place:
onblur=ValidFirstField()
<input type="password" autocomplete="new-password" name="password1" id="password1" size="20" maxlength="$MAX_PASSWORD_LEN" onkeydown="clearMessage('pw_message'); displayMessage('pw_strength');" onkeyup="chkPass(this.value);" onblur="ValidFirstField(this, 'Password', $MIN_PASSWORD_LEN, $MAX_PASSWORD_LEN, ValidPasswordSafety, ['$companyname', '$fname', '$lname', '$email1', '$email2'], 'pw_message', ' not allowed; please choose another.', 1, 'password2' );" >
validation Please note: the line of code with fieldname + ' must be between ' is the validation that is triggered out of sequence:
function ValidFirstField(field1, fieldname, minlen, maxlen, cfunc, aProhibited, msg_field, bad_msg, common_msg, mark_field)
{
if (!field1.value.length)
{
return;
}
var login_prompt = document.getElementById('login-prompt');
if (login_prompt)
{
login_prompt.style.display = STYLE_NONE; /* clear in case set via ajax */
}
var msg = document.getElementById(msg_field);
msg.innerHTML = '';
var allowSubmit = true;
if (field1.value.length < minlen || field1.value.length > maxlen)
{
msg.innerHTML = fieldname + ' must be between ' + minlen + ' and ' + maxlen + ' characters: ' + field1.value.length;
allowSubmit = false;
field1.focus(); // TODO temporarily suppress to prevent focus/onblur race in IE
}
...
jquery that displays the fields and clears the content
$('#show-email').click(function()
{
chg_email_clicked = true;
$('#chg-email-clicked').val(1);
// alert('chg=' + chg_email_clicked);
$(this).hide();
// from https://stackoverflow.com/questions/15738259/disabling-chrome-autofill mike nelson
var $chrome_fake = $('.chrome-fake');
$chrome_fake.show();
window.setTimeout(function ()
{
$chrome_fake.hide();
},1);
$('#email1').val('');
// var testemail1 = document.getElementById('email1').value;
// alert(testemail1);
$('.hide-email').show();
});
Related
So I want to have an input of type number <input type="number"> and I want to RESTRICT users from ENTERING DECIMAL VALUE
Note: I'm hiding the spin buttons of the input type text. Know more here
EDIT: ANYTHING WILL WORK! EVEN JAVASCRIPT!
I searched a lot but found nothing.
I did find this answer but it basically blocks the use of any other key on the keypad except the number keys, so the basic problems occur such as the user cannot use backspace and cut the number entered, another problem is the user cannot use tab to change focus onto the next input.
Thank You!
Preventing user input can be done with JavaScript. I'd use the input event for catching values, as it's a unified interface, encompassing any input method you can think of keyup, paste, pointer events, touch events, etc...
document.querySelector('input').addEventListener('input', e => {
e.target.value = Math.round(e.target.value.replace(/\D/g,''))
});
<input>
But you really should not do it! For at least the following reasons:
Forbidding user input is, by and large, perceived as disrespectful and drives users away. In short, it reduces any user engagement metric you can think of (funneling, sales, visits, sharing, etc...). Don't take my word for it. Do some A/B testing: present the same form with and without blocking user input and look at the results.
Form elements are just tools to help users give you data. But they are completely by-pass-able. If you give me a form I can send whatever I want using it, by simply opening the browser console. The validation must be done on server side. If you're using the value to do something on client side, sanitize the input value in the method, without changing user input.
A respectful way to inform users decimal values are not valid is by making the input :invalid, using the pattern attribute ( e.g: pattern="[0-9]"), styling accordingly (e.g: :invalid { border-color: red }), and displaying an appropriate message.
Don't delete or block user input. They'll do it themselves if you tell them why the value is invalid.
When following web standards, your solution lasts. When you come up with hacks, there will always be the odd device in which your hack doesn't work. You don't know where things will be in 1-2 years from now, nevermind 5 or 10.
Last, but not least, have a closer look at Constraint Validation. You'll need to know and use it when creating quality UX and accessible forms.
This is one option for creating an input element using javascript to limit the values that can be entered. I create an array of allowed keys, including all the digits, backspace, and tab as you specified. I added an event listener for the keydown event, and if the key pressed is not in the allowed group, I prevent the default action, or prevent the value from being entered.
I also added an event listener to the paste event, as you could right click paste and enter information that does not meet the criteria. Instead of trying to validate pasted values I disable pasting all together.
If you have any questions, please ask.
const allowedKeys = [..."0123456789", "Backspace", "Tab"];
const myInput = document.querySelector("input");
myInput.addEventListener("keydown", e => {
const key = e.key;
const allowed = allowedKeys.includes(key);
if (!allowed) e.preventDefault();
});
myInput.addEventListener("paste", e => e.preventDefault());
<input type="number">
I'm trying to create an autologin script for https://sso.verisk.com/login/default
I'm able to load the page and populate the Username and Password fields, but after clicking the Sign In button it will say "Please enter a username" and "Please enter a password". If I simply delete a character from the populated field, it will pass the validation.
To narrow it down, I've visited the page at https://sso.verisk.com/login/default and used the console to enter:
document.getElementById("okta-signin-username").value = "username"
document.getElementById("okta-signin-password").value = "password"
document.getElementById("okta-signin-submit").click()
As mentioned, this populates the Username and Password, but the validation doesn't detect field values until a character is either deleted or added manually. I've tested forms on other web sites with success so I'm not sure why this one is failing. Would greatly appreciate any points in the right direction!!
I believe the proper question could be "how can I submit a form programmatically"
The solution is this
Forms work like this, don't always think like a human when you deal with systems. The query selector is simply "form" because form is the only one form element in the entire document.
So I have a problem with newer browsers saving passwords. Say I have a password box like so:
<input type="password" autocomplete="off" />
New browsers like IE11 and Safari in iOS 7.1 have started ignoring the autocomplete="off" in password boxes specifically and offer the user to save the password. In my company (a bank), we view this as a security concern.
I was wondering if anybody has solved this problem yet. Maybe somebody has written a javascript plugin that masks a normal input[type=text] so that the autocomplete="off" attribute will be respected.
Update:
For a little more information, here is the documentation for autocomplete on msdn: http://msdn.microsoft.com/en-us/library/ie/ms533486%28v=vs.85%29.aspx
You can make a fake password input with type text using a custom font:
#font-face {
font-family: 'password';
font-style: normal;
font-weight: 400;
src: url(https://jsbin-user-assets.s3.amazonaws.com/rafaelcastrocouto/password.ttf);
}
input.key {
font-family: 'password';
width: 100px; height: 16px;
}
<p>Password: <input class="key" type="text" autocomplete="off" /></p>
JSBin Demo
Notice that this only raises more security concerns.
Here's an idea, but I'm suggesting it for cases where browsers get the autofill wrong for passwords that aren't used for logins. There probably needs to be a better standard for identifying login screens so browsers don't have to use heuristics looking for fields with type="password".
Load the form with the password field with type="text", so browsers' autocompletion algorithms will ignore it. When the user inputs something in that field, switch its type="password".
I'm not much of a JavaScript programmer, but I hacked a JSFiddle to show how it theoretically works.
Perhaps onfocus would be a better way to go, too, but I didn't try it.
The solution that worked for me was like this :
First input type should be text
At the focus event turn input type to password
Listen for user inputs and if input field value is empty set type to text again
This way at the start and when input field is empty browser will not show suggestions.
Firstly, autocomplete = "off" should be on the <form> element, not the individual fields. This is because browsers typically store the values for all fields in a given form together (eg to allow for saving multiple username/password combinations for the same site).
Set it in the form, and it should work just fine for you. (although passwords already saved will typically still be auto-completed, so clear your password store before testing)
However, I would suggest that you're probably chasing the wrong target if this is considered a security concern.
The reason browsers offer this feature is because users want to be able to store their login credentials. Preventing them from doing so won't stop them wanting to, and if users really want to, there are still a number of ways they can get around it -- there are browser plug-ins explicitly designed to kill thew autocomplete = "off" feature and allow all passwords to be saved.
How your user stores the password at their end is ultimately not your security concern, and not something you really have any control over anyway.
In fact, if we prevent people from storing their passwords, it is more likely that they will use the same password in multiple places (simply because people don't have the capacity to remember different passwords for every site they use), so by preventing them from saving it, you might actually be making your users' passwords less secure.
If your site has a genuine need for security that cannot allow a password to be saved, then you will need to consider an alternative mechanism entirely. For example, bank logins these days often require users to enter specific numbered characters from their password -- eg "Please enter the fifth, eighth and twelfth characters from your password".
However, these schemes are more aimed at securing the transmission of the password rather than the storing of it: by only entering certain given characters, we don't have to input or transmit the entire password at all, so there is no chance of it being hacked en-route. It is still assumed that the user will probably have the password noted down somewhere (especially if they have to work out which is the twelfth character in the string)
This kind of scheme can be a real pain for users, but does offer a genuine level of login security without having to actually input or transmit the password. The additional level of difficulty it adds to the login process, however, means that only really high-security sites like banks are likely to use this kind of scheme over a regular password.
I struggled with this for quite some time, but here is a solution that solved the issue for me.
Initially, create the password input as a 'text' input:
<input type="text" name="mfa_psw" id="mfa_psw" autocomplete="off">
Then use Javascript to listen for keystroke events. If the password input is not null, convert the type to 'password'.
<script type="text/javascript">
var pswInput = document.getElementById("mfa_psw");
pswInput.onkeyup = function(e){
if(e.keyCode == 13){
mfa(); // enter key pressed, call next function (i.e. log in)
return false;
} else {
if (pswInput.value==null) {
pswInput.type = 'text';
// input is empty, covert to 'text' to prevent password autofil
} else {
pswInput.type = 'password';
// input is not empty, convert to 'password' to hide text entry
}
}
}
Note: this solution does mean that the first character of the user's password is exposed for a moment before the input type is changed to 'password'. However, assuming the user's password is longer than 1 character, this really shouldn't be an issue!
Have you tried changing the name attribute to something ridiculous? I believe the autocomplete functionality is based off the name attribute. I'm not 100% sure but in the limited testing I did changing the name attribute was changing what type of autocomplete data was being presented.
Obvious example just to be clear: name="username" was showing my username while name="email" was showing my previously entered email addresses. When I switched to name="browsersAreStupidForImplementingThisFeature" I didn't get any autocomplete data.
Needs further testing but might be a good place to start? Good luck
We had a use case where admins could view other user records and make changes. One of the fields was that other user's password. In this instance, letting the password manager pre-fill the field was a "bad thing". So what we ended up doing was waiting a short period of time after the page had loaded and then cleared out the password field...
// After the page has loaded...
window.addEventListener('load', setTimeout(function() {
// Wait a bit and then clear out the contents of the field
document.getElementById('other-password').value='';
}), 100);
Use Javascript to listen for keystroke events. If the password input is not null, convert the type to 'password'.
<input type="text" name="keybrd" id="keybrd" autocomplete="off">
<script type="text/javascript">
var keybrd = document.getElementById('keybrd');
keybrd.onkeyup = function(){
if (keybrd.value==null) {
keybrd.type = 'text';
} else {
keybrd.type = 'password';
}
}
Note: It's easiest way to mask the password input for all browser type.
I've added PO Box filtering per this short tutorial:
http://inchoo.net/ecommerce/magento/prevent-po-boxes-in-shipping-address-field-on-checkout/comment-page-1/#comment-35117
Essentially, this simply calls my controller, does a preg_match on the 'street1' and street2' fields, and gives an alert if a PO Box address is entered, else it just calls shipping.save() and goes to the next step.
The problem is that if a user has a PO Box address saved (and this is not the default address), when you select the alternate address (with the PO Box), the hidden form fields aren't updated with the selected address, and the PO Box validation does not get called.
In an attempt to remedy this, I am firing shipping.setAddress(value) when the select element is changed:
jQuery("#shipping-address-select").change(function(){
var value = jQuery("#shipping-address-select option:selected").val();
shipping.setAddress(value);
});
This works almost entirely as expected, it sets the address to what I expect, and everything is nice and wonderful; however, a small glitch that occurs here is that after calling shipping.setAddress(value) (which performs an ajax call), the select element automatically will display the 'New Address' option after I've chosen an actual address. This is purely a visual glitch, as the correct address is used, but having it show 'New Address' will be confusing to users.
Is there a way to remedy this without resorting to modifying anything in opcheckout.js (where the Shipping class and setAddress() bits reside)?
-- edit --
This is Magento Professional - 1.11.1.0
While certainly not an optimal solution, in the meantime I have had to resort to updating the hidden form fields manually using:
jQuery("#shipping-address-select").on('change',function(){
var address = jQuery("#shipping-address-select option:selected").html().split(', ');
jQuery("#shipping\\:street1").val(address[1]);
jQuery("#shipping\\:street2").val(address[2]);
});
I am so proud of this code. /sarcasm.
We tend to position the cursor on the first element of all newly created objects (e.g. name field for user or the email id field on the login page). Does it make sense to auto-focus on the name field for user on User.update, since the user could modify any other field of the User and doing on auto-focus while doing User.update actually marks the entire name field instead of positioning the cursor on the name element. What should be the right behavior?
The purpose of auto-focus behavior on a web page is to save users from moving off the keyboard to make a mouse action for the most common task on that page.
So you need to ask the question: "What is the most common task performed on this page?"
Then ask, "What is the first UI element (field) a user needs to access or edit to accomplish the most common task(s) on this screen?"
Your answer should determine where your auto-focus goes. But be careful - users expect the auto-focus to go on the first field on the page. So only place it elsewhere if you are sure that this is desirable to the users. And also in that case, consider moving that field to the top of the page.
In your case, the "name" element gets entirely marked (selected) because that is how auto-focus works for fields that already contain data. This is the most desirable behavior because it allows the user to replace the contents of the field without doing further work with the cursor and delete keys, and if they only want to edit, they can simply use the Home/End and arrow keys to quickly move the cursor where they need it.
===== Edit / Addendum =====
I forgot to add this in the original answer, but it's such a huge pet peeve of mine that I have to mention it here.
Please, if you do an auto-focus, make sure it doesn't fire if the user is already typing! There is NOTHING more annoying than having your cursor moved automatically while you're in the middle of logging in.
This used to happen on Yahoo! Mail's login screen all the time. If the page was loading slowly, the login form would render a few seconds before the DOM was ready and the auto-focus only fired when it was ready. So I'd click manually to focus in the login field, and I'd already be halfway through my password when auto-focus would silently move my cursor back to the login field and I'd look up at the screen to find half my password in plain text up in the login field, smashed up against my username.
The fix is so simple; just check if the login field is still blank before focusing there. Otherwise don't because you then know the user already typed something and the convenience of auto-focus would turn into a frustration. Here's example code, assuming your field is given an id="username":
function focusIfBlank(){
username = document.getElementById('username');
if(username.value == "") {
username.focus();
}
}
Also consider calling focusIfBlank() inline instead of when the DOM is ready, because you'll increase the chances of it being useful to the user since it will focus almost instantly after it's rendered.
I am not sure whether its your answer,
<body>
Name: <input type="text" autofocus /> <br />
Email: <input type="text" />
</body>
Refer this,and this for more options..