Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome Autofill/Autocomplete no value for password

When you have saved username and password for some site Chrome will autofill that username and password, but if you try to get the value for the password input field it is empty String even though there is value there ******.

If you click somewhere on the page no mater where the value of the input type="password" will be filled.

This is Fiddle user/pass of the structure of the html and the console.log command. It cannot be seen here but it can be reproduced on every page that has login form and the username and password are autofilled on the load of the page. If you inspect the value of the field before clicking anywhere else on the site it will be empty String.

This is not the case in Firefox or Internet Explorer it will fill the value of the input element with the password.

I am using Windows 7 Ultimate 64-bit OS and Google Chrome version is 48.0.2564.97 m

Is this normal behavior, bug or?

UPDATE:

If you click on F5 to reload the page and inspect the password field the value for password will be there. If you click the reload button in Chrome in top left corner the value for the password field will be empty string.

like image 262
onetwo12 Avatar asked Jan 27 '16 22:01

onetwo12


People also ask

Why is my password Autofill not working on Chrome?

On the top right corner click on the Menu icon. Then, click on Settings. From the list on the left side of the screen, click on Autofill. Click on Passwords and turn on the toggle for Offer to save passwords.

Why is my password Autofill not working?

Clear Browsing DataAn outdated browser cache can prevent the Autofill functionality in Chrome from kicking in, so try clearing it. Go to Chrome Settings > Privacy and Security > Clear Browsing Data.


3 Answers

This seems to be a bug in Chrome. When Chrome auto-fills a password on an initial page load (but not a refresh), the value appears in the form field on-screen, but querying passwordField.value in Javascript returns an empty string. If you depend on seeing that value in Javascript, this prevents you from doing so. Once the user does any other action on the page, such as clicking anywhere on the page, the value suddenly becomes visible to Javascript.

I'm not actually 100% sure if this is a bug, or if there is a security reason for doing this such as preventing a hidden frame from stealing your password by tricking the browser into filling it in.

A workaround that we have used is to detect the background color change that Chrome makes to fields that it has auto-filled. Chrome colors the background of auto-filled fields yellow, and this change is always visible to Javascript even when the value is not. Detecting this in Javascript lets us know that the field was auto-filled with a value, even though we see the value as blank in Javascript. In our case, we have a login form where the submit button is not enabled until you fill in something in the password field, and detecting either a value or the auto-fill background-color is good enough to determine that something is in the field. We can then enable the submit button, and clicking the button (or pressing enter) instantly makes the password field value visible to Javascript because interacting with the page fixes the problem, so we can proceed normally from there.

like image 181
Adam Hamilton Avatar answered Oct 07 '22 09:10

Adam Hamilton


Working Answer as of July 8, 2016

Adam correctly stated this is a bug (or intended behavior). However, none of the previous answers actually say how to fix this, so here is a method to force Chrome to treat the autocompleted value as a real value.

Several things need to happen in order, and this needs to only run in Chrome and not Firefox, hence the if.

First we focus on the element. We then create a new TextEvent, and run initTextEvent, which adds in a custom string that we specify (I used "@@@@@") to the beginning of the value. This triggers Chrome to actually start acting like the value is real. We can then remove the custom string that we added, and then we unfocus.


Code:

input.focus();

var event = document.createEvent('TextEvent');

if ( event.initTextEvent ) {

    event.initTextEvent('textInput', true, true, window, '@@@@@');

    input.dispatchEvent(event);

    input.value = input.value.replace('@@@@@','');

}

input.blur();

Edit August 10, 2016

This only works right now in Chrome on Windows and Android. Doesn't work on OSX. Additionally, it will stop working at all in Sept 2016, according to:

https://www.chromestatus.com/features/5718803933560832

Also, I've opened a Chromium ticket.

https://bugs.chromium.org/p/chromium/issues/detail?id=636425

As of August 12, a member of the Chrome team said on the above ticket that the behavior won't be changing because they don't consider it a bug.

Long-term Work-Around Suggestion:

That said, the current behavior has been tweaked from when it was first implemented. The user no longer has to interact with the password input for the value to be reported. The user now just needs to interact (send a mouse or keyboard event) with any part of the page. That means that while running validation on pageload still won't work, clicking on a submit button WILL cause Chrome to correctly report the password value. The work-around then, is to revalidate all inputs that might be autocompleted, if that is what you are trying to do, on submit.


Edit December 13, 2016:

A new Chromium ticket has been opened and is being received better. If interested in changing this behavior of Chrome's, please star this new ticket:

https://bugs.chromium.org/p/chromium/issues/detail?id=669724

like image 38
Andy Mercer Avatar answered Oct 07 '22 09:10

Andy Mercer


Continuing from what Kelderic said, here's my work around. Like a lot of people, I don't need the actual password value. I really just need to know that the password box has been autofilled, so that I can display the proper validation messages.

Personally, I would not use suggested solution to detect the background color change cause by Chrome's autofill. That approach seems brittle. It depends on that yellow color never changing. But that could be changed by an extension and be different in another Blink based browser (ie. Opera). Plus, there's no promise Google wont use a different color in the future. My method works regardless of style.

First, in CSS I set the content of the INPUT when the -webkit-autofil pseudo-class is applied to it:

input:-webkit-autofill {
  content: "\feff"
}

Then, I created a routine to check for the content to be set:

const autofillContent = `"${String.fromCharCode(0xFEFF)}"`;
function checkAutofill(input) {
    if (!input.value) {
        const style = window.getComputedStyle(input);
        if (style.content !== autofillContent)
            return false;
    }

    //the autofill was detected
    input.classList.add('valid'); //replace this. do want you want to the input
    return true;
}

Lastly, I polled the input to allow the autofill time to complete:

const input = document.querySelector("input[type=password]");

if (!checkAutofill(input)) {
    let interval = 0;
    const intervalId = setInterval(() => {
        if (checkAutofill(input) || interval++ >= 20)
            clearInterval(intervalId);
    }, 100);
}
like image 38
Ben Avatar answered Oct 07 '22 08:10

Ben