Goals:
My first got the first three points, but required a tricky dance [2]
- if request.GET.get('next) is set, store it for later
- then forcibly redirect user to my test view
- let that be captured by django-otp or let directly through
- redirect to the page we stored first time
[2] https://gitlab.com/goetzk/django-otp-vip/commit/2bfb89e0bf405864077c7683cda51f1102f12021
I've just come up with what I think is a better solution so I'm going to share it with the group - I'm happy to receive some pointers on how to improve it too.
Its a single ~50 line piece of middleware [3] which can be installed after django_otp.middleware.OTPMiddleware and ensures any user that has an otp device and is authenticated is sent to the otp login form.
[3] https://gitlab.com/goetzk/django-otp-vip/commit/787c89c37821b48151bc77c7e37ba2ebba09f401
Peter: Is this something that (with changes) you'd be happy to merge in to django-otp?
thanks,
kk
Because links break over time, this is the code as committed just now:
# Set up logging first thing
import logging
logger = logging.getLogger(__name__)
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django_otp import user_has_device, _user_is_anonymous, _user_is_authenticated
# https://stackoverflow.com/questions/2916966/non-global-middleware-in-django
# was the best help I found here, with several good posts.
otp_login_url = reverse('run_multi_factor') # This should probably be settings.OTP_LOGIN
excluded_urls_list = ['/accounts/logout/', otp_login_url]
class MandatoryOtpMiddleware(object):
"""Ensure users configured for OTP are using it.
This middleware uses data set by django_otp.middleware.OTPMiddleware so must
be installed after it in Django middleware settings.
"""
def process_request(self, request):
"""
Automatically ensure users who should be logged in via OTP are.
"""
current_url = request.path_info
# We don't need to worry about annon users
if _user_is_anonymous(request.user):
return None
# A select few views can't be captured. For example
# * Logout means we can never leave the site
# * OTP login means a redirect loop when viewing the otp login url.
if current_url in excluded_urls_list:
logger.debug('Currently requested url ({0}) is in excluded urls list ({1})'.format(current_url, excluded_urls_list))
return None
# Only need to check this if they are logged in
if _user_is_authenticated(request.user):
# If they have at least one device they should be logged in via OTP
if user_has_device(request.user):
if not request.user.is_verified():
logger.debug('{0} is authenticated but not verified. Redirecting to {1}'.format(request.user, otp_login_url))
return HttpResponseRedirect(otp_login_url)
# else, they are verified and are OK
# else they have no device; they don't need to have OTP
--
You received this message because you are subscribed to the Google Groups "django-otp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-otp+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.