Skip to main content

A RESTful API for user signup and authentication using email addresses

Project description

django-rest-authemail

Python package pypi pypi

django-rest-authemail is a Django/Python application that provides a RESTful API interface for user signup and authentication. Email addresses are used for authentication, rather than usernames. Because the authentication user model is based on Django's AbstractBaseUser and is itself abstract, the model can be extended without the need for additional database tables. Token authentication allows the API to be accessed from a variety of front ends, including Django, React and AngularJS clients, and iOS and Android mobile apps.

Features

  • Supports and tested with Django REST Framework 3.7.1.
  • Supports and tested with Django 1.11.17 and 2.0.
  • Supports and tested with Python 3.6 and 3.7.
  • API endpoints for signup, signup email verification, login, logout, password reset, password reset verification, password change, and user detail.
  • Extensible abstract user model.
  • Perform password confirmation and other client-side validation on the front end for a better user experience.
  • Token authentication.
  • User models in the admin interface include inlines for signup and password reset codes.
  • An example project is included and contains example UI templates.

Installation

django-rest-authemail is available on the Python Package Index (PyPI) at https://pypi.python.org/pypi/django-rest-authemail.

Install django-rest-authemail using one of the following techniques.

  • Use pip:
pip install django-rest-authemail
  • Download the .tar.gz file from PyPI and install it yourself.
  • Download the source from Github and install it yourself.

If you install it yourself, also install the Django, Django REST Framework, and requests. Install South if you are using Django < 1.7.

Usage

In the settings.py file of your project, include rest_framework and rest_framework.authtoken in INSTALLED_APPS. Set the authentication scheme for the Django REST Framework to TokenAuthentication.

    INSTALLED_APPS = (
        ...
        #'south',        # Remove comment if you're using South for migrations.
        'rest_framework',
        'rest_framework.authtoken',
        ...
    )

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
        )
    }

Optionally, you may add an AUTH_EMAIL_VERIFICATION setting to specify whether to enable email verification for new users on account registration/signup. Setting this to False will automatically verify newly created users.

Create a Django application for your user data. For example,

    python manage.py startapp accounts

In the models.py file of your application, extend EmailAbstractUser, add custom fields, and assign objects to EmailUserManager(). For example,

    from django.db import models
    from authemail.models import EmailUserManager, EmailAbstractUser

    class MyUser(EmailAbstractUser):
        # Custom fields
        date_of_birth = models.DateField('Date of birth', null=True, blank=True)

        # Required
        objects = EmailUserManager()

In the settings.py file of your project, include authemail and your application in INSTALLED_APPS. Set AUTH_USER_MODEL to the class of your user model. For example,

    AUTH_USER_MODEL = 'accounts.MyUser'

    INSTALLED_APPS = (
        ...
        #'south',        # Remove comment if you're using South for migrations.
        'rest_framework',
        'rest_framework.authtoken',
        'authemail',
        'accounts',
        ...
    )

In the admin.py file of your application, extend EmailUserAdmin to add your custom fields. For example,

    from django.contrib import admin
    from django.contrib.auth import get_user_model
    from authemail.admin import EmailUserAdmin

    class MyUserAdmin(EmailUserAdmin):
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            ('Personal Info', {'fields': ('first_name', 'last_name')}),
            ('Permissions', {'fields': ('is_active', 'is_staff', 
                                           'is_superuser', 'is_verified', 
                                           'groups', 'user_permissions')}),
            ('Important dates', {'fields': ('last_login', 'date_joined')}),
            ('Custom info', {'fields': ('date_of_birth',)}),
        )

    admin.site.unregister(get_user_model())
    admin.site.register(get_user_model(), MyUserAdmin)

