Storage of the private key is another thing. For a web app it is difficult to acces a hardware-based storage system. So typically it is stored in Localstorage or IndexdedDB, encrypted using a user-provided password. It is possible (but very involved and I have not seen web apps using it) to use WebAuthn for that.