Hey, I'm working on a web app that has a login dialog that works like this:
<form>
-- user/pass are submitted via AJAXHere's the problem: the browser never offers the usual "Save this password? Yes / Never / Not Now" prompt that it does for other sites.
I tried wrapping the <div>
in <form>
tags with "autocomplete='on'" but that made no difference.
Is it possible to get the browser to offer to store the password without a major rework of my login flow?
thanks Eric
p.s. to add to my question, I'm definitely working with browers that store passwords, and I've never clicked "never for this site" ...this is a technical issue with the browser not detecting that it's a login form, not operator error :-)
This work much better for me, because it's 100% ajaxed and the browser detects the login.
<form id="loginform" action="javascript:login(this);" >
<label for="username">Username</label>
<input name="username" type="text" value="" required="required" />
<label for="password">Password</label>
<input name="password" type="password" value="" required="required" />
<a href="#" onclick="document.getElementById("loginform").submit();" >Login</a>
</form>
The following code is tested on
JS-Fiddle:
http://jsfiddle.net/ocozggqu/
Post-code:
// modified post-code from https://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
function post(path, params, method)
{
method = method || "post"; // Set method to post by default if not specified.
// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.id = "dynamicform" + Math.random();
form.setAttribute("method", method);
form.setAttribute("action", path);
form.setAttribute("style", "display: none");
// Internet Explorer needs this
form.setAttribute("onsubmit", "window.external.AutoCompleteSaveForm(document.getElementById('" + form.id + "'))");
for (var key in params)
{
if (params.hasOwnProperty(key))
{
var hiddenField = document.createElement("input");
// Internet Explorer needs a "password"-field to show the store-password-dialog
hiddenField.setAttribute("type", key == "password" ? "password" : "text");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
var submitButton = document.createElement("input");
submitButton.setAttribute("type", "submit");
form.appendChild(submitButton);
document.body.appendChild(form);
//form.submit(); does not work on Internet Explorer
submitButton.click(); // "click" on submit-button needed for Internet Explorer
}
Remarks
window.external.AutoCompleteSaveForm
is needed Here is a sample ajax login-code:
function login(username, password, remember, redirectUrl)
{
// "account/login" sets a cookie if successful
return $.postJSON("account/login", {
username: username,
password: password,
remember: remember,
returnUrl: redirectUrl
})
.done(function ()
{
// login succeeded, issue a manual page-redirect to show the store-password-dialog
post(
redirectUrl,
{
username: username,
password: password,
remember: remember,
returnUrl: redirectUrl
},
"post");
})
.fail(function ()
{
// show error
});
};
Remarks
You may attach the dialog to the form, so all those inputs are in a form. The other thing is make the password text field right after the username text field.
None of the answers already make it clear you can use the HTML5 History API to prompt to save the password.
First, you need to make sure you have at least a <form>
element with a password and email or username field. Most browsers handle this automatically as long as you use the right input types (password, email or username). But to be sure, set the autocomplete values correctly for each input element.
You can find a list of the autocomplete values here: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
The ones you need are: username
, email
and current-password
Then you have two possibilities:
history.pushState({}, "Your new page title");
You can also change the page's URL, but that is not required to prompt to save the password:
history.pushState({}, "Your new page title", "new-url");
Documentation: https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
This has the additional benefit that you can prevent the browser to ask to save the password if the user entered the password incorrectly. Note that in some browsers the browser will always ask to save the credentials, even when you call .preventDefault and not use the history API.
If you don't want to navigate away and/or modify the browser history, you can use replaceState instead (this also works).
add a bit more information to @Michal Roharik 's answer.
if your ajax call will return a return url, you should use jquery to change the form action attribute to that url before calling form.submit
ex.
$(form).attr('action', ReturnPath);
form.submitted = false;
form.submit();
I have been struggling with this myself, and I finally was able to track down the issue and what was causing it to fail.
It all stemmed from the fact that my login form was being dynamically injected into the page (using backbone.js). As soon as I embed my login form directly into my index.html file, everything worked like a charm.
I think this is because the browser has to be aware that there is an existing login form, but since mine was being dynamically injected into the page, it didn't know that a "real" login form ever existed.
Your site is probably already in the list where the browser is told not to prompt for saving a password. In firefox, Options -> Security -> Remember password for sites[check box] - exceptions[button]
The truth is, you can't force the browser to ask. I'm sure the browser has it's own algorithm for guessing if you've entered a username/password, such as looking for an input of type="password"
but you cannot set anything to force the browser.
You could, as others suggest, add user information in a cookie. If you do this, you better encrypt it at the least and do not store their password. Perhaps store their username at most.
I had similar problem, login was done with ajax, but browsers (firefox, chrome, safari and IE 7-10) would not offer to save password if form (#loginForm) is submitted with ajax.
As a SOLUTION I have added hidden submit input (#loginFormHiddenSubmit) to form that was submitted by ajax and after ajax call would return success I would trigger a click to hidden submit input. The page any way needed to refreshed. The click can be triggered with:
jQuery('#loginFormHiddenSubmit').click();
Reason why I have added hidden submit button is because:
jQuery('#loginForm').submit();
would not offer to save password in IE (although it has worked in other browsers).
I spent a lot of time reading the various answers on this thread, and for me, it was actually something slightly different (related, but different). On Mobile Safari (iOS devices), if the login form is HIDDEN when the page loads, the prompt will not appear (after you show the form then submit it). You can test with the following code, which displays the form 5 seconds after the page load. Remove the JS and the display: none and it works. I am yet to find a solution to this, just posted in case anyone else has the same issue and can not figure out the cause.
JS:
$(function() {
setTimeout(function() {
$('form').fadeIn();
}, 5000);
});
HTML:
<form method="POST" style="display: none;">
<input name='email' id='email' type='email' placeholder='email' />
<input name='password' id='password' type='password' placeholder='password' />
<button type="submit">LOGIN</button>
</form>
I found a fairly elegant solution (or hack, whatever fits) for Prototype.JS users, being one of the last holdouts using Prototype. A simple substitution of corresponding jQuery methods should do the trick.
First, make sure there's a <form>
tag, and a submit button with a class name that can be referenced later (in this case faux-submit
) that is nested inside an element with a style set to display:none
, as illustrated below:
<form id="login_form" action="somewhere.php" method="post">
<input type="text" name="login" />
<input type="password" name="password" />
<div style="display:none">
<input class="faux-submit" type="submit" value="Submit" />
</div>
<button id="submit_button">Login</button>
</form>
Then create a click observer for the button
, that will "submit" the form as illustrated:
$('submit_button').observe('click', function(event) {
$('login_form').submit();
});
Then create a listener for submit
event, and stop it. event.stop()
will stop all submit events in the DOM unless it's wrapped in Event.findElement
with the class of the hidden input button (as above, faux-submit
):
document.observe('submit', function(event) {
if (event.findElement(".faux-submit")) {
event.stop();
}
});
This is tested as working in Firefox 43 and Chrome 50.
This solution worked for me posted by Eric on the codingforums
The reason why it does not prompt it is because the browser needs the page to phyiscally to refresh back to the server. A little trick you can do is to perform two actions with the form. First action is onsubmit have it call your Ajax code. Also have the form target a hidden iframe.
Code:
<iframe src="ablankpage.htm" id="temp" name="temp" style="display:none"></iframe>
<form target="temp" onsubmit="yourAjaxCall();">
See if that causes the prompt to appear.
Eric
Posted on http://www.codingforums.com/showthread.php?t=123007
Using a cookie would probably be the best way to do this.
You could have a checkbox for 'Remember me?' and have the form create a cookie to store the //user's login// info. EDIT: User Session Information
To create a cookie, you'll need to process the login form with PHP.
Not every browser (e.g. IE 6) has options to remember credentials.
One thing you can do is to (once the user successfully logs in) store the user information via cookie and have a "Remember Me on this machine" option. That way, when the user comes again (even if he's logged off), your web application can retrieve the cookie and get the user information (user ID + Session ID) and allow him/her to carry on working.
Hope this can be suggestive. :-)
This will automatically enable autocomplete and save password in browsers.
autocomplete="on"
(form)autocomplete="username"
(input, email/username)autocomplete="current-password"
(input, password)<form autocomplete="on">
<input id="user-text-field" type="email" autocomplete="username"/>
<input id="password-text-field" type="password" autocomplete="current-password"/>
</form>
Check out more at Apple's documentation: Enabling Password AutoFill on an HTML Input Element
The browser might not be able to detect that your form is a login form. According to some of the discussion in this previous question, a browser looks for form fields that look like <input type="password">
. Is your password form field implemented similar to that?
Edit: To answer your questions below, I think Firefox detects passwords by form.elements[n].type == "password"
(iterating through all form elements) and then detects the username field by searching backwards through form elements for the text field immediately before the password field (more info here). From what I can tell, your login form needs to be part of a <form>
or Firefox won't detect it.
I tried spetson's answer but that didn't work for me on Chrome 18. What did work was to add a load handler to the iframe and not interrupting the submit (jQuery 1.7):
function getSessions() {
$.getJSON("sessions", function (data, textStatus) {
// Do stuff
}).error(function () { $('#loginForm').fadeIn(); });
}
$('form', '#loginForm').submit(function (e) {
$('#loginForm').fadeOut();
});
$('#loginframe').on('load', getSessions);
getSessions();
The HTML:
<div id="loginForm">
<h3>Please log in</h3>
<form action="/login" method="post" target="loginframe">
<label>Username :</label>
<input type="text" name="login" id="username" />
<label>Password :</label>
<input type="password" name="password" id="password"/>
<br/>
<button type="submit" id="loginB" name="loginB">Login!</button>
</form>
</div>
<iframe id="loginframe" name="loginframe"></iframe>
getSessions() does an AJAX call and shows the loginForm div if it fails. (The web service will return 403 if the user isn't authenticated).
Tested to work in FF and IE8 as well.
If you use a type="button"
with an onclick
handler to login using ajax
, then the browser won't offer to save the password.
<form id="loginform">
<input name="username" type="text" />
<input name="password" type="password" />
<input name="doLogin" type="button" value="Login" onclick="login(this.form);" />
</form>
Since this form does not have a submit button and has no action field, the browser will not offer to save the password.
However, if you change the button to type="submit"
and handle the submit, then the browser will offer to save the password.
<form id="loginform" action="login.php" onSubmit="return login(this);">
<input name="username" type="text" />
<input name="password" type="password" />
<input name="doLogin" type="submit" value="Login" />
</form>
Using this method, the browser should offer to save the password.
Here's the Javascript used in both methods:
function login(f){
var username = f.username.value;
var password = f.password.value;
/* Make your validation and ajax magic here. */
return false; //or the form will post your data to login.php
}
There's an ultimate solution to force all browsers (tested: chrome 25, safari 5.1, IE10, Firefox 16) to ask for save the password using jQuery and ajax request:
JS:
$(document).ready(function() {
$('form').bind('submit', $('form'), function(event) {
var form = this;
event.preventDefault();
event.stopPropagation();
if (form.submitted) {
return;
}
form.submitted = true;
$.ajax({
url: '/login/api/jsonrpc/',
data: {
username: $('input[name=username]').val(),
password: $('input[name=password]').val()
},
success: function(response) {
form.submitted = false;
form.submit(); //invoke the save password in browser
}
});
});
});
HTML:
<form id="loginform" action="login.php" autocomplete="on">
<label for="username">Username</label>
<input name="username" type="text" value="" autocomplete="on" />
<label for="password">Password</label>
<input name="password" type="password" value="" autocomplete="on" />
<input type="submit" name="doLogin" value="Login" />
</form>
The trick is in stopping the form to submit its own way (event.stopPropagation()), instead send your own code ($.ajax()) and in the ajax's success callback submit the form again so the browser catches it and display the request for password save. You may also add some error handler, etc.
Hope it helped to someone.
Source: Stackoverflow.com