> > The one slight issue > is that if the user picks the same password (or ever does so in the > future) then the hash could become the same again, >
I don't think that's true, at least using django.contrib.auth. The salt is re-generated whenever the password is changed, so the odds of the user picking the same password and obtaining the same salt are fairly close to zero. :) Including last_login in the hash is certainly a fine idea, though. -- Scott On Sat, Jun 28, 2008 at 7:29 AM, Luke Plant <[EMAIL PROTECTED]> wrote: > > On Saturday 28 June 2008 01:39:26 Scott Moonen wrote: > > > > The problem with this is it requires state on the server, which > > > means . . . > > > > I don't think it's necessary to implement this in such a way that > > additional server state is stored. Instead, you could let the > > confirmation token be a hash of the internal user state -- > > including, most importantly, the user password's salt and encrypted > > values. That way, the valid confirmation token is 1) known only to > > the server (the User 'password' field is not externalized), 2) able > > to be computed at any time without being stashed anywhere, 3) > > constant until the user changes their password, and 4) guaranteed > > to change whenever the password is actually changed. > > When I was writing the email, I almost included something about > including a 'last modified' timestamp on the user object, so I was > getting close, but not quite. This is great. The one slight issue > is that if the user picks the same password (or ever does so in the > future) then the hash could become the same again, and anyone who > intercepted the email once would be able to reset the password again. > However, this is fixable by including user.last_login in the hash of > the internal user state. (We don't want to force people to use > different passwords, and we can't do that properly anyway without > keeping a history of password hashes). > > So, the URL would end up like: > > https://example.com/reset/34-7127f83ebf8ce7ed22bdc50a50572a30 > > i.e. > > https://example.com/reset/{uid}-{hash}<https://example.com/reset/%7Buid%7D-%7Bhash%7D> > > where > > hash = sha1(settings.SECRET_KEY + str(user.id) + user.password + > str(user.last_login)) > > The reset page then allows the user to enter a new password. It sets > the new password (which *is* allowed to be the same as the last > password) and updates the last_login timestamp. > > I'm happy to implement -- I've got the tests setup already etc, so it > should be easy enough. > > Luke > > -- > "I have had a perfectly lovely evening. However, this wasn't it." > (Groucho Marx) > > Luke Plant || http://lukeplant.me.uk/ > > > > -- http://scott.andstuff.org/ | http://truthadorned.org/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---