skip to content

On a login form and on a change-password form, which HTML autocomplete values belong on the password inputs, and what does autocomplete="new-password" change?

level: middleimportance: must knowfreq 60%

answer

  1. two tokens, opposite requests
  2. fill the stored one vs never fill it
  3. username is half the pattern
  4. both new and confirm carry the same token
  5. a change form with no identifier

basics

~20 s

Login uses autocomplete="username" plus autocomplete="current-password". A change-password form uses current-password for the old value and new-password on both the new and confirm fields, which tells the browser to offer a generated password instead of filling the stored one.

solid answer

~50 s

On a sign-in form the two controls are `autocomplete="username"` and `autocomplete="current-password"` — that pair is what tells the browser and any password manager "this is a login, fill the saved credential here". On a change-password or reset form, the old-password box takes `current-password` and **both** the new and the confirm boxes take `autocomplete="new-password"`. The distinction matters because the two tokens ask for opposite behaviour: `current-password` means *fill the value you already have*, while `new-password` means *do not fill the old one, offer to generate a strong one instead, and after submit save this as the updated credential*. Get it wrong and the browser stuffs the existing password into the "new password" box, the user submits it unchanged, and the manager either fails to save or saves the wrong value. If the change form has no visible username field, keep a hidden-from-view but present input carrying `autocomplete="username"` with the account identifier so the manager can match the entry it should update.

code

html · 15 lines
html
<form method="post" action="/account/password">
  <input type="text" name="username" value="[email protected]"
         autocomplete="username" readonly hidden>

  <label for="old">Current password</label>
  <input id="old" name="old" type="password" autocomplete="current-password">

  <label for="new">New password</label>
  <input id="new" name="new" type="password" autocomplete="new-password">

  <label for="confirm">Confirm new password</label>
  <input id="confirm" name="confirm" type="password" autocomplete="new-password">

  <button>Change password</button>
</form>

go deeper

for a junior

Memorise the login pair: autocomplete="username" on the identifier and autocomplete="current-password" on the password, and know that a brand-new password uses new-password instead.

for a middle

Explain the mechanics: current-password invites the browser to fill the stored value, new-password forbids that and invites generation plus a save-or-update prompt. Say why both the new and confirm boxes carry the same token.

for a senior

Be able to diagnose from a symptom — users report the old password appearing in the new-password box, or the manager never offering to update — and connect it to the missing token or the missing username field on an authenticated change screen.

for a principal

Own the credential UX end to end: which flows exist, how generated passwords are encouraged, how the manager's stored entry stays correct after a rotation, and how that policy is enforced in a shared auth component rather than rediscovered per team.

## Two tokens, two opposite requests HTML defines three password-adjacent autofill tokens: `current-password`, `new-password`, and `one-time-code`. The first two look like variations on "password" but they request opposite behaviour from the browser's credential store. `current-password` means: *this field wants the password the user already has for this site.* The browser is invited to fill it from its store, and after a successful submission to treat the form as a sign-in. `new-password` means: *this field wants a password the user does not have yet.* The browser must **not** fill the stored value here. Instead it may offer to generate a strong random password, and after submission it should offer to save or update the stored credential rather than reuse it. ## The two canonical forms A sign-in form: ```html <label for="u">Email</label> <input id="u" name="u" type="email" autocomplete="username"> <label for="p">Password</label> <input id="p" name="p" type="password" autocomplete="current-password"> ``` The `username` token is half the pattern and is routinely forgotten. A password manager stores a pair, so it needs to know which field is the identifier; `type="email"` alone is a weaker signal because plenty of forms contain an email field that is not the account name. A registration form: ```html <input type="email" autocomplete="username"> <input type="password" autocomplete="new-password"> <input type="password" autocomplete="new-password"> ``` Both password boxes get `new-password`. That is deliberate, not a copy-paste slip: when the browser generates a password it fills both, and when the user types their own it knows the second box is a confirmation of the same new secret rather than a second credential. A change-password form: ```html <input type="password" autocomplete="current-password"> <!-- old --> <input type="password" autocomplete="new-password"> <!-- new --> <input type="password" autocomplete="new-password"> <!-- confirm --> ``` ## What breaks when you get it wrong The most common bug is marking every password field `current-password`, or marking none of them at all and letting heuristics decide. The browser then fills the stored password into the *new* password box. Two bad outcomes follow. Either the user does not notice, submits, and the server rejects the change because the new password equals the old one — or the server accepts it and nothing actually changed. Meanwhile the manager sees a login-shaped submission and never prompts to update the stored entry, so the next visit fills a password that is no longer current. The mirror mistake is putting `new-password` on a login field. Now the browser refuses to fill the saved credential and instead offers to generate one, which is baffling on a sign-in screen and pushes users toward typing from memory. ## The missing-username problem Many change-password screens live behind an authenticated session and show no username at all. A credential manager needs an identifier to know *which* stored entry to update — without one it may create a duplicate entry or skip the update prompt entirely. The standard remedy is to include the account identifier in the form as a real input carrying `autocomplete="username"`, made non-editable and hidden visually rather than removed from the accessibility tree by `type="hidden"` — managers generally look at real, rendered fields. Something like: ```html <input type="text" name="username" value="[email protected]" autocomplete="username" readonly hidden> ``` Behaviour varies between managers, so test with more than one; the principle — give the form an identifier — holds regardless. ## Related tokens and grouping `one-time-code` is the third member of the family and covers a code delivered out of band, which is a different flow again. For passkeys, the HTML autofill grammar allows the `webauthn` token to be appended after the field name (as in `autocomplete="username webauthn"`) so that the browser can surface passkeys in the same autofill dropdown as saved passwords. ## What these tokens are not They are not a security control. Nothing about `new-password` enforces password strength, and nothing about `current-password` verifies anything — the server still owns rules, hashing and rate limiting. What the tokens buy is that the *right* value lands in the *right* box and the manager's stored entry stays in sync, which in practice is what pushes users toward long generated passwords instead of memorable reused ones. They are also not a substitute for labelling. A password field still needs a real `<label>`; the autofill token speaks to the browser, the label speaks to the user and to assistive technology, and neither one covers for the other.

  • Why does the confirm-password field get new-password rather than being left without a token?
    Because the browser needs to know the second box holds the same new secret. With `new-password` on both, a generated password is filled into both at once and the manager treats the pair as one credential. Left untokenised, heuristics may read the confirm box as a separate password field, which can suppress generation or produce a mismatched save prompt.
  • A change-password page shows no username anywhere. Why does that matter to a password manager, and what do you add?
    A manager stores identifier-and-secret pairs, so with no identifier in the form it cannot tell which stored entry to update; it may create a duplicate or skip the prompt. Include the account identifier as a real, rendered-but-hidden, read-only input carrying `autocomplete="username"`. A `type="hidden"` input is generally not enough, since managers look at actual form controls.
  • Do these tokens make the form more secure by themselves?
    No. `new-password` does not enforce strength and `current-password` verifies nothing — hashing, password policy and rate limiting all remain server-side concerns. The tokens are a usability mechanism: they make generated passwords easy to accept and keep the stored credential in sync, which indirectly reduces reuse. Treat them as autofill correctness, not as a control you can point at in a security review.

saying these in an interview costs you the question

  • Puts current-password on every password field
  • Thinks new-password is only for registration, not change forms
  • Omits autocomplete="username" from the login form
  • Says the tokens enforce password strength
  • Uses a type="hidden" input as the username signal

context