Use one of the following steps to create the database tables:

  1. For Django >= 1.7, create the database tables with Django's makemigrations, migrate, and create a superuser with createsuperuser.
    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser
  1. For Django < 1.7, create the database tables with syncdb and South's migrate. Set up a superuser when prompted by syncdb. Convert your accounts application to South. You will receive an error message from South, so fake the initial migration as a workaround (see http://south.aeracode.org/ticket/1179).
    python manage.py syncdb
    python manage.py migrate
    python manage.py convert_to_south accounts
    python manage.py migrate accounts 0001 --fake
  1. To migrate from Django 1.6.X to 1.7, upgrade django-rest-authemail, uninstall south, and bring the migrations up-to-date with migrate.
    pip install --upgrade django-rest-authemail
    pip uninstall south
    python manage.py migrate

Check your setup by starting a Web server on your local machine:

    python manage.py runserver

Direct your browser to the Django /admin and log in.

    127.0.0.1:8000/admin

You should see Users, Groups, Password reset codes, Signup codes, and Tokens. If you click on Users, you should see your superuser account.

Add the authemail API endpoints to your project's urls.py file. For example,

    from accounts import views

    urlpatterns = [
        url(r'^admin/', include(admin.site.urls)),

        url(r'^api/accounts/', include('authemail.urls')),
    ]

When users signup or reset their password, they will be sent an email with a link and verification code. Include email settings as environment variables or in your project's settings.py file. See https://docs.djangoproject.com/en/dev/ref/settings/#email-host for more information. For example,

	# Email settings
	import os

	EMAIL_FROM = os.environ.get('AUTHEMAIL_DEFAULT_EMAIL_FROM') or '<YOUR DEFAULT_EMAIL_FROM HERE>'
	EMAIL_BCC = os.environ.get('AUTHEMAIL_DEFAULT_EMAIL_BCC') or '<YOUR DEFAULT_EMAIL_BCC HERE>'

	EMAIL_HOST = os.environ.get('AUTHEMAIL_EMAIL_HOST') or '<YOUR EMAIL_HOST HERE>'
	EMAIL_PORT = os.environ.get('AUTHEMAIL_EMAIL_PORT') or 0
	EMAIL_HOST_USER = os.environ.get('AUTHEMAIL_EMAIL_HOST_USER') or '<YOUR EMAIL_HOST_USER HERE>'
	EMAIL_HOST_PASSWORD = os.environ.get('AUTHEMAIL_EMAIL_HOST_PASSWORD') or '<YOUR EMAIL_HOST_PASSWORD HERE>'
	EMAIL_USE_TLS = True
	EMAIL_USE_SSL = False

	SERVER_EMAIL = os.environ.get('AUTHEMAIL_SERVER_EMAIL') or '<YOUR SERVER_EMAIL HERE>'

Try out authemail API calls by firing up python and using the authemail wrapper methods (runserver should still be executing). For example,

    python
    >>> from authemail import wrapper
    >>> account = wrapper.Authemail()
    >>> first_name = 'Your first name'
    >>> last_name = 'Your last name'
    >>> email = 'your_email@gmail.com'
    >>> password = 'Your password'
    >>> response = account.signup(first_name=first_name, last_name=last_name,
    ... email=email, password=password)

In the Django /admin, you should see a new user (not verified) and a new signup code. You should receive an email at your_email@gmail.com. Use the code in the email to verify your email address using the wrapper (normally, the link in the email would point to the front end, which would issue the signup verify request to the API):

    >>> code = '7f31e7a515df266532df4e00e0cf1967a7de7d17'
    >>> response = account.signup_verify(code=code)

In the Django /admin, the new user is now verified and the signup code is absent. The new user can now login and you can inspect the associated login token:

    >>> response = account.login(email=email, password=password)
    >>> account.token
    u'a84d062c1b60a36e6740eb60c6f9da8d1f709322'

You will find the same token for the user in the Token table in the Django /admin. Find out more information about the user (insert your token):

    >>> token = 'a84d062c1b60a36e6740eb60c6f9da8d1f709322'
    >>> response = account.users_me(token=token)
    >>> response
    {u'first_name': u'Your first name', u'last_name': u'Your last name', u'email': u'your_email@gmail.com'}

Use the authentication token to logout:

    >>> response = account.logout(token=token)
    >>> response
    {u'success': u'User logged out.'}

