Skip to main content

Reusable Django app for TOTP and WebAuthn two-factor authentication

Project description

Django Lokdown - Two-Factor Authentication (2FA) System

A reusable Django package providing robust Two-Factor Authentication (2FA) with support for TOTP and WebAuthn Passkeys.

Install in your project

pip install django-lokdown

Add to INSTALLED_APPS, wire URLs, configure WebAuthn settings, and run migrations. See lokdown/README.md for full integration steps.

INSTALLED_APPS = [
    # ...
    "lokdown",
]

Local development (this repository)

The published package is only the lokdown app. The example/ directory is a temporary Django project for manual testing:

pip install -e ".[dev]"
python manage.py migrate
python manage.py runserver

Default admin credentials after migrate: admin / password. See example/README.md.

Overview

The Django Lokdown 2FA system supports two authentication methods:

  1. TOTP (Time-based One-Time Password) - Compatible with authenticator apps like Google Authenticator, Authy, etc.
  2. WebAuthn Passkeys - Modern passwordless authentication using WebAuthn standard, compatible with:
    • YubiKeys and other hardware security keys
    • Apple Keychain (iOS/macOS)
    • Google Password Manager
    • Windows Hello
    • Any WebAuthn-compliant authenticator

Project Structure

django-lokdown/
├── lokdown/               # Pip package (published to PyPI)
│   ├── admin.py           # Django admin interface
│   ├── admin_auth.py      # Admin authentication logic
│   ├── urls.py                # API routes + override_admin_urls()
│   ├── apps.py            # Django app configuration
│   ├── models.py          # Database models
│   ├── serializers.py     # DRF serializers
│   ├── urls.py           # Application URLs
│   ├── views.py          # API views
│   ├── control/          # Authentication controllers
│   │   ├── backup_code_controller.py
│   │   ├── passkey_controller.py
│   │   ├── token_views.py
│   │   └── totp_controller.py
│   ├── helpers/          # Utility helpers
│   │   ├── backup_codes_helper.py
│   │   ├── common_helper.py
│   │   ├── passkey_helper.py
│   │   ├── session_helper.py
│   │   ├── totp_helper.py
│   │   └── twofa_helper.py
│   ├── management/       # Django management commands
│   │   └── commands/
│   │       └── security_audit.py
│   ├── migrations/       # Database migrations
│   ├── static/          # Static files (CSS, JS)
│   └── templates/       # HTML templates
├── example/             # Local dev/test Django project (not published)
│   ├── devsite/         # Example settings and URLs
│   └── manage.py
├── manage.py            # Forwards to example/manage.py
├── pyproject.toml       # Package metadata and dependencies
└── requirements-dev.txt # Editable install for local work

Recent Admin Authentication Improvements

Streamlined User Experience

The admin 2FA system has been significantly improved to provide a seamless, one-click experience:

One-Click 2FA Setup

  • No Confirmation Buttons: Users simply click their preferred 2FA method (TOTP or Passkey)
  • Automatic Progression: Form submits automatically after method selection
  • Loading States: Visual feedback during the setup process
  • Verification-Before-Save: TOTP is only saved to the database after successful verification

Enhanced Passkey Experience

  • Automatic Authentication: Passkey authentication triggers immediately when selected
  • Native Browser Prompts: Uses the browser's built-in WebAuthn UI
  • No Extra Buttons: Eliminates unnecessary confirmation steps
  • Graceful Error Handling: Falls back to other methods if passkey fails

Backup Code Management

  • Visual Display: Regenerated backup codes are shown immediately after generation
  • Download Options: TXT and CSV download formats available
  • Auto-Download: Automatic TXT download after 5 seconds
  • Security Warnings: Clear instructions for secure storage
  • Dark Mode Support: Consistent theming with the admin interface

Admin Interface Features

