I am trying to improve the user experience on registration by not requiring the user to retype their password if validation on other fields fail. There are a few ways to implement this, example using session cookie and storing a hash of the password on the server side. I am exploring this alternative of storing user password temporarily on the client side without having the server to keep track of it. Is this method feasible? What are the risks involved?
In principle, values stored in sessionStorage are restricted to the same scheme + hostname + unique port, and if the browser has a clean exit these values should be deleted at the end of the session. However, according to this post it can survive a browser restart if the user chooses to "restore the session" after a crash (which means its values also exist in persistent memory until they are cleared, so keep that in mind). If well implemented, I'd say it's safe enough - especially compared to your alternative of using a cookie (which has many pitfalls that I wouldn't even consider). The W3C Specification also states that Web Storage might indeed be used to store sensitive data (though it's unclear whether or not that practice is endorsed).
As for the risks, it's simply a matter of tradeoffs: you're making your site a little more convenient for your users, while increasing a little the window of opportunity for the password to be captured (either by means of a XSS vulnerability, by the value persisting in persistent storage for longer than you intended to, or by the user leaving the computer unattended before finishing registration). Ideally, passwords should never leave RAM, but that's usually impractical to do, so some compromise is necessary. I'd just advise to clear the password from sessionStorage as soon as the registration succeeds, and to keep an eye for vulnerabilities on sessionStorage implementations that may eventually come to light.
I suggest another approach: Instead of submitting the form to the server, use an XMLHttpRequest to create the account. If server side validation fails, the form and all its content is still available. If it was successful, redirect to the target page.
You will be having hard time deciding on which of the two stored values to use as the user's intended password (the one in the local storage, or the one in the input field), if none of them are empty but for some reason differ.
This can potentially provide for a social engineering attack vector, where the attacker prepares a trap by opening the registration form, filling the local/session storage either by using you own code and later removing any traces of it (input error notifications) with a DOM editor, or entering desired password directly in local/session storage (both is supported on some browsers and extremely easy to do), then later asking the victim to register with your website and, well, use it. Since your code can be easily inspected/tested to see how you handle such cases, the attacker might do this slightly differently than what I described (even script injections directly in local/session storage aren't out of the question, if you later process that value locally on form POST), but to same effect.
The victim won't suspect anything until she logs out and tries to log back in. Depending on how persistent the user session is, this process of logging out and logging back in might not be necessary, and the victim wouldn't have noticed her password wasn't the one she entered in the password field, but instead the attacker's password of choice was used to create her new account.
Needles to say, the attacker just gained access to the victim's newly created account and all the data the victim entered, even if the victim was cautious and made sure there was no shoulder-surfing involved.
So the takeaway here is that you will potentially have to deal with two different locations of to the system same registration data, that might for whatever reason differ, and decide which one to use in a way that's safe both to your system, as well as the end user that's registering. This might prove pretty tricky to do properly, so I'd advise against it.
Instead, rather make sure your registration form is served via HTTPS, and then simply fill the password field back, as it was last entered on user's POST request and if it satisfies your constraints, even if some of the other input fields are filled in incorrectly and the form needs reposting.
I'd use some intertab communication to distribute the password instead of storing the password in any persistent storage (cookie, localstorage, etc. there are countless solutions, check evercookie). This way the password will live in the browser until you close the last tab for the actual domain.
You can do intertab communication safely with
postMessage probably there are other methods I don't know of, they are always reinventing the wheel. The first two sends the messages to every tab, the last one sends only to tabs opened from the same parent tab, so it is somewhat restrictive, but supported by more browsers.
TildalWave's post is interesting, I think these methods are not vulnerable to that, because the sync is almost instant and you can sync login, logout, etc. too.
If you decide to use localstorage anyways, it is better to use a signed userid, timeout and salt instead of the password itself. You can send the credentials to the server, which can verify them, and send the data with the signature back. They can be stored in a cookie or whatever persistent storage you want. These tokens are sometimes used by REST APIs if there is a browser client, because this solution is stateless and still gives a sensation of having a classic session. Sometimes they sign every request, not just the user id to enhance security.