It also doesn't add any security. Your password can still be guessed or phished. When authenticating with a cryptographic token (U2F/WebAuthn), that vector goes away. (Even OTP can be phished... the phishing site can just ask you for the code.)
Password managers do make it more difficult to get phished, since they will not know what password to autofill on phishing.example.com... but on the other hand, password manager users are used to having to force-fill a password. I have to take my password out of LastPass to log into Battle.net or Fusion 360, and websites like the Wall Street Journal create your account on dowjones.com but require you to log in on wsj.com (or maybe it's the opposite, I forget).
With WebAuthn, more care is required for both the site operator and the user (have more than one way of logging in in case you lose your phone, make sure the enrollment and login origins are the same), but you are then open to fewer attacks.
WebAuthn is less phishing resistant than it should be. The original intent was that WebAuthn + token binding would ensure that, even if an attacker obtained a fraudulent certificate for a victim site and had an MITM position on the network, the attacker still couldn’t steal a WebAuthn protected session. Alas, Chrome removes its token binding implementation, and WebAuthn no longer has this property. If you authenticate with WebAuthn, and there is a MITM, the MITM gets your session.
(Conventional phishing is still prevented. If you go to, say, g00gle.com, the owner of g00gle.com can’t reuse your authentication to authenticate to google.com. But this relies on your browser actually knowing what domain it’s looking at, which relies on the CA system.)
The WebAuthn specification still explains how you could get token binding if it's present, it's just that it isn't present on any major implementations today.
I'm not sure I believe that real bad guys can successfully attack the Web PKI yet would be foiled by a site using token binding. I think crooks sophisticated enough to burn an exploit to get themselves a fraudulent certificate and put themselves on path for the main attack probably just break into the actual target web server and dispense with everything else entirely. I'd welcome token binding as an option, but I expect I'd never use it in my software.
If you include attackers who control an organizational MITM CA in your threat model, then this could be a big deal. If I were, say, a bank, I would like WebAuthn to protect me against compromise of an organization’s MITM box. Token binding can do this to some extent.
Surely in most MITM box scenarios the token binding just isn't possible?
The only correct MITM box design for TLS is back-to-back client and server, and with that structure there are two TLS channels instead of the one you expected so you can't bind anything to "the" channel between your client and the destination server as there are in fact two channels.
Hacks to try to do something else invariably break and make everything worse. The resulting wreckage for TLS 1.3 took a year of engineering plus an extra year of whining MITM box owners reluctant to stop doing broken crap. We certainly don't want to encourage more of that.
So you are vulnerable to an active MITM, but they don't actually acquire any private secrets to be used to create their own sessions. MITM with passwords OTOH, gives the attacker your password.
That depends on how the site works. On most sites, when I authenticate with WebAuthn (or by any other means), I get a bearer token good for several weeks. So a single spoofed WebAuthn session gets the attacker access
for quite a while.
AFAIK Microsoft added token binding back in the Edge version based on Chromium. As other commenters pointed out, token binding is still part of the WebAuthn spec.
Security seems roughly equivalent, there is always a fallback method of authentication in case the user changes their device or forgets their password. Even biometrics on an iPhone can fall back to a 4 digit pin code.
I agree there are advantages to using public key crypto but the reality is that it's more difficult to get right (and therefore not implemented) compared to a simple hashing function for a password.