After a quick search and reading documentation I implemented Django - Two Factor Authentication in one of my Django project [Reference Link].
It works great I am using Google Authenticator for token based login. The problem arises when I want to extend login methodology of the library. I want to enforce my every user to use 2-Factor-Auth as compulsion. I am not using any signup measures so there has to be a check at the time of Login for a user.
The problem is to design a custom login mechanism but I am unable to incorporate this library with the custom login.
PS: I have a custom user model and currently I am using default Login that came with Django Two Factor Authentication.
I did not though the code was necessary so I did not posted it but I can share it if needed.
After a through look at the library code I was able to manipulate the check in the two_factor library.
So, looking at two_factor
folder it is easily understandable that is nothing but a Django app similar to others.
I navigated to the library files in my virtual environment venv\Lib\site-packages\two_factor\views\core.py
. As mentioned in the documentation there is no enforcement for users till now to setup 2fa.
In LoginView(...)
there is a function done
. IT checks for the device availability for 2fa just add a else clause for redirection.
def done(self, form_list, **kwargs):
"""
Login the user and redirect to the desired page.
"""
# Check if remember cookie should be set after login
current_step_data = self.storage.get_step_data(self.steps.current)
remember = bool(current_step_data and current_step_data.get('token-remember') == 'on')
login(self.request, self.get_user())
redirect_to = self.get_success_url()
device = getattr(self.get_user(), 'otp_device', None)
response = redirect(redirect_to)
if device:
signals.user_verified.send(sender=__name__, request=self.request,
user=self.get_user(), device=device)
# Set a remember cookie if activated
if getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_AGE', None) and remember:
# choose a unique cookie key to remember devices for multiple users in the same browser
cookie_key = REMEMBER_COOKIE_PREFIX + str(uuid4())
cookie_value = get_remember_device_cookie(user=self.get_user(),
otp_device_id=device.persistent_id)
response.set_cookie(cookie_key, cookie_value,
max_age=settings.TWO_FACTOR_REMEMBER_COOKIE_AGE,
domain=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_DOMAIN', None),
path=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_PATH', '/'),
secure=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_SECURE', False),
httponly=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_HTTPONLY', True),
samesite=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_SAMESITE', 'Lax'),
)
else:
return redirect('two_factor:setup')
return response
So what happens is the check for device can only be successful if the user has setup the 2fa but it will never be true for unverified user.
I totally understand there will be a more efficient and elegant method to do the above task but with my little knowledge and time limitation I have to do this. I will post an update if I encounter and I also welcome feedbacks for my solution.