Skip to main content

Passwordless authentication for Django using JWT and supporting multiple emails per user.

Project description

JWT Passwordless

PyPI version

A Django REST Framework package that makes implementing passwordless authentication with JWT tokens simple and secure.

This package is a fork of django-rest-framework-passwordless by Aaron Ng, which hasn't been maintained for a couple of years. This fork adds JWT support and several other improvements while maintaining the same core functionality.

This package is actively maintained by the Hire Abroad tech team and is used in production across Hire Abroad projects.

Why JWT Passwordless?

Passwordless authentication improves user experience and security by eliminating password management. Users receive a short-lived token via email or SMS, which they can exchange for a JWT token to authenticate in your application.

Key Differences from Original Repository

This fork introduces several important improvements over the original repository:

  1. JWT Authentication: Uses djangorestframework-simplejwt instead of DRF's TokenAuthentication for more flexible token-based auth with no server-side storage requirements
  2. Configurable Token Length: Token length can be customized (3-6 digits) through settings
  3. Improved Test Coverage: More comprehensive testing for better reliability
  4. Fixed Custom Field Bug: The original repository had a bug where custom email field names worked only in signals but not in other parts of the code (it used hardcoded "email" field in many places). This fork ensures that custom field names work consistently throughout the codebase

Key Benefits

  • 🔒 Enhanced Security: No passwords to be hacked, phished, or forgotten
  • 🌐 Better User Experience: Frictionless sign-in experience without password frustrations
  • 🔄 Seamless JWT Integration: Works with Django REST Framework's JWT authentication
  • 📱 Multiple Channels: Support for both email and mobile authentication
  • Verification Tracking: Built-in support for tracking verified emails/phones

Installation

From PyPI

pip install jwt-passwordless

From Source

git clone https://github.com/Hire-Abroad/jwt-drf-passwordless.git
cd jwt-drf-passwordless
pip install -e .

Note: If you're familiar with the original drfpasswordless package, note that this package uses different import names (jwt_passwordless instead of drfpasswordless)

Quick Start

1. Add to INSTALLED_APPS in settings.py

INSTALLED_APPS = [
    # ...
    'rest_framework',
    'rest_framework_simplejwt',  # Required for JWT functionality
    'jwt_passwordless',
    # ...
]

2. Include the URLs in your project

from django.urls import path, include

urlpatterns = [
    # ...
    path('api/', include('jwt_passwordless.urls', namespace='jwt_passwordless')),
    # ...
]

3. Configure Settings in settings.py

PASSWORDLESS_AUTH = {
    # Authentication types - 'EMAIL', 'MOBILE', or both
    'PASSWORDLESS_AUTH_TYPES': ['EMAIL'],
    
    # Token expiry time in seconds (default: 15 minutes)
    'PASSWORDLESS_TOKEN_EXPIRE_TIME': 15 * 60,
    
    # Email settings
    'PASSWORDLESS_EMAIL_NOREPLY_ADDRESS': 'noreply@example.com',
    'PASSWORDLESS_EMAIL_SUBJECT': "Your Login Token",
    'PASSWORDLESS_EMAIL_PLAINTEXT_MESSAGE': "Enter this token to sign in: %s",
    
    # Optional: customize token length (3-6 digits)
    'PASSWORDLESS_TOKEN_LENGTH': 6,
    
    # Optional: Mark email as verified after successful authentication
    'PASSWORDLESS_USER_MARK_EMAIL_VERIFIED': True,
    'PASSWORDLESS_USER_EMAIL_VERIFIED_FIELD_NAME': 'email_verified',
    
    # Optional: For SMS authentication
    # 'PASSWORDLESS_AUTH_TYPES': ['EMAIL', 'MOBILE'],
    # 'PASSWORDLESS_MOBILE_NOREPLY_NUMBER': '+15551234567',
    # 'PASSWORDLESS_MOBILE_MESSAGE': "Your login code is: %s",
}

# Configure djangorestframework-simplejwt (optional but recommended)
from datetime import timedelta
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    # ... other JWT settings
}

