I am using Django Two Factor Authorization in my login view. I am using a plugin manager to register the plugin TwoFactorPlugin
which
My problem is that although in the view I return the view's HttpResponse
, it always returns the LOGIN_REDIRECT_URL
. If I remove the LOGIN_REDIRECT_URL
, it will always redirect to accounts/profile/
, which is the two factor's default login success url.
Is it possible to override this to return the HttpResponse of the view?
Is there another way to do this (or any suggestion really) ?
views.py:
from two_factor.views import LoginView as TwoFactorLoginView
@login_required
def login_success(request):
success_message = f"User logged in successfully."
return HttpResponse(success_message)
class TwoFactor_LoginView(TwoFactorLoginView):
def form_valid(self, form):
response = super().form_valid(form)
# plugin_response is an HttpResponse return from the plugin "two_factor"
plugin_response = PluginManager.perform_action(
"two_factor",
self.request,
email=self.request.user.email,
password=form.cleaned_data.get("password"),
token=self.request.POST.get("token"),
)
# If the plugin action returns an HttpResponse, use it instead
if isinstance(plugin_response, HttpResponse):
return plugin_response
return response
urls.py:
path("login/", TwoFactor_LoginView.as_view(), name="login"),
path("login_success/", login_success, name="login_success"),
settings.py:
LOGIN_URL = "login/"
LOGIN_REDIRECT_URL = "/login_success/"
I completely rewrote this code.
In the django-two-factor-auth the custom LoginView
class has a done
method which basically redirects to LOGIN_REDIRECT_URL
.
So I overrode it by adding the done
method in my class, exposing the response to be able to modify it to my liking:
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:
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"),
)
return response
# If the user does not have a device.
elif OTPRequiredMixin.is_otp_view(self.request.GET.get("next")):
if self.request.GET.get("next"):
self.request.session["next"] = self.get_success_url()
return redirect("two_factor:setup")
return response
Now all I had to do is add my own get_success_url to my TwoFactor_LoginView
class:
def get_success_url(self):
return reverse("login_success")