Security Dashboard

  • Real-time Statistics: 2FA adoption rates, active sessions, failed attempts
  • Security Score: Calculated based on adoption and threat levels
  • Quick Actions: Direct links to manage different security aspects
  • Dark Mode Support: Adapts to user's system preferences

Backup Code Management

  • Bulk Regeneration: Regenerate backup codes for multiple users at once
  • Visual Display: See new codes immediately after regeneration
  • Download Formats: TXT and CSV options for different use cases
  • Security Notices: Clear warnings about secure storage

Admin Actions

  • Overwrite Support: Replace existing 2FA methods through admin interface
  • Bulk Operations: Manage multiple users' 2FA settings
  • Security Audit: CLI commands for comprehensive security monitoring
  • Export Data: Download security reports and logs

User Flow Examples

First-Time Admin Setup

  1. Login: Admin logs in with username/password
  2. 2FA Selection: Clicks TOTP or Passkey (one-click)
  3. Setup Process:
    • TOTP: QR code appears, admin scans with authenticator app, enters code for verification
    • Passkey: Browser prompts for device authentication (fingerprint, face ID, PIN)
  4. Backup Codes: Automatically generated and displayed with download options
  5. Completion: Redirected to admin dashboard

Subsequent Admin Login

  1. Login: Admin logs in with username/password
  2. 2FA Verification: Clicks preferred verification method (one-click)
  3. Authentication:
    • TOTP: Enter 6-digit code from authenticator app
    • Passkey: Automatic device prompt (no extra clicks)
    • Backup Code: Enter backup code with rate limiting
  4. Access: Redirected to admin dashboard

Technical Improvements

Verification-Before-Save Pattern

# TOTP is only saved after successful verification
if totp.verify(totp_code):
    two_fa.totp_secret = secret
    two_fa.save()
    # Generate backup codes...
else:
    # Show error and allow retry

Automatic Passkey Trigger

// Passkey authentication triggers immediately on selection
if (method === 'passkey') {
    setTimeout(function() {
        authenticateWithPasskey();
    }, 500);
}

Backup Code Display

# Store codes in session for immediate display
request.session['regenerated_backup_codes'] = new_codes
request.session['regenerated_backup_codes_count'] = updated

Security Enhancements

  1. Verification-Before-Save: TOTP secrets are only stored after successful verification
  2. One-Click Flows: Streamlined UX reduces user friction while maintaining security
  3. Dark Mode Support: Consistent theming across all interfaces
  4. Rate Limiting: Strict rate limiting for backup codes and failed attempts
  5. Session Management: Secure session handling with automatic cleanup
  6. Error Handling: Graceful fallbacks for failed authentication attempts

API Endpoints

Detailed authentication and 2FA workflows: lokdown/docs/AUTHENTICATION.md.

Authentication Flow

1. Login Initiation

Endpoint: POST /api/auth/login Description: Start the login process. If 2FA is enabled, returns session info for verification.

Request:

{
    "username": "your_username",
    "password": "your_password"
}

Response (No 2FA):

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "requires_2fa": false
}

Response (2FA Required):

{
    "session_id": "abc123def456...",
    "requires_2fa": true,
    "totp_enabled": true,
    "passkey_enabled": true,
    "expires_at": "2024-01-15T10:30:00Z"
}

2. 2FA Verification

Endpoint: POST /api/auth/verify Description: Complete login by verifying 2FA token.

Request (TOTP):

{
    "session_id": "abc123def456...",
    "totp_token": "123456"
}

Request (Passkey):

{
    "session_id": "abc123def456...",
    "passkey_response": {
        "id": "credential_id",
        "response": {
            "authenticatorData": "base64_encoded_data",
            "clientDataJSON": "base64_encoded_data",
            "signature": "base64_encoded_signature"
        }
    }
}

Request (Backup Code):

{
    "session_id": "abc123def456...",
    "backup_code": "ABC123DEF4"
}

Response:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "requires_2fa": false
}

2FA Setup

1. Setup TOTP

