Skip to main content

Django module for anonymous lockout

Project description

Django Anonymous Lockout

Django anonymous lockout is a simple django module for keeping track of failed loging attemps to an endpoint that is protected by some password, but does not require authentication with an authentication backend.

It works by fetching the IP of the one making the attempt. If the attempt is successful, it stores this and the resource can be shown. If the attempt fails, the session connected to the attempt get's it's failed_in_row field incremented. If this counter exceeds the threshold (default 100), the IP address is locked out for LOCKOUT_DURATION time (default 1 day). The only time the counter is reset, is after this lockout has expired.

Installation

Djano anonymous lockout can be installed with pip:

pip install django-anon-lockout

Then add anon_lockout to INSTALLED_APPS. It can go in any order.

INSTALLED_APPS = [
    ...,
    anon_lockout,
]

Finally migrate the models:

python manage.py migrate

Usage

Django Anonymous Lockout operates without signals, which means that you will specifically have to call the handler for it to work. The handler is specified in handlers.py (handle_attempt). It takes in the ip, wheter the attempt was failed or not and which resource was attempted accessed.

In your code, you would typically check if the password is correct and then call handle_attempt with the correct arguments. handle_attempt will return True if the attempt leads to a lockout, or the user (ip and resource) is already locked out. This means that even though a user might have "authenticated" correctly, if the ip is locked out, it will still not allow the user to see the resource.

To get the IP of an request, you can for instance use this snippet:

def get_ip(request: HttpRequest):
    """Returns the ip (hashed) of the given request."""

    user_ip: str = request.META.get("HTTP_X_FORWARDED_FOR")
    ip: str = ""
    if user_ip:
        ip = user_ip.split(",")[0]
    else:
        ip = request.META.get("REMOTE_ADDR")
    return hashlib.sha256(ip.encode("utf-8")).hexdigest()

This snippet is also included in utils.py.

Example

Assuming you have a simple form with the field "password".

views.py:

def my_endpoint(request, resource_id):
    if request.method == "POST":
        form = MyForm(request.POST)
        if form.is_valid():
            password = form.cleaned_data["password"]
            if correct_password(password):
                locked = handle_attempt(get_ip(request), failed=False, resource="resource")
                if not locked:
                    return redirect(request, "see-resource")
            else:
                locked = handle_attempt(get_ip(request), failed=True, resource="resource")
                # do more handling here
            if locked:
                form.add_error("password", "Locked out")
    else:
        form = MyForm()
    context = {
      "form": form,
    }
    return render(request, "anon_login.html", context)

A working, but very simple example is in tests/views.py.

Configuration

There are 2 settings that you can override:

LOCKOUT_DURATION: Decides how long a user is locked out for. Default is 1 day.

LOCKOUT_THRESHOLD: Decides how many attempts in a row that has to fail for a lockout to occur. Default is 100 attempts.

Tests

There are a few tests that makes sure the basic funtionality works. These can be run by:

python manage.py test tests.tests

Note: for this to work you would have to clone this repo. It does not work if it is included in INSTALLED_APPS.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_anon_lockout-2.1.0.tar.gz (6.6 kB view details)

Uploaded Source

Built Distribution

django_anon_lockout-2.1.0-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file django_anon_lockout-2.1.0.tar.gz.

File metadata

  • Download URL: django_anon_lockout-2.1.0.tar.gz
  • Upload date:
  • Size: 6.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.4

File hashes

Hashes for django_anon_lockout-2.1.0.tar.gz
Algorithm Hash digest
SHA256 999867b8dcb7f68e48814c0d491af511fe0ac0fb6f3e6615dbc48d5168521e27
MD5 c46de0a03c0aaff4e63099451d0f278e
BLAKE2b-256 b02e6278323f3b3ff5cf6aecb0d6efece7c8778dff328e55542bed2f0c14fa6e

See more details on using hashes here.

File details

Details for the file django_anon_lockout-2.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_anon_lockout-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71ef9ceb808f22db9b06a6a144b501739fa587b7910d73f608139ae31e5945a6
MD5 62f600717f8a64fdc90341834920067c
BLAKE2b-256 19298dd1f666984d9fd11639d77ebffc8806510599121dc9647c2b6c6a3da08a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page