Skip to main content

Authenticate to Django with JSON Web Tokens (JWTs) signed by Cloudflare Access. A Django reimplementation of https://developers.cloudflare.com/cloudflare-one/identity/authorization-cookie/validating-json/#python-example

To run the demo, set the following environment variables:

export ALLOWEDFLARE_ACCESS_URL=https://your-organization.cloudflareaccess.com
export ALLOWEDFLARE_AUDIENCE=64-character hexadecimal string
export ALLOWEDFLARE_PRIVATE_DOMAIN=your-domain.tld

Then run

docker compose up

Configure Cloudflare Tunnel public hostname demodj.your-domain.tld to http://localhost:8001 or equivalent.

Customizing user setup

On every authenticated request, the backend calls configure_user(user, request, created), which by default makes the user staff and grants all view_* permissions to an allowedflare_everyone group so everyone can browse the admin site read-only. Set ALLOWEDFLARE_CONFIGURE_USER in settings to replace it.

The default re-checks group permissions on every request (a few queries). If you'd rather pay nothing on the request path, do per-user setup only on creation and sync group permissions at post_migrate — the only moment new permissions can come into existence:

# settings.py
def ALLOWEDFLARE_CONFIGURE_USER(user, request, created):
    from yourapp.allowedflare_user import configure_user
    return configure_user(user, request, created)

# yourapp/allowedflare_user.py
from django.contrib.auth.models import Group, Permission

def configure_user(user, request, created):
    if created:
        user.is_staff = True
        user.save()
        everyone, _ = Group.objects.get_or_create(name='allowedflare_everyone')
        user.groups.add(everyone)
    return user

def sync_everyone_permissions(sender, **kwargs):
    everyone, _ = Group.objects.get_or_create(name='allowedflare_everyone')
    missing = Permission.objects.filter(codename__startswith='view').exclude(group=everyone)
    if missing.exists():
        everyone.permissions.add(*missing)

# yourapp/apps.py
from django.apps import AppConfig
from django.db.models.signals import post_migrate

class YourAppConfig(AppConfig):
    name = 'yourapp'

    def ready(self):
        from yourapp.allowedflare_user import sync_everyone_permissions
        post_migrate.connect(sync_everyone_permissions, weak=False)

TODO

  • Iterate on the same-origin (re-)authenticating proxy
  • Iterate on Admin site ModelBackend
    • http://localhost:8001/admin/login/ text when authenticated is "You are authenticated as , but are not authorized to access this page. Would you like to login to a different account?"
  • Expand unit test coverage
  • Basic integration and end-to-end tests
  • mTLS support and testing
  • Configure PostgreSQL
    • Post-migration hook to create a readonly DB user
    • Use the readonly DB user for django-sql-explorer and jupyterhub
    • Update the django-sql-explorer allowlist to accept SET since it's only dangerous for MySQL
    • Exclude only specific fields, like password hash, from the django-sql-explorer view of the django.contrib.auth schema
    • See if admin site change history fields can be shown in the django-sql-explorer schema viewer

Open Questions

Download files

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

Source Distribution

allowedflare-2026.35.1.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

allowedflare-2026.35.1-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

Details for the file allowedflare-2026.35.1.tar.gz.

File metadata

  • Download URL: allowedflare-2026.35.1.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.6

File hashes

Hashes for allowedflare-2026.35.1.tar.gz
Algorithm Hash digest
SHA256 eabae676ad16103f19df73a15ac4f768f991afecb5b419f29e11ff3e19f70120
MD5 651bf3a392e81d1acf81df6c113d14bf
BLAKE2b-256 f3d6c071f43729d60176071defd7d86092101535e4c10af0202fc34d6b057d85

See more details on using hashes here.

File details

Details for the file allowedflare-2026.35.1-py3-none-any.whl.

File metadata

File hashes

Hashes for allowedflare-2026.35.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4912e5d22bd2336055752dd4a20c032ca53c14ec997c18cef0f3eae850fdc1c7
MD5 30ad1cc6fbb846a28bf6944ddc06f51e
BLAKE2b-256 35ba748a5ff1c7922d8d64eae214b57f049ffdf375465d547a99e20177715df9

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2026.35.1 This release

2 files

2026.29.1

2 files

2024.44.3

2 files

2024.44.1

2 files

2024.28.2

2 files

2024.28.1

2 files

2024.18.0

2 files

2024.10.3

2 files

2024.10.2

2 files

2024.10.1

2 files

2024.10.0

2 files

2024.9.0

2 files

2023.47.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page