Endpoint: POST /api/auth/2fa/setup/totp Description: Generate TOTP secret and QR code for authenticator app setup.

Response:

{
    "secret": "JBSWY3DPEHPK3PXP",
    "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
    "provisioning_uri": "otpauth://totp/..."
}

2. Verify TOTP Setup

Endpoint: POST /api/auth/2fa/verify/totp Description: Verify TOTP token to complete setup.

Request:

{
    "totp_token": "123456"
}

Response:

{
    "message": "TOTP setup verified successfully",
    "backup_codes": ["ABC123DEF4", "GHI567JKL8", "MNO901PQR2"]
}

Save backup_codes immediately; they are shown once and replace any previous backup codes.

3. Setup WebAuthn Passkey

Endpoint: POST /api/auth/2fa/passkey/setup Description: Generate challenge for WebAuthn passkey registration.

Response:

{
    "challenge": "base64_encoded_challenge",
    "rp_id": "localhost",
    "rp_name": "Django Lokdown",
    "user_id": "1",
    "user_name": "username",
    "user_display_name": "John Doe",
    "pub_key_cred_params": [
        {"type": "public-key", "alg": -7},
        {"type": "public-key", "alg": -257}
    ],
    "authenticator_selection": {
        "user_verification": "preferred",
        "resident_key": "preferred"
    },
    "timeout": 60000
}

4. Verify WebAuthn Passkey Setup

Endpoint: POST /api/auth/2fa/passkey/verify Description: Verify WebAuthn passkey registration response.

Request:

{
    "session_id": "<uuid from setup>",
    "passkey_response": {
        "id": "...",
        "rawId": "...",
        "type": "public-key",
        "response": {
            "authenticatorData": "...",
            "clientDataJSON": "...",
            "attestationObject": "..."
        }
    }
}

Response:

{
    "message": "Passkey setup verified successfully",
    "backup_codes": ["ABC123DEF4", "GHI567JKL8"]
}

backup_codes is populated when new codes were generated (passkey-only enrollment). It is empty if the user already had backup codes (e.g. from TOTP).

2FA Management

1. Get 2FA Status

Endpoint: GET /api/auth/2fa/status Description: Get current 2FA settings for user.

Response:

{
    "is_enabled": true,
    "totp_enabled": true,
    "passkey_enabled": true,
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z"
}

2. Disable 2FA

Endpoint: POST /api/auth/2fa/disable Description: Disable 2FA for user.

Response:

{
    "message": "2FA disabled successfully"
}

3. Get Passkey Credentials

Endpoint: GET /api/auth/2fa/passkey/credentials Description: Get list of registered passkey credentials.

Response:

[
    {
        "id": 1,
        "credential_id": "base64_encoded_id",
        "sign_count": 5,
        "transports": ["usb", "nfc"],
        "rp_id": "localhost",
        "created_at": "2024-01-15T10:00:00Z",
        "last_used": "2024-01-15T10:30:00Z"
    }
]

4. Remove Passkey Credential

Endpoint: DELETE /api/auth/2fa/passkey/remove?credential_id=abc123 Description: Remove a specific passkey credential.

5. Verify Backup Code (Dedicated Endpoint)

Endpoint: POST /api/auth/2fa/verify/backup Description: Verify backup code with strict rate limiting (10 attempts per minute per IP).

Request:

{
    "session_id": "abc123def456...",
    "backup_code": "ABC123DEF4"
}

Response:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "requires_2fa": false,
    "message": "Backup code verified successfully"
}

Rate Limiting: This endpoint is strictly rate-limited to 10 attempts per minute per IP address. Failed attempts are logged for security monitoring.

Usage Examples

Setting up TOTP 2FA

  1. Setup TOTP:
curl -X POST http://localhost:8000/api/auth/2fa/setup/totp \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
  1. Scan QR code with your authenticator app (Google Authenticator, Authy, etc.)

  2. Verify setup:

curl -X POST http://localhost:8000/api/auth/2fa/verify/totp \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"token": "123456"}'

Setting up WebAuthn Passkeys

  1. Setup Passkey:
curl -X POST http://localhost:8000/api/auth/2fa/passkey/setup \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
  1. Use the response to register your passkey with the WebAuthn API in your frontend:
// Frontend JavaScript example
const options = await fetch('/api/auth/2fa/passkey/setup', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
        'Content-Type': 'application/json'
    }
}).then(r => r.json());

// Create credentials
const credential = await navigator.credentials.create({
    publicKey: options
});

// Send to server for verification
await fetch('/api/auth/2fa/passkey/verify', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        credential_id: credential.id,
        authenticator_data: btoa(String.fromCharCode(...new Uint8Array(credential.response.authenticatorData))),
        client_data_json: btoa(String.fromCharCode(...new Uint8Array(credential.response.clientDataJSON))),
        signature: btoa(String.fromCharCode(...new Uint8Array(credential.response.signature)))
    })
});

Login with 2FA

  1. Initiate login:
curl -X POST http://localhost:8000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "your_username", "password": "your_password"}'
  1. If 2FA is required, verify with your chosen method:

    TOTP:

    curl -X POST http://localhost:8000/api/auth/verify \
      -H "Content-Type: application/json" \
      -d '{"session_id": "abc123...", "totp_token": "123456"}'
    

    Passkey:

    curl -X POST http://localhost:8000/api/auth/verify \
      -H "Content-Type: application/json" \
      -d '{"session_id": "abc123...", "passkey_response": {...}}'
    

    Backup Code:

    curl -X POST http://localhost:8000/api/auth/verify \
      -H "Content-Type: application/json" \
      -d '{"session_id": "abc123...", "backup_code": "ABC123DEF4"}'
    

Supported Passkey Authenticators

The WebAuthn implementation supports all modern passkey authenticators:

Hardware Security Keys

  • YubiKey (all models)
  • Feitian security keys
  • Solo security keys
  • Titan security keys
  • Any FIDO2-compliant security key

Platform Authenticators

  • Apple Keychain (iOS 15+, macOS 12+)
  • Google Password Manager (Android, Chrome)
  • Windows Hello (Windows 10+)
  • Touch ID (macOS)
  • Face ID (iOS)

Browser Support

  • Chrome 67+
  • Firefox 60+
  • Safari 13+
  • Edge 18+

Security Features

Session Management

  • Login sessions expire after 10 minutes
  • Sessions are tied to IP address and user agent
  • Failed verification attempts are logged

Backup Codes

  • 8 backup codes are generated during TOTP setup
  • Each backup code can only be used once
  • Backup codes are automatically removed after use

Passkey Security

  • Supports multiple passkey credentials per user
  • Credentials are tied to specific users and domains
  • Sign count prevents replay attacks
  • Backup eligible/state tracking for cross-device sync
  • Resident key support for passwordless authentication

Rate Limiting

  • All endpoints are protected by Django REST Framework rate limiting
  • Failed authentication attempts are throttled
  • Backup codes have strict rate limiting: 10 attempts per minute per IP address
  • Failed backup code attempts are logged for security monitoring

Database Schema

UserTwoFactorAuth

  • user: OneToOneField to User
  • is_enabled: Boolean flag for 2FA status
  • totp_secret: CharField for TOTP secret
  • totp_enabled: Boolean flag for TOTP status
  • passkey_enabled: Boolean flag for passkey status
  • backup_codes: JSONField for backup codes
  • created_at/updated_at: Timestamps

PasskeyCredential

  • user: ForeignKey to User
  • credential_id: Unique credential identifier
  • public_key: TextField for public key
  • sign_count: BigInteger for replay protection
  • transports: JSONField for supported transports
  • rp_id: CharField for relying party ID
  • user_handle: CharField for user handle
  • created_at/last_used: Timestamps

LoginSession

  • user: ForeignKey to User
  • session_id: Unique session identifier
  • is_authenticated: Boolean for completion status
  • requires_2fa: Boolean for 2FA requirement
  • totp_verified/passkey_verified: Boolean flags
  • created_at/expires_at: Timestamps
  • ip_address/user_agent: Client information

FailedBackupCodeAttempt

  • user: ForeignKey to User
  • ip_address: GenericIPAddressField for tracking
  • user_agent: TextField for browser/client info
  • attempted_code: CharField for partial code (for monitoring)
  • created_at: Timestamp of failed attempt

Configuration

Environment Variables

The following environment variables can be configured in your Django settings:

# Database Configuration
LOCAL_DB=True  # Use SQLite for local development
DB_NAME=your_db_name
DB_USER=your_db_user
DB_PASSWORD=your_db_password
DB_HOST=your_db_host
DB_PORT=your_db_port

# Security Settings
SECRET_KEY=your_secret_key
DEBUG=True  # Set to False in production
ALLOWED_HOSTS=*  # Configure for production

# CSRF Settings
DJANGO_CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
DJANGO_CSRF_COOKIE_DOMAIN=yourdomain.com

# WebAuthn Configuration
WEBAUTHN_RP_ID=localhost  # Your domain
WEBAUTHN_RP_NAME=Lokdown Local  # Your application name
WEBAUTHN_ORIGIN=http://localhost:8000  # Your origin

# 2FA Configuration
BACKUP_CODE_RATE_LIMIT=10  # Rate limiting for backup codes (attempts per minute)
TWOFA_SESSION_TIMEOUT=10  # Session timeout for 2FA verification (minutes)
BACKUP_CODES_COUNT=8  # Number of backup codes to generate
BACKUP_CODE_LENGTH=10  # Backup code length (characters)
ADMIN_2FA_REQUIRED=True  # Require 2FA for admin users

Django Settings Configuration

The application includes several non-default Django settings:

Security Settings

# SSL/HTTPS Settings (disabled by default for development)
SECURE_SSL_REDIRECT = False
CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
SECURE_HSTS_SECONDS = 60
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Session Configuration
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_AGE = 1209600  # 2 weeks in seconds
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'

REST Framework Configuration

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
    'DEFAULT_FORMAT_SUFFIXES': ['json'],  # Only allow JSON format
    'DEFAULT_VERSIONING_CLASS': None,  # Disable versioning
    'URL_FORMAT_OVERRIDE': None,
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/hour',
        'user': '1000/hour',
    },
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_simplejwt.authentication.JWTAuthentication'],
}

JWT Configuration

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=5),
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': False,
    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'AUTH_HEADER_TYPES': ('Bearer',),
}

API Documentation (Spectacular)

SPECTACULAR_SETTINGS = {
    'TITLE': 'Django Lokdown',
    'VERSION': '1.0.0',
    'SERVE_INCLUDE_SCHEMA': False,
    'COMPONENT_SPLIT_REQUEST': True,
    'CAMELIZE_NAMES': False,
    'SORT_OPERATIONS': False,
    'SORT_TAGS': True,
    'DISABLE_ERRORS_AND_WARNINGS': True,
    'CONTACT': {
        'name': 'Loknus Labs LLC',
        'email': 'loknuslabs@gmail.com',
        'url': 'https://loknuslabs.io',
    },
    'LICENSE': {
        'name': 'GNU General Public License v3.0',
        'url': 'https://www.gnu.org/licenses/gpl-3.0.html',
    },
}

Dependencies

The following packages are required (see requirements.txt):

Core Dependencies

  • Django>=4.2.3
  • djangorestframework
  • djangorestframework-simplejwt
  • django-cors-headers
  • drf-spectacular

2FA Dependencies

  • pyotp - For TOTP generation and verification
  • webauthn - For WebAuthn passkey support
  • qrcode - For QR code generation
  • Pillow - For image processing

