Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authenticate by IP address in Django

I have a small Django application with a view that I want to restrict to certain users. Anyone from a specific network should be able to see that view without any further authentication, based on IP address alone. Anyone else from outside this IP range should be asked for a password and authenticated against the default Django user management.

I assume I have to write a custom authentication backend for that, but the documentation confuses me as the authenticate() function seems to expect a username/password combination or a token. It is not clear to me how to authenticate using IP addresses here.

What would be the proper way to implement IP address-based authentication in Django? I'd prefer to use as much existing library functions as possible for security-related code instead of writing all of it myself.

like image 211
Mad Scientist Avatar asked Sep 12 '12 07:09

Mad Scientist


1 Answers

There are two suitable approaches for that kind of authentication:

  • As Decorator: if some of views (but not many of them) requires this check, then it is better to write a decorator for that (something like @Jingo had written)
  • As Middleware: if that check needed to be done by all (or many) views, instead of using a decorator, writing a middleware is a better solution.

A sample middleware can be something like:

ALLOWED_IP_BLOCKS = [......]

class NeedToLoginMiddleware(object):
    def process_request(self, request):
        ip = request.META['REMOTE_ADDR']
        if not ip in ALLOWED_IP_BLOCKS: #ip check
            if not request.user.is_authenticated(): #if ip check failed, make authentication check
                return HttpResponseRedirect(...)
        return None
  • You can make ip check using a list, or a regex as @Jingo mentioned.
  • If you are using django authentication and REMOTE_ADDR is not in ALLOWED_IP_BLOCKS list, then you can use is_authenticated to check if related user had logged in or not. But for using is_authenticated in a custom middleware, your custom middleware must be placed after AuthenticationMiddleware, because request.user is set on that level.

    MIDDLEWARE_CLASSES = (
        ...
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'path.to.my.NeedToLoginMiddleware',
        ...
    )
    
    • If a few views do not require this authentication, then you can make a list of exceptional urls and get the request url from request.path and check if the request url requires ip check/authentication.

More info about custom middleware classes

like image 170
FallenAngel Avatar answered Oct 19 '22 13:10

FallenAngel