There are different reasons to do a two-page login:
-
Realm discovery
-
SSO (in general)
-
"Security" (like your bank showing you "your" picture after you enter your username)
I recently had to convert a login page from the classic email/password/submit page to a two-step process because we started having users for whom we didn't store a password and they needed to be authenticated/redirected to their identity provider. My initial version worked. But only in incognito/privacy mode ignoring the real-world usage of password managers. Chrome, Firefox, and LastPass all had different issues in auto-populating the password field on the second page (or sometimes the username on the first field).
Note
|
For the this article, please read "username" as "username and/or email", depending on your application. |
I tried some of the suggestions I found on the Internet:
-
Making a hidden
username
form input on the password page (there already was a static element showing the provided username), similar to:
<input type="hidden" size="50" value="{{ username }}"
name="username" id="username" autocomplete="username">
-
Add the correct autocomplete value for password, as well:
<input type="password" size="50" value=""
name="password" id="password" autocomplete="current-password"/>
But it just didn't work reliably. The above was enough, sometimes, for some of three mentioned above.
I read Password Form Styles that Chromium Understands, which kind of helped but it failed to work everywhere. Sign-in form best practices says "oh just do it in Javascript" and then links back to that Chromium page.
Another page current post in the mists of my past, suggested having a hidden password field on the first page, where you just ask for username. So I tried this:
<style> .hidden { display: none; } </style>
<input class="hidden" name="hiddenPwd" type="password" />
and various combinations of type
, class
with CSS that hides it, type="hidden"
, and so on. But
still not everything worked.
So, I kept looking and found, oddly enough, the Auth0 login page gave me what I needed, where the final version is this password input on their initial page:
<input class="cfd3a9ac2" name="hiddenPwd" type="password" autoComplete="off"
tabindex="-1" aria-hidden="true" />
the "magic", as it were, ended up being:
-
Hiding via CSS.
-
Its own HTML name.
-
type="password"
-
And, amazingly,
autocomplete="off"
! Thatoff
is what what lets Firefox, Chrome, and LastPass to act like they should.
Example minimal HTML forms one can use as a good starting point.
first-template.html
<form action="/login/" method="post">
<input type="text" inputmode="email" size="50" required autofocus
name="username" id="username" autocomplete="username">
<input class="hidden" name="hiddenPwd" type="password" autoComplete="off"
tabindex="-1" aria-hidden="true" />
<input type="submit" value="Next" />
</form>
second-second-template.html
<form action="/login/" method="post">
{{ username }}
<input type="hidden" size="50" value="{{ username }}" name="username"
id="username" autocomplete="username">
<input type="password" size="50" value="" name="password" id="password"
autocomplete="current-password"/>
<input type="submit" value="Log In" />
</form>