Database Dependencies

  • mysqlclient - For MySQL database support (optional)
  • sqlite3 - Built-in SQLite support

Development Dependencies

  • pytest-django - For testing
  • black - For code formatting
  • flake8 - For linting

Installation

Installing in Your Django Project

  1. Add to requirements.txt:
# requirements.txt
Django>=4.2.3
djangorestframework
djangorestframework-simplejwt
django-cors-headers
drf-spectacular
django-lokdown  # Add this line
pyotp
webauthn
qrcode
Pillow
  1. Install dependencies:
pip install -r requirements.txt
  1. Add to INSTALLED_APPS in your Django settings:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'lokdown',  # Add this line
    # ... your other apps
]
  1. Include the URLs in your main urls.py:
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('lokdown.urls')),  # Add this line
    # ... your other URL patterns
]
  1. Configure environment variables in your Django settings:
# WebAuthn Configuration
WEBAUTHN_RP_ID = 'yourdomain.com'  # Your domain
WEBAUTHN_RP_NAME = 'Your App Name'  # Your application name
WEBAUTHN_ORIGIN = 'https://yourdomain.com'  # Your origin

# 2FA Configuration
BACKUP_CODE_RATE_LIMIT = 10  # Rate limiting for backup codes
TWOFA_SESSION_TIMEOUT = 10  # Session timeout for 2FA verification (minutes)
BACKUP_CODES_COUNT = 8  # Number of backup codes to generate
BACKUP_CODE_LENGTH = 10  # Backup code length (characters)
ADMIN_2FA_REQUIRED = True  # Require 2FA for admin users
  1. Run migrations:
python manage.py migrate
  1. Optional: Customize admin interface (recommended):
# In your Django settings
ADMIN_SITE_HEADER = "Your App Admin"
ADMIN_SITE_TITLE = "Your App Administration"
ADMIN_INDEX_TITLE = "Welcome to Your App Administration"

Development Installation

If you want to contribute to the library:

  1. Clone the repository:
git clone https://github.com/your-username/django-lokdown.git
cd django-lokdown
  1. Install in development mode:
pip install -e .
  1. Install development dependencies:
pip install -r requirements.txt
  1. Configure environment variables:
export WEBAUTHN_RP_ID="localhost"
export WEBAUTHN_RP_NAME="Django Lokdown"
export LOCAL_DB="True"
  1. Run migrations:
python manage.py migrate

6Run the development server:

python manage.py runserver

Note: This development setup is only needed if you want to contribute to the library. For regular usage, just follow the "Installing in Your Django Project" steps above.

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For support, email loknuslabs@gmail.com or visit https://loknuslabs.io.

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_lokdown-1.0.0.tar.gz (58.8 kB view details)

Uploaded Source

Built Distribution

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

django_lokdown-1.0.0-py3-none-any.whl (76.6 kB view details)

Uploaded Python 3

File details

Details for the file django_lokdown-1.0.0.tar.gz.

File metadata

  • Download URL: django_lokdown-1.0.0.tar.gz
  • Upload date:
  • Size: 58.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for django_lokdown-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9e587ba5997fec4d7cc550db825f3f9e7e2c34ea16fe466439ab62da5bb1f23d
MD5 a792af80c6458cb7ea296bfe27219cb4
BLAKE2b-256 66a58bfe56d22df522287d4b86734562302f6faa604a38913ea7d8e541f5d41c

See more details on using hashes here.

File details

Details for the file django_lokdown-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: django_lokdown-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 76.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for django_lokdown-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 149d6ebbdee347cbf759ddbe5531335ec9d578ddd80a21e2b53adf33bcb8b909
MD5 9397a3213ed0db9ed1c245eea7689399
BLAKE2b-256 fe50b46d08662be329597adb64833b7edb3c796a613428176e2c976c7e5be142

See more details on using hashes here.

Supported by

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