Play with password reset and change!

If you are having trouble getting your code to execute, or are just curious, try out the Django REST Framework Browsable API. If you type an authemail API endpoint into your browser, the Browsable API should appear (runserver should still be executing). For example,

    127.0.0.1/api/accounts/signup

In the Content: field of the Browsable API, type:

    {
        "first_name": "Your first name",
        "last_name": "Your last name",
        "email": "your_email@gmail.com",
        "password": "Your password"
    }

Then click on POST. You will either receive an error message to help in your debugging, or, if your signup was successful:

    {
        "first_name": "Your first name",
        "last_name": "Your last name",
        "email": "your_email@gmail.com",
    }

Try out the other authemail API endpoints with the Django REST Framework Browsable API.

Make authemail API calls with front end code. To get started, follow the steps in the README.md for the example_project. Enhance the Django code in the example_project or extend the concepts to React, AngularJS, iOS, and Android front ends.

When calling endpoints from the front end that require authentication (logout, password/change, and users/me), include the authorization token key in the HTTP header. For example,

    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

Here's an example using curl,

    curl -X GET 'http://127.0.0.1:8000/accounts/logout' \
         -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'

Authemail API Endpoints

For the endpoints that follow, the base path is shown as /api/accounts. This path is for example purposes. It can be customized in your project's urls.py file.

POST /api/accounts/signup

Call this endpoint to sign up a new user and send a verification email. Sample email templates are found in authemail/templates/authemail. To override the email templates, copy and modify the sample templates, or create your own, in your_app/templates/authemail.

Your front end should handle password confirmation, and if desired, require the visitor to input their first and last names.

Unverified users can sign up multiple times, but only the latest signup code will be active.

  • Payload

    • email (required)
    • password (required)
    • first_name (optional)
    • last_name (optional)
  • Possible responses

    201 (Created)
    Content-Type: application/json
    {
        "email": "amelia.earhart@boeing.com"
        "first_name": "Amelia", 
        "last_name": "Earhart", 
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "email": [
            "This field is required."
        ], 
        "password": [
            "This field is required."
        ] 
    }

    {
        "email": [
            "Enter a valid email address."
        ]
    }

    {
        "detail": "User with this Email address already exists."
    }

GET /api/accounts/signup/verify/?code=<code>

When the user clicks the link in the verification email, the front end should call this endpoint to verify the user.

  • Parameters

    • code (required)
  • Possible responses

    200 (OK)
    Content-Type: application/json
    {
        "success": "User verified."
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "detail": "Unable to verify user."
    }

POST /api/accounts/login

Call this endpoint to log in a user. Use the authentication token in future calls to identify the user.

  • Payload

    • email (required)
    • password (required)
  • Possible responses

    200 (OK)
    Content-Type: application/json
    {
        "token": "91ec67d093ded89e0a752f35188802c261899013"
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "password": [
            "This field is required."
        ], 
        "email": [
            "This field is required."
        ]
    }

    {
        "email": [
            "Enter a valid email address."
        ]
    }

    401 (Unauthorized)
    {
        "detail": "Authentication credentials were not provided."
    }

    {
        "detail": "Unable to login with provided credentials."
    }

GET /api/accounts/logout

Call this endpoint to log out an authenticated user.

  • HTTP Header
    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
  • Possible responses
    200 (OK)
    Content-Type: application/json
    {
        "success": "User logged out."
    }

    401 (Unauthorized)
    Content-Type: application/json
    {
        "detail": "Authentication credentials were not provided."
    }

    {
        "detail": "Invalid token"
    }

POST /api/accounts/password/reset

Call this endpoint to send an email to a user so they can reset their password. Similar to signup verification, the password reset email templates are found in authemail/templates/authemail. Override the default templates by placing your similarly-named templates in your_app/templates/authemail.

  • Payload

    • email (required)
  • Possible responses

    201 (Created)
    Content-Type: application/json
    {
        "email": "amelia.earhart@boeing.com"
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "email": [
            "This field is required."
        ]
    }

    {
        "email": [
            "Enter a valid email address."
        ]
    }

    {
        "detail": "Password reset not allowed."
    }

