I think it's also worth looking at the protocol used to perform the authentication. This is closely tied to what kind of verifier you can/can't store.
If you store a salted hashed password, the authenticating party needs to send you the actual password.
Sure, they could send you the password over an encrypted connection. But that implies that a security context (and shared secret) has already been established. There's a chicken/egg problem here. The most desirable approach is to use a protocol which performs mutual authentication as part of the initial setup of the security context.
There are protocols which can perform password-based authentication without actually sending the plaintext password. It's called a zero-knowledge password proof. In addition, some of these allow a "verifier" to be stored rather than the password itself.
In this scenario, not only do you not store a secret which would allow impersonation of a user, but that secret is also never even sent to you.
If you store a salted hashed password, the authenticating party needs to send you the actual password.
Sure, they could send you the password over an encrypted connection. But that implies that a security context (and shared secret) has already been established. There's a chicken/egg problem here. The most desirable approach is to use a protocol which performs mutual authentication as part of the initial setup of the security context.
There are protocols which can perform password-based authentication without actually sending the plaintext password. It's called a zero-knowledge password proof. In addition, some of these allow a "verifier" to be stored rather than the password itself.
In this scenario, not only do you not store a secret which would allow impersonation of a user, but that secret is also never even sent to you.
We need support for this in browsers :)