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.
- π 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
, andTokenVerify
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
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
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,
}
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',
}
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'),
]
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 devicesDELETE /trusted-devices/{device_uid}
β Delete a devicePATCH /trusted-devices/{device_uid}
β Update device permissions
Each trusted device includes:
device_uid
: Unique UUIDuser_agent
: Browser or device stringip_address
: IP addresscountry
,region
,city
: Geolocation (viaipapi.co
)last_seen
,created_at
: Timestampscan_delete_other_devices
,can_update_other_devices
: Optional privileges
- During login, a
device_uid
is generated and embedded in the token. - Clients use that token (with
device_uid
) for refresh/verify. - Each request is linked to a known device.
- Users can manage or restrict their devices via API or Admin.
# π§© 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
- Django
- Django REST Framework
- djangorestframework-simplejwt
- ipapi.co (for IP geolocation)
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 |
We love community contributions! To collaborate:
-
Fork the repo and create a feature branch:
git checkout -b feature/my-amazing-idea
-
Follow code style β run:
make lint # runs flake8, isort, black
-
Write & run tests:
pytest
-
Commit with clear messages and open a Pull Request. GitHub Actions will lint + test your branch automatically.
- π‘ Questions / ideas β GitHub Discussions
- π Bugs / feature requests β GitHub Issues
- PRs require at least one approval and passing CI
- We squashβmerge to keep history clean
- Follows Semantic Versioning (
MAJOR.MINOR.PATCH
), tagged asvX.Y.Z
Made with β€οΈ by Jahongir Ganiev Security questions or commercial support? Open an issue or email [email protected]