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.29.1.tar.gz (25.7 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.29.1-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for allowedflare-2026.29.1.tar.gz
Algorithm Hash digest
SHA256 85c3292c06234f0675016002f6cfab30341540ae6bd4c79d24b438c7592134bf
MD5 5559319339baf6bb31c521d595333c6b
BLAKE2b-256 1b00d1ee9a71e40d61ce6579be5c20074619642feebf8dc6e45747a217b1a200

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for allowedflare-2026.29.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ce62da1cfb58e34b35937162b9919d6b22fc9315ea368dd97970a5e8a754ca1b
MD5 0df473c36d3f349b84713bbdf70337e6
BLAKE2b-256 30d7040a5e4f6f400d40358c0f506309bd814165176567594e8c19525c997637

See more details on using hashes here.

Release history Release notifications | RSS feed

2026.35.1

2 files

This release

2026.29.1 This release

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