is deprecated in Vaadin 7, what is the recommended way to present a login form that browsers will recognize and auto-fill with saved username and password?
Specifically I’m using the LastPass FireFox plug-in. It doessn’t recognize a
TextField and
PasswordField in a
FormLayout .
Nowadays, all browsers except Firefox have unfortunately closed the loophole that LoginForm depended on to make the browser store and autofill the password. We are not aware of any workarounds that could work together with Vaadin’s AJAX nature.
The most reliable way is to use a Servlet or RequestHandler that serves static HTML containing a that is POSTed and processed before passing requests through to Vaadin’s normal bootstrap handler. We have planned to write a tutorial about how to do this, but it has not yet been done.
You can still continue using LoginForm with Vaadin 7 if you want to even though it is deprecated. It works in the same way as in Vaadin 6.x which means that Firefox saves username and password, most other browsers save the username and some save nothing at all.
I have no news regarding the tutorial. There are still lots of bugs that have higher priority than writing a tutorial for something that is essentially just a small usability inconvenience.
I don’t understand why LoginForm is deprecated. The “loophole” you are talking about is still there, it’s just that most browsers are a bit more strict nowadays. The most obvious restriction being that the form containing the username/password cannot be submitted using javascript - something that can easily be fixed in LoginForm.
I did a little research and quite a bit of trial-and-error, and eventually came up with something that runs on most browsers (if not all):
public class App extends Application {
@Override
public void init() {
LoginForm loginForm = new LoginForm() {
@Override
public byte[] getLoginHTML() {
String html = new String(super.getLoginHTML());
// most browsers: do not use javascript to submit the form
html = html.replace(
"<form id='loginf' target='logintarget' onkeypress=\"submitOnEnter(event)\"",
"<form id='loginf' target='logintarget'");
// chrome: the form.action attribute cannot be set using javascript - make it static
String winPath = getApplication().getURL().toString() + getWindow().getName();
html = html.replace(
"<form id='loginf'",
"<form id='loginf' action='" + winPath + "/loginHandler'");
// chrome: the iframe.src attribute must not be blank
html = html.replace(
"<iframe name='logintarget'",
"<iframe name='logintarget' src='#'");
// most browsers: use a "real" <input type=submit> element
int buttonStartIdx = html.indexOf("<div><div onclick=");
int buttonEndIdx = html.lastIndexOf("</form>") - 1;
html = html.replace(
html.substring(buttonStartIdx, buttonEndIdx),
"<input type='submit' value='" + getLoginButtonCaption() + "'");
return html.getBytes();
}
};
Window mainWindow = new Window();
mainWindow.setContent(loginForm);
setMainWindow(mainWindow);
}
}
I tested this against the most recent versions of the browsers that I know:
As a security professional, I would recommend not remembering passwords on the form itself. It is generally a bad security practice and any static analysis review of your source code should return a finding. The reason for this is that the passwords are generally stored somewhere on disk in a non-secure way making them susceptible to being found by an attacker. This exposes unnecessary risk to your end user.
What do you mean by “remembering passwords on the form itself”? The form’s HTML does not contain any passwords. Instead, the HTML is structured in such a way that browser-side tools that auto-fill passwords are capable of recognizing it as a login form.
In any case, while your comment may be good advice, etc., you are talking about a separate issue that’s not relevant to this discussion.
Not all password auto-fill solutions are stupidly insecure.
If someone wants to use a tool to auto-fill passwords, who are you or me to tell them that they can’t?
This discussion is simply about making it possible for people to do something, not forcing them to.
I believe it is quite relevant to the topic. As a security professional, I would not be doing what I am ethically responsible for if I did not point out the risks involved with a potential solution. The discussion is around implementing something which, as you correctly pointed out, could be implemented in a very non-secure method. Implementing a secure solution to this problem is not an easy thing to solve and a lot of smart people do not do it securely because there are things that can be missed. I am simply bringing awareness to that risk and how the security industry views auto-complete and auto-fill solutions with regards to passwords. You can choose to do with that information as you wish.
We did test some alternatives similar to what you did before we decided to deprecate the component, but we did not find the solution that you have found. We were aware that the loophole was still present, but our assumption was that it didn’t work any more if the form was submitted in an iframe.
I have updated
ticket #8171 accordingly and it might well lead to us removing the deprecation before Vaadin 7.0.0 is released.
As someone with insights into both security and usability, I would recommend the application developer and the end user to choose whether to save passwords or not based on various tradeoffs.
Most applications that involve sensitive data, e.g. internet banking sites, have chosen to tell the browser to not save the password, whereas most other applications lean towards the usability (or ignorance) of allowing the passwords to be saved.
An end user that is aware of the security tradeoffs can choose whether to save the password based on how highly he values the security of that particular password combined with e.g. reliance on the used browser’s capability of storing the password in a secure way (e.g. the master password in Firefox or browsers storing the passwords in the secure OS X keychain that is protected by the user’s login password). End users that are not aware of security implications might still choose to store the password in a text file somewhere if the application doesn’t offer to save the password…
Ok, just wanted to post here my idea for this issue. Could I create my custom client/server component place there (in client widget constructor all fields that I needed in form)? Or browser will not understand that this is the form that it need to full fill, cause approach with LoginForm.class looking as a hack.
P.S. would be great if we continue discussion about this issue…
Just wanted to bump this again, has anyone tried the method Leif hinted at?
If I get a chance I will have a go.
Regarding the ethics of the topic, I think how people store the credentials on their own PC is out of the developers control, we provide a platform that conforms as much as possible to modern web standards, which involves accepting passwords if they are provided by the browser. My concern is however that it is the assumption of the user that this information is only submitted when they click login? It’s all semantics I suppose as if it can be done then it will be done but is it an issue with Vaadin if it can be done? Wouldn’t this allow you to harvest the users address and even card details and upload them to the server without their knowledge in theory? If this is the case people should there be a tutorial at all? I think not.
The uri was the tricky part. Note that with so much HTML changing, it’s easier just to replace it all. Also, there didn’t seem to be any point in calling the set*Caption() functions only to reference them here, so my captions are just in the HTML; change it as you with for your application.
It’s been 4 years now. Is the tutorial available finally? The one to which Thomas Hoenen is referring is for the deprecated LoginForm. It’s very annoying not being able to remember credentials / autofill forms, and I don’t want to use any hackish method as the iframe one.
Unconsistent info about how to supposedly accomplish this is unconsistent accross Vaadin sources. For instance:
“Login form with auto-completion and auto-fill for all major browsers”… blah… “You can derive from this class and implement the createContent(com.vaadin.ui.TextField, com.vaadin.ui.PasswordField, com.vaadin.ui.Button) method”… blah blah… “Note that the API of LoginForm changed significantly in Vaadin 7.7”
No such “createContent()” method exist in Vaadin 7.7.
“This component no longer fulfills its duty reliably in the supported browsers and a VerticalLayout with two TextFields can be used instead.”
No details are given on how to accomplish this purpose with a VerticalLayout and two TextFields, but that’s what my login form was using for sure and in any case browser is not offering to remember passwords, no matter which one (Chrome, Firefox, IE…) I try.
Also that class has 4 .addListener() methods, two of them are deprecated, and and extra .addLoginListener()… which of them is the proper one to implement a regular login?? If I try to implement all the abstract classes of both methods there’s only a loginSuccessful(), which vastly differs from the code posted by Thomas Hoenen.
Vaadin 6 docs are of no help to, as what’s stated here doesn’t seem to apply anymore:
I just discovered that they un-deprecated LoginForm using this extension. However, when trying to find the docs, they refer to methods tht don’t exist:
“Release notes - Feb 12, 20160.6.2:
Calling
setInputPrompt on the password field breaks the functionality of the login form, so disable it from having any effect. The input prompt is not readable, so it does not make sense to use this feature in any case.”
The setInputPrompt() method don’t seem to exist. Also, when trying to follow instructions from
the plugin GitHub page , DefaultVerticalLoginForm and other classe don’t exist.