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.2.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.2-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for django_trusted_devices-1.2.tar.gz
Algorithm Hash digest
SHA256 057a825034acf544ee6df1b3032ab1bafca0be332e0bcb44eb49d1fe22a3f25e
MD5 f62557d3ec773ab969992809737fad94
BLAKE2b-256 d867593da95e4bf7966abc08ad340c23483cf3e46334879621cc9241b6ebdb48

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_trusted_devices-1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 365029926a55c5239f762a21b19ccf09b12f08a6bb6bfb8e94b23bb4e8704aad
MD5 e4fee4da69247c71ffe3aaefe69bd02d
BLAKE2b-256 cdf658c1ed825ae42c899cf5cfb285fa543a8f7e090075f227fda8bb8bb544a6

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