# Required if using mobile authentication with Twilio
# import os
# os.environ['TWILIO_ACCOUNT_SID'] = 'your-account-sid'
# os.environ['TWILIO_AUTH_TOKEN'] = 'your-auth-token'

Usage

Email Authentication Flow

  1. Request a token:

    POST /api/auth/email/
    {"email": "user@example.com"}
    
  2. System sends a token to the user's email

  3. Exchange token for JWT:

    POST /api/auth/token/
    {"email": "user@example.com", "token": "123456"}
    
  4. Receive JWT tokens:

    {
      "access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
      "refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
    }
    
  5. Use the JWT token for authentication:

    GET /api/some-protected-endpoint/
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
    

Mobile Authentication Flow

Similar to email flow but using mobile endpoints:

  1. Request a token:

    POST /api/auth/mobile/
    {"mobile": "+15551234567"}
    
  2. System sends a token to the user's mobile number

  3. Exchange token for JWT:

    POST /api/auth/token/
    {"mobile": "+15551234567", "token": "123456"}
    

Advanced Configuration

Custom Field Names

You can customize the field names used for email and mobile authentication:

PASSWORDLESS_AUTH = {
    # ...
    'PASSWORDLESS_USER_EMAIL_FIELD_NAME': 'email',  # Default is 'email'
    'PASSWORDLESS_USER_MOBILE_FIELD_NAME': 'phone',  # If your field is named 'phone' instead of 'mobile'
    # ...
}

Custom Callbacks

You can customize how tokens are sent by providing your own callback functions:

PASSWORDLESS_AUTH = {
    # ...
    'PASSWORDLESS_EMAIL_CALLBACK': 'myapp.utils.send_custom_email_with_callback_token',
    'PASSWORDLESS_SMS_CALLBACK': 'myapp.utils.send_custom_sms_with_callback_token',
    # ...
}

Customizing Token Creation

You can customize how JWT tokens are created and serialized:

PASSWORDLESS_AUTH = {
    # ...
    'PASSWORDLESS_AUTH_TOKEN_CREATOR': 'myapp.utils.create_custom_jwt_token_for_user',
    'PASSWORDLESS_AUTH_TOKEN_SERIALIZER': 'myapp.serializers.CustomJWTTokenResponseSerializer',
    # ...
}

Security Considerations

  • Token Expiration: Tokens are designed to expire quickly (default: 15 minutes)
  • Token Invalidation: Creating a new token invalidates previous tokens
  • Verified Status: Email/mobile verified status is tracked and updated

Contributing

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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Contact

Hire Abroad - contact@hireabroad.com

Project Link: https://github.com/Hire-Abroad/jwt-passwordless
Original Project: https://github.com/aaronn/django-rest-framework-passwordless


Made by Hire Abroad tech team
Original package by Aaron Ng

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

jwt_passwordless-1.0.4.tar.gz (31.9 kB view details)

Uploaded Source

Built Distribution

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

jwt_passwordless-1.0.4-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file jwt_passwordless-1.0.4.tar.gz.

File metadata

  • Download URL: jwt_passwordless-1.0.4.tar.gz
  • Upload date:
  • Size: 31.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.12

File hashes

Hashes for jwt_passwordless-1.0.4.tar.gz
Algorithm Hash digest
SHA256 4715758975c0ac396c10235c9f94b38c1580862955a5ab9caf03c1a9f67c24d9
MD5 d97fb5f63ae73c3a87df971c9b7025e8
BLAKE2b-256 177b200b8372d2206e27ecd97c3b655f797bf6db40f7ca7fb7c9758840815b40

See more details on using hashes here.

File details

Details for the file jwt_passwordless-1.0.4-py3-none-any.whl.

File metadata

File hashes

Hashes for jwt_passwordless-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 75314ee316701393adb4453dfeaae989adc77e4e3b1492f22bf4c4bc7ed1fa8d
MD5 3823cf99f7aa52c6e401d06e61c92db7
BLAKE2b-256 8f75fa6b479f298bd5608be6d017262d407ec53310f90ceb4638a29887ae3084

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