Skip to main content

Secure and manage trusted login devices for Django users

Project description

🔐 Django Trusted Device

A plug-and-play Django app that adds trusted device management to your API authentication system using djangorestframework-simplejwt. Automatically associates tokens with user devices, tracks login locations, and enables per-device control over access and session management.


Docs

🚀 Features

  • 🔑 JWT tokens include a unique device_uid
  • 🌍 Auto-detect IP, region, and city via ipapi.co
  • 🛡️ Per-device session tracking with update/delete restrictions
  • 🔄 Custom TokenObtainPair, TokenRefresh, and TokenVerify views
  • 🚪 Logout unwanted sessions from the device list
  • 🧼 Automatic cleanup, optional global control rules
  • 🧩 API-ready – supports DRF out of the box
  • ⚙️ Fully customizable via TRUSTED_DEVICE Django settings
  • 🚫 Rejects refresh/verify from unknown or expired devices

📦 Installation

pip install django-trusted-device

Add to your INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    'trusted_devices',
    'rest_framework_simplejwt.token_blacklist',
]

Run migrations:

python manage.py migrate

⚙️ Configuration

Customize behavior in settings.py:

TRUSTED_DEVICE = {
    "DELETE_DELAY_MINUTES": 60 * 24 * 7,  # 7 days
    "UPDATE_DELAY_MINUTES": 60,           # 1 hour
    "ALLOW_GLOBAL_DELETE": True,
    "ALLOW_GLOBAL_UPDATE": True,
}

🧩 Usage

🔐 SimpleJWT configuration

Replace default SimpleJWT serializers with TrustedDevice serializers.:

from datetime import timedelta

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'trusted_devices.authentication.TrustedDeviceAuthentication',
    ),
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=30),
    "AUTH_HEADER_TYPES": ("Bearer",),
    "TOKEN_OBTAIN_SERIALIZER": 'trusted_devices.serializers.TrustedDeviceTokenObtainPairSerializer',
    "TOKEN_REFRESH_SERIALIZER": 'trusted_devices.serializers.TrustedDeviceTokenRefreshSerializer',
    "TOKEN_VERIFY_SERIALIZER": 'trusted_devices.serializers.TrustedDeviceTokenVerifySerializer',
}

🔐 Custom Token Views

Replace the default SimpleJWT views with:

from trusted_devices.views import (
    TrustedDeviceTokenObtainPairView,
    TrustedDeviceTokenRefreshView,
    TrustedDeviceTokenVerifyView,
)

urlpatterns = [
    path('api/token/', TrustedDeviceTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TrustedDeviceTokenRefreshView.as_view(), name='token_refresh'),
    path('api/token/verify/', TrustedDeviceTokenVerifyView.as_view(), name='token_verify'),
]

📡 Device Management API

Use the provided TrustedDeviceViewSet:

from trusted_devices.views import TrustedDeviceViewSet

router.register(r'trusted-devices', TrustedDeviceViewSet, basename='trusted-device')

Endpoints:

  • GET /trusted-devices — List all trusted devices
  • DELETE /trusted-devices/{device_uid} — Delete a device
  • PATCH /trusted-devices/{device_uid} — Update device permissions

👤 Device Model

Each trusted device includes:

  • device_uid: Unique UUID
  • user_agent: Browser or device string
  • ip_address: IP address
  • country, region, city: Geolocation (via ipapi.co)
  • last_seen, created_at: Timestamps
  • can_delete_other_devices, can_update_other_devices: Optional privileges

🧠 How It Works

  1. During login, a device_uid is generated and embedded in the token.
  2. Clients use that token (with device_uid) for refresh/verify.
  3. Each request is linked to a known device.
  4. Users can manage or restrict their devices via API or Admin.

🧪 Testing Locally

# 🧩 Create and activate a uv-managed virtual environment
uv venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 📦 Install the package in editable mode with dev extras
uv pip install -e ".[dev]"

# 🧪 Run the test suite
pytest

🧱 Dependencies

  • Django
  • Django REST Framework
  • djangorestframework-simplejwt
  • ipapi.co (for IP geolocation)

🗃️ Model Snapshot

Field Purpose
device_uid UUID primary key
user_agent, ip_address Device fingerprint
country / region / city Geo‑lookup
last_seen / created_at Activity timestamps
can_update_other_devices Granular permission
can_delete_other_devices Granular permission

🤝 Collaboration & Contributing

We love community contributions! To collaborate:

  1. Fork the repo and create a feature branch:

    git checkout -b feature/my-amazing-idea
    
  2. Follow code style – run:

    make lint  # runs flake8, isort, black
    
  3. Write & run tests:

    pytest
    
  4. Commit with clear messages and open a Pull Request. GitHub Actions will lint + test your branch automatically.


🗣️ Discussions & Issues


🛠 Maintainer Workflow

  • PRs require at least one approval and passing CI
  • We squash‑merge to keep history clean
  • Follows Semantic Versioning (MAJOR.MINOR.PATCH), tagged as vX.Y.Z

📄 License

MIT


Made with ❤️ by Jahongir Ganiev Security questions or commercial support? Open an issue or email contact@jakhongir.dev

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_trusted_devices-1.1.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

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

django_trusted_devices-1.1-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file django_trusted_devices-1.1.tar.gz.

File metadata

  • Download URL: django_trusted_devices-1.1.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for django_trusted_devices-1.1.tar.gz
Algorithm Hash digest
SHA256 b9c10e2fc21866e254040d9abc950d4d32fbd1b6badc8fe60521bf52c7b7f929
MD5 6df1c5aac6af108aa53f41c8051c32f2
BLAKE2b-256 bc93227d45f492cc62d07f2c9216b63b34ff0fa8bc101ce51a5094ad03f71c7d

See more details on using hashes here.

File details

Details for the file django_trusted_devices-1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_trusted_devices-1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fe3464ab5f2591301560ccf2c6cd8d12e689d75fc7a8f363f2795fc0497d3272
MD5 c675b9d9bca0cbb1a8a63f8bb1b82416
BLAKE2b-256 5ab100768d46675f74982b7836c6b855fe62c4e1d4f236cee16d17403606e34a

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