Excellent guy question!
Come on, according to django documentation:
There are 4 views for password reset:
# - password_reset envia o email
# - password_reset_done mostra uma mensagem de sucesso para o envio do email
# - password_reset_confirm checa a url e pergunta por uma nova senha
# - password_reset_complete mostra uma mensagem de sucesso para todo o processo
Views password_reset and password_reset_confirm use the same class to generate and check the token. django.contrib.auth.tokens.default_token_generator
.
1. How it is generated and verified?
Looking at the documentation link it is possible to notice that Django uses the following class for token generation from django.contrib.auth.tokens.default_token_generator
.
Looking for that class in the github project it is possible to verify that the token is generated according to the user and the timestamp.
Removing comments from the code if you have:
def make_token(self, user):
return self._make_token_with_timestamp(user, self._num_days(self._today()))
def _make_token_with_timestamp(self, user, timestamp):
ts_b36 = int_to_base36(timestamp)
hash = salted_hmac(
self.key_salt,
self._make_hash_value(user, timestamp),
).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash)
def _make_hash_value(self, user, timestamp):
login_timestamp = '' if user.last_login is None else user.last_login.replace(microsecond=0, tzinfo=None)
return (
six.text_type(user.pk) + user.password +
six.text_type(login_timestamp) + six.text_type(timestamp)
)
By checking this code and what’s on github (I won’t include everything because I think it’s unnecessary) we can conclude that the token formed is generated from the timestamp+"-"+hash
Where:
#timestamp = conversao numero de dias desde 01/01/2001 para a base 36.
#hash = user.pk + user.password + user.last_login + timestamp
The fact that the code is used six.text_type
is due to the fact that a pattern of str
for the Python3 and unicode
for the other versions, as shown in the class code itself six
.
if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes
MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
2. The token is either persisted in the database and linked to the user, or only one id hash is generated ?
As it is possible to verify in the project code, the token is not persisted but generated and confirmed at the time of access. As demonstrated in the first question.
3. Using this method tokens can be generated for other utilities, for example to activate an account?
Yes, you can enjoy the class django.contrib.auth.tokens.default_token_generator
to be able to generate and validate the token, but you will have to implement your own views.
Thank you very much, I had seen this code on Github but I didn’t understand how it was the validation since it was not persisted a code for comparison, so summarizing and similar to the way it encrypts the password, just uses the same encryption mechanism and compares the keys ?
– user5020
This documentation and version 1.8 , is valid for newer versions ?
– user5020