GET /api/accounts/password/reset/verify/?code=<code>

When the user clicks the link in the password reset email, call this endpoint to verify the password reset code.

  • Parameters

    • code (required)
  • Possible responses

    200 (OK)
    Content-Type: application/json
    {
        "success": "User verified."
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "password": [
            "This field is required."
        ] 
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "detail": "Unable to verify user."
    }

**POST /api/accounts/password/reset/verified**

Call this endpoint with the password reset code and the new password, to reset the user's password.  The front end should prompt the user for a confirmation password and give feedback if the passwords don't match.

- Payload

    - code (required)
    - password (required)

- Possible responses

```python
    200 (OK)
    Content-Type: application/json
    {
        "success": "Password reset."
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "password": [
            "This field is required."
        ] 
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "detail": "Unable to verify user."
    }

POST /api/accounts/password/change

Call this endpoint to change a user's password.

  • HTTP Header
    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
  • Payload

    • password (required)
  • Possible responses

    200 (OK)
    Content-Type: application/json
    {
        "success": "Password changed."
    }

    400 (Bad Request)
    Content-Type: application/json
    {
        "password": [
            "This field is required."
        ] 
    }

    401 (Unauthorized)
    Content-Type: application/json
    {
        "detail": "Authentication credentials were not provided."
    }

    {
        "detail": "Invalid token"
    }

GET /api/accounts/users/me

Call this endpoint after logging in and obtaining an authorization token to learn more about the user.

  • HTTP Header
    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
  • Possible responses
    200 (OK)
    Content-Type: application/json
    {
        "id": 1,
        "email": "amelia.earhart@boeing.com",
        "first_name": "Amelia",
        "last_name": "Earhart",
    }

    401 (Unauthorized)
    Content-Type: application/json
    {
        "detail": "Authentication credentials were not provided."
    }

    {
        "detail": "Invalid token"
    }

Wrapper

A wrapper is available to access the Authemail API with Python code. First create an instance of the Authemail class, then call methods to access the API. There is a one-to-one mapping between the endpoints and instance methods. For example,

    from authemail import wrapper

    account = wrapper.Authemail()
    response = account.signup(first_name=first_name, last_name=last_name,
        email=email, password=password)

    if 'detail' in response:
        # Handle error condition
    else:
        # Handle good response

See example_project/views.py for more sample usage.

Inspiration and Ideas

Inspiration and ideas for django-rest-authemail were derived from:

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-rest-authemail-1.7.0.tar.gz (41.1 kB view details)

Uploaded Source

Built Distribution

django_rest_authemail-1.7.0-py2.py3-none-any.whl (48.5 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-rest-authemail-1.7.0.tar.gz.

File metadata

  • Download URL: django-rest-authemail-1.7.0.tar.gz
  • Upload date:
  • Size: 41.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.1

File hashes

Hashes for django-rest-authemail-1.7.0.tar.gz
Algorithm Hash digest
SHA256 fbae50fa8e12036a4a4e06814fc885feef255c055ad5b9352c6fe27bdf3cfec9
MD5 66f61199053e4128840c1738466683cc
BLAKE2b-256 e7c56d4d8b26d1aff3b9ae03697fc714534d433f9abff201bd3c7dd6a9450c57

See more details on using hashes here.

File details

Details for the file django_rest_authemail-1.7.0-py2.py3-none-any.whl.

File metadata

  • Download URL: django_rest_authemail-1.7.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 48.5 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.1

File hashes

Hashes for django_rest_authemail-1.7.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 fa3c36bb4611d9854fb912f8c7c2e6085f4bf778fdbd2fcb39bfd96114076302
MD5 2d60bbf7e1bf61d265df8be10dca5f51
BLAKE2b-256 dc2cfee34ffcf9b9a2182f60a25fcc674e527652d8d89f2380cfb61aef24c265

See more details on using hashes here.

Supported by

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