encripted in reset password
This commit is contained in:
parent
f62348dcdb
commit
bd84dbc3bb
|
@ -17,7 +17,7 @@ Including another URLconf
|
|||
from django.contrib.auth import views as auth_views
|
||||
from django.views.generic import RedirectView
|
||||
from django.urls import path, reverse_lazy
|
||||
from .views import LoginView
|
||||
from .views import LoginView, PasswordResetConfirmView
|
||||
from .admin import views as views_admin
|
||||
from .user import views as views_user
|
||||
|
||||
|
@ -44,13 +44,16 @@ urlpatterns = [
|
|||
),
|
||||
name='password_reset_done'
|
||||
),
|
||||
path('auth/reset/<uidb64>/<token>/',
|
||||
auth_views.PasswordResetConfirmView.as_view(
|
||||
template_name='auth/password_reset_confirm.html',
|
||||
success_url=reverse_lazy('idhub:password_reset_complete')
|
||||
),
|
||||
path('auth/reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(),
|
||||
name='password_reset_confirm'
|
||||
),
|
||||
# path('auth/reset/<uidb64>/<token>/',
|
||||
# auth_views.PasswordResetConfirmView.as_view(
|
||||
# template_name='auth/password_reset_confirm.html',
|
||||
# success_url=reverse_lazy('idhub:password_reset_complete')
|
||||
# ),
|
||||
# name='password_reset_confirm'
|
||||
# ),
|
||||
path('auth/reset/done/',
|
||||
auth_views.PasswordResetCompleteView.as_view(
|
||||
template_name='auth/password_reset_complete.html'
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.utils.translation import gettext_lazy as _
|
|||
from django.contrib.auth import views as auth_views
|
||||
from django.contrib.auth import login as auth_login
|
||||
from django.http import HttpResponseRedirect
|
||||
from nacl import secret
|
||||
|
||||
|
||||
class LoginView(auth_views.LoginView):
|
||||
|
@ -23,7 +22,7 @@ class LoginView(auth_views.LoginView):
|
|||
user = form.get_user()
|
||||
# Decrypt the user's sensitive data encryption key and store it in the session.
|
||||
password = form.cleaned_data.get("password")
|
||||
sensitive_data_encryption_key = user.decrypt_sensitive_data_encryption_key(password)
|
||||
sensitive_data_encryption_key = user.decrypt_sensitive_data(password)
|
||||
key_dids = cache.get("KEY_DIDS", {})
|
||||
if not user.is_anonymous and user.is_admin:
|
||||
user_dashboard = reverse_lazy('idhub:user_dashboard')
|
||||
|
@ -41,3 +40,14 @@ class LoginView(auth_views.LoginView):
|
|||
|
||||
return HttpResponseRedirect(self.extra_context['success_url'])
|
||||
|
||||
|
||||
class PasswordResetConfirmView(auth_views.PasswordResetConfirmView):
|
||||
template_name = 'auth/password_reset_confirm.html'
|
||||
success_url = reverse_lazy('idhub:password_reset_complete')
|
||||
|
||||
def form_valid(self, form):
|
||||
password = form.cleaned_data.get("password")
|
||||
user = form.get_user()
|
||||
user.set_encrypted_sensitive_data(password)
|
||||
user.save()
|
||||
return HttpResponseRedirect(self.success_url)
|
||||
|
|
|
@ -2,7 +2,7 @@ import re
|
|||
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from idhub_auth.models import User
|
||||
from idhub_auth.models import User, gen_salt
|
||||
|
||||
|
||||
class ProfileForm(forms.ModelForm):
|
||||
|
@ -31,4 +31,3 @@ class ProfileForm(forms.ModelForm):
|
|||
|
||||
return last_name
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import nacl
|
||||
import base64
|
||||
|
||||
from django.db import models
|
||||
from django.core.cache import cache
|
||||
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
|
||||
from nacl import secret, pwhash
|
||||
|
||||
|
||||
class UserManager(BaseUserManager):
|
||||
|
@ -44,10 +47,8 @@ class User(AbstractBaseUser):
|
|||
is_admin = models.BooleanField(default=False)
|
||||
first_name = models.CharField(max_length=255, blank=True, null=True)
|
||||
last_name = models.CharField(max_length=255, blank=True, null=True)
|
||||
# TODO: Hay que generar una clave aleatoria para cada usuario cuando se le da de alta en el sistema.
|
||||
encrypted_sensitive_data_encryption_key = models.BinaryField(max_length=255)
|
||||
# TODO: Hay que generar un salt aleatorio para cada usuario cuando se le da de alta en el sistema.
|
||||
salt_of_sensitive_data_encryption_key = models.BinaryField(max_length=255)
|
||||
encrypted_sensitive_data = models.CharField(max_length=255)
|
||||
salt = models.CharField(max_length=255)
|
||||
|
||||
objects = UserManager()
|
||||
|
||||
|
@ -92,14 +93,54 @@ class User(AbstractBaseUser):
|
|||
return ", ".join(set(roles))
|
||||
|
||||
def derive_key_from_password(self, password):
|
||||
kdf = pwhash.argon2i.kdf # TODO: Move the KDF choice to SETTINGS.PY
|
||||
ops = pwhash.argon2i.OPSLIMIT_INTERACTIVE # TODO: Move the KDF choice to SETTINGS.PY
|
||||
mem = pwhash.argon2i.MEMLIMIT_INTERACTIVE # TODO: Move the KDF choice to SETTINGS.PY
|
||||
salt = self.salt_of_sensitive_data_encryption_key
|
||||
return kdf(secret.SecretBox.KEY_SIZE, password, salt, opslimit=ops, memlimit=mem)
|
||||
kdf = nacl.pwhash.argon2i.kdf
|
||||
ops = nacl.pwhash.argon2i.OPSLIMIT_INTERACTIVE
|
||||
mem = nacl.pwhash.argon2i.MEMLIMIT_INTERACTIVE
|
||||
return kdf(
|
||||
nacl.secret.SecretBox.KEY_SIZE,
|
||||
password,
|
||||
self.get_salt(),
|
||||
opslimit=ops,
|
||||
memlimit=mem
|
||||
)
|
||||
|
||||
def decrypt_sensitive_data(self, password, data=None):
|
||||
sb_key = self.derive_key_from_password(password.encode('utf-8'))
|
||||
sb = nacl.secret.SecretBox(sb_key)
|
||||
if not data:
|
||||
data = self.get_encrypted_sensitive_data()
|
||||
if not isinstance(data, bytes):
|
||||
data = data.encode('utf-8')
|
||||
|
||||
return sb.decrypt(data).decode('utf-8')
|
||||
|
||||
def encrypt_sensitive_data(self, password, data):
|
||||
sb_key = self.derive_key_from_password(password.encode('utf-8'))
|
||||
sb = nacl.secret.SecretBox(sb_key)
|
||||
if not isinstance(data, bytes):
|
||||
data = data.encode('utf-8')
|
||||
|
||||
return sb.encrypt(data).decode('utf-8')
|
||||
|
||||
def get_salt(self):
|
||||
return base64.b64decode(self.salt.encode('utf-8'))
|
||||
|
||||
def set_salt(self):
|
||||
self.salt = base64.b64encode(nacl.utils.random(16)).decode('utf-8')
|
||||
|
||||
def get_encrypted_sensitive_data(self):
|
||||
return base64.b64decode(self.encrypted_sensitive_data.encode('utf-8'))
|
||||
|
||||
def set_encrypted_sensitive_data(self, password):
|
||||
key = base64.b64encode(nacl.utils.random(64))
|
||||
key_dids = cache.get("KEY_DIDS", {})
|
||||
|
||||
if key_dids.get(user.id):
|
||||
key = key_dids[user.id]
|
||||
else:
|
||||
self.set_salt()
|
||||
|
||||
key_crypted = self.encrypt_sensitive_data(password, key)
|
||||
self.encrypted_sensitive_data = base64.b64encode(key_crypted).decode('utf-8')
|
||||
|
||||
def decrypt_sensitive_data_encryption_key(self, password):
|
||||
sb_key = self.derive_key_from_password(password)
|
||||
sb = secret.SecretBox(sb_key)
|
||||
return sb.decrypt(self.encrypted_sensitive_data_encryption_key)
|
||||
|
||||
|
|
Loading…
Reference in a new issue