<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: Tag recovery</title>
    <link>http://blog.moertel.com/articles/tag/recovery?tag=recovery</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>Don't let password recovery keep you from protecting your users</title>
      <description>&lt;p&gt;In 2006&amp;#8217;s most-read article on my blog, &lt;em&gt;&lt;a href="http://blog.moertel.com/articles/2006/12/15/never-store-passwords-in-a-database"&gt;Never store passwords in
a
database!&lt;/a&gt;&lt;/em&gt;,
I urged web programmers, unsurprisingly, not to store passwords
in their user databases.  I tried to persuade them to salt and hash
the passwords instead: store the salts and hashes in the database and
throw the passwords away.  The article, posted shortly after the
Reddit blog announced the &lt;a href="http://web.archive.org/web/20070109023445/http%3A//reddit.com/blog/theft"&gt;theft of its unprotected user
database&lt;/a&gt;, generated buckets of comments.
Reading over them today, I noticed something that I had missed
earlier.&lt;/p&gt;


	&lt;p&gt;It seems that a decent slice of programmers think that switching
to a salted-and-hashed password scheme implies giving up the ability to
assist users who have forgotten their passwords.  If the
passwords are irretrievably hashed away, the programmers reason, there&amp;#8217;s no way
to recover forgotten passwords and email them to stranded users.
Hence those users are screwed.&lt;/p&gt;


	&lt;p&gt;And that wrinkle, it might seem, is a good reason not to switch to a
salted-and-hashed password scheme.&lt;/p&gt;


	&lt;p&gt;But that wrinkle turns out to be imaginary.  Not being able to recover
an account&amp;#8217;s password does not mean that you can&amp;#8217;t
recover the account itself.  The password, after all, is not the thing
of value; the account is.  And, as we shall see, we can recover
an account without knowing its password.&lt;/p&gt;


	&lt;p&gt;Recall that the primary benefit of using a hash is that it is a
one-way operation.  Once you salt and hash a password, there is no
practical way to retrieve it.  That&amp;#8217;s what protects it from would-be
attackers.  But that also means &lt;em&gt;you&lt;/em&gt; can&amp;#8217;t get at it, either.
Thus sending password reminders to people who have forgotten their
passwords is no longer an option.&lt;/p&gt;


	&lt;p&gt;How, then, can you help your stranded users?  One method is to send
them account-recovery tokens, which you can think of as one-time,
special-purpose passwords.  (This method is suitable only if you
require no stronger authentication than knowing that your site&amp;#8217;s users own
the email addresses they claim to own.  This is the case for most &amp;#8220;low
security&amp;#8221; sites such as Slashdot, Reddit, and Digg, as
well as most blogging systems.)&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s how it works.  Say Joe has lost his password and can&amp;#8217;t log in
to your site. He clicks that button that says &amp;#8220;I&amp;#8217;ve lost my
password. Help me!&amp;#8221;  Now what?&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s what you do:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Generate a big, random, unique token and stuff it into Joe&amp;#8217;s account record in the database.  Stuff the current date and time in there, too.&lt;/li&gt;
		&lt;li&gt;Send an email to Joe, but instead of enclosing his password (which you can&amp;#8217;t recover), tell Joe to click on the enclosed account-recovery link, which includes the random token: &lt;code&gt;http://example.com/recover-account?token=pCIqq1unxntVqc8XtCXg&lt;/code&gt;.&lt;/li&gt;
		&lt;li&gt;Joe receives the email and clicks on the link, which sends his token to your site.&lt;/li&gt;
		&lt;li&gt;Look up the token in the user database.  Is it there?
	&lt;ol&gt;
	&lt;li&gt;No? Render a screen that says, &amp;#8220;Sorry, bub, that token is no longer valid.&amp;#8221;  Stop.&lt;/li&gt;
		&lt;li&gt;Yes? Excellent. Grab the user record associated with the token.  (It will, of course, be Joe&amp;#8217;s record.)&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
		&lt;li&gt;Is the date and time stamp on that record more than a few hours old?
	&lt;ol&gt;
	&lt;li&gt;Yes? Render that screen that says, &amp;#8220;Sorry, bub, that token is no longer valid.&amp;#8221; Stop.&lt;/li&gt;
		&lt;li&gt;No? Congratulations.  Joe has effectively authenticated himself via his email address.&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
		&lt;li&gt;Render a confirmation screen that explains the following to Joe:
	&lt;ol&gt;
	&lt;li&gt;His account password is going to be reset to the following random string: &lt;strong&gt;ocZodbew&lt;/strong&gt;. (Generate a new random string each time.)&lt;/li&gt;
		&lt;li&gt;If he likes the password, great.  If not, he can use the change-password feature immediately after the password is reset.&lt;/li&gt;
		&lt;li&gt;If he understands the above and wants to continue, he should confirm by clicking the big &amp;#8220;Reset My Account Password&amp;#8221; button.&lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
		&lt;li&gt;Joe clicks the button.&lt;/li&gt;
		&lt;li&gt;You, in response, do the following:
	&lt;ol&gt;
	&lt;li&gt;Delete the recovery token from Joe&amp;#8217;s user record in the database. (This prevents somebody from using the old token to steal his account, should, for example, Joe&amp;#8217;s email get stolen.)&lt;/li&gt;
		&lt;li&gt;Replace Joe&amp;#8217;s old password with the new, randomly generated password from above.  (You will, of course, use the salted-and-hashed method and &lt;em&gt;not&lt;/em&gt; store the new password itself.)&lt;/li&gt;
		&lt;li&gt;Log Joe in.&lt;/li&gt;
		&lt;li&gt;Render a screen saying, &amp;#8220;Joe, please don&amp;#8217;t forget that your new password is &lt;strong&gt;ocZodbew&lt;/strong&gt;.  If you would like to change it, just visit Change My Password in your account preferences [provide a link].  Otherwise, you&amp;#8217;re logged in and ready to go.  Enjoy the site!&amp;#8221; &lt;/li&gt;
	&lt;/ol&gt;
	&lt;/li&gt;
		&lt;li&gt;And you&amp;#8217;re done.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The code required to make it happen is shorter than the explanation
above.  It&amp;#8217;s one of those easier-done-than-said things.&lt;/p&gt;


	&lt;p&gt;So, if concerns about account recovery have been holding you
back from protecting your users&amp;#8217; passwords, you need hold back no
longer.  It&amp;#8217;s time to &amp;#8220;do&amp;#8221; your due diligence.&lt;/p&gt;


&lt;div class="update"&gt;

	&lt;p&gt;&lt;strong&gt;Update 2007-09-10:&lt;/strong&gt; I made clear that the account-recovery method I
describe above is suitable only for low-security sites where
a valid email address is sufficient to authenticate users.&lt;/p&gt;


&lt;/div&gt;</description>
      <pubDate>Fri, 09 Feb 2007 15:36:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:ddd87596-c734-4f36-996c-bc74a39e9dd3</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2007/02/09/dont-let-password-recovery-keep-you-from-protecting-your-users</link>
      <category>web development</category>
      <category>security</category>
      <category>security</category>
      <category>passwords</category>
      <category>salt</category>
      <category>hash</category>
      <category>database</category>
      <category>recovery</category>
      <category>risks</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/370</trackback:ping>
    </item>
  </channel>
</rss>
