django-stormpath

Stormpath integration for Django.


License
Apache-2.0
Install
pip install django-stormpath==1.1.0

Documentation

django-stormpath

Simple, scalable, user authentication for Django (powered by Stormpath).

stormpath Release stormpath Downloads stormpath-django Code Quality stormpath-django Build stormpath-django Coverage

Note

This is a beta release, if you run into any issues, please file a report on our Issue Tracker.

Meta

This library provides user account storage, authentication, and authorization with Stormpath.

This library works with Python 2.7.x and Python 3.3+. It supports Django versions 1.6+.

Note

This library will NOT work on Google App Engine due to incompatibilities with the requests package :(

Installation

To install the library, you'll need to use pip:

$ pip install django-stormpath

How it Works

django-stormpath provides an AUTHENTICATION_BACKEND which is used to communicate with the Stormpath REST API.

When a user tries to log in, and Stormpath is used as the authentication backend, django-stormpath always asks the Stormpath service if the user's credentials (username or email and password) are correct. Password hashes are always stored in Stormpath, and not locally.

If a user's credentials are valid, there are two possible scenarios:

  1. User doesn't exist in Django's database (PostgreSQL, MySQL, Oracle etc.). In this case, a user will be created in the local Django user database with their username, password, email, first name, and last name identical to the Stormpath user's. Then this user will be authenticated.
  2. User exists in Django's database. In this case, if a user's information has changed on Stormpath, the Django user's fields are updated accordingly. After this, the user will be authenticated.

Note

An account on Stormpath can be disabled, enabled, locked and unverified. When a user is created or updated, the is_active field is set to True if the Stormpath account is enabled and False otherwise. For a Stormpath user to be able to log into the Django admin interface it must specify the is_superuser and is_staff properties in the Stormpath Account's customData resource.

Usage

First, you need to add django_stormpath to your INSTALLED_APPS setting in settings.py:

INSTALLED_APPS = (
    # ...,
    'django_stormpath',
)

Next, you need to add the Stormpath backend into AUTHENTICATION_BACKENDS:

AUTHENTICATION_BACKENDS = (
    # ...
    'django_stormpath.backends.StormpathBackend',
)

After that's done, you'll also need to tell Django to use Stormpath's user model:

AUTH_USER_MODEL = 'django_stormpath.StormpathUser'

You can read more about how Django's custom user model works here <https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#specifying-a-custom-user-model> _.

Lastly, you need to specify your Stormpath credentials: your API key and secret, as well as your Stormpath Application URL.

For more information about these things, please see the official guide.

To specify your Stormpath credentials, you'll need to add the following settings to your settings.py:

STORMPATH_ID = 'yourApiKeyId'
STORMPATH_SECRET = 'yourApiKeySecret'
STORMPATH_APPLICATION = 'https://api.stormpath.com/v1/applications/YOUR_APP_UID_HERE'

Once this is done, you're ready to get started! The next thing you need to do is to sync your database and apply any migrations:

$ python manage.py migrate

And that's it! You're now ready to get started =)

Example: Creating a User

To pragmatically create a user, you can use the following code:

from django.contrib.auth import get_user_model

UserModel = get_user_model()
UserModel.objects.create(
    email = 'john.doe@example.com',
    given_name = 'John',
    surname = 'Doe',
    password = 'password123!'
)

The above example just calls the create_user method:

UserModel.objects.create_user('john.doe@example.com', 'John', 'Doe', 'Password123!')

To create a super user, you can use manage.py:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

This will set is_admin, is_staff and is_superuser to True on the newly created user. All extra parameters like the aforementioned flags are saved on Stormpath in the Accounts customData Resource and can be inspected outside of Django. This just calls the UserModel.objects.create_superuser method behind the scenes.

Once you're all set up you can use the StormpathUser model just as you would the normal django user model to form relationships within your models:

class Book(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)

Note

When doing the initial migrate call (or manage.py createsuperuser) an Account is also created on Stormpath. Every time the save method is called on the UserModel instance it is saved/updated on Stormpath as well. This includes working with the Django built-in admin interface.

ID Site

If you'd like to not worry about building your own registration and login screens at all, you can use Stormpath's new ID site feature. This is a hosted login subdomain which handles authentication for you automatically.

To make this work in Django, you need to specify a few settings:

AUTHENTICATION_BACKENDS = (
    # ...
    'django_stormpath.backends.StormpathIdSiteBackend',
)

# This should be set to the same URI you've specified in your Stormpath ID
# Site dashboard.  NOTE: This URL must be *exactly* the same as the one in
# your Stormpath ID Site dashboard (under the Authorized Redirect URLs input
# box).
STORMPATH_ID_SITE_CALLBACK_URI = 'http://localhost:8000/handle-callback/stormpath/

# The URL you'd like to redirect users to after they've successfully logged
# into their account.
LOGIN_REDIRECT_URL = '/redirect/here'

Lastly, you've got to include some URLs in your main urls.py as well:

url(r'', include('django_stormpath.urls')),

An example of how to use the available URL mappings can be found here.

Social Login

Django Stormpath supports social login as well. Currently supported Providers are: Google, Github, Linkedin and Facebook. First thing that you need to do is add StormpathSocialBackend to the list of allowed authentication backends in your settings file:

AUTHENTICATION_BACKENDS = (
    # ...
    'django_stormpath.backends.StormpathSocialBackend',
)

After that you can enable each provider with the following settings:

STORMPATH_ENABLE_GOOGLE = True
STORMPATH_ENABLE_FACEBOOK = True
STORMPATH_ENABLE_GITHUB = True
STORMPATH_ENABLE_LINKEDIN = True

STORMPATH_SOCIAL = {
        'GOOGLE': {
            'client_id': os.environ['GOOGLE_CLIENT_ID'],
            'client_secret': os.environ['GOOGLE_CLIENT_SECRET'],
        },
        'FACEBOOK': {
            'client_id': os.environ['FACEBOOK_CLIENT_ID'],
            'client_secret': os.environ['FACEBOOK_CLIENT_SECRET']
        },
        'GITHUB': {
            'client_id': os.environ['GITHUB_CLIENT_ID'],
            'client_secret': os.environ['GITHUB_CLIENT_SECRET']
        },
        'LINKEDIN': {
            'client_id': os.environ['LINKEDIN_CLIENT_ID'],
            'client_secret': os.environ['LINKEDIN_CLIENT_SECRET']
        },
}

And that's it! Now if you navigate to "https://yourdjangoapp.com/social-login/google/" for each provider respectively, you will be redirected to that provider for authentication. If you are authenticated succesffully you will be redirected back to your django app and logged in automatically. Stormpath django also creates a directory for each social provider automatically so you don't need to worry about it.

Note

Please note that the callback URL's for each provider are listed in django stormpath's urls.py file. You will need to use these callback urls and set them as redirect URI's when configuring each provider in their respecive dashboards. For intance the callback URL for Google is: "https://yourdjangoapp.com/social-login/google/callback".

Note

Note that for OAuth2 to work we need to be using HTTPS. For django to work correctly with HTTPS please set the following settings:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True

Caching

The best kind of websites are fast websites. Django-Stormpath includes built-in support for caching. You can currently use either:

All can be easily configured using configuration variables.

There are several configuration settings you can specify to control caching behavior. You need to add the STORMPATH_CACHE_OPTIONS to your Django project's settings file.

Here's an example which shows how to enable caching with redis:

 from stormpath.cache.redis_store import RedisStore

 STORMPATH_CACHE_OPTIONS = {
    'store': RedisStore,
    'store_opts': {
        'host': 'localhost',
        'port': 6379
    }
}

Here's an example which shows how to enable caching with memcached:

from stormpath.cache.memcached_store import MemcachedStore

STORMPATH_CACHE_OPTIONS = {
   'store': MemcachedStore,
   'store_opts': {
       'host': 'localhost',
       'port': 11211
   }
}

If no cache is specified, the default, MemoryStore, is used. This will cache all resources in local memory.

For a full list of options available for each cache backend, please see the official Caching Docs in our Python library.

Copyright and License

Copyright &copy; 2014 Stormpath, inc. You may use and/or modify this library under the terms of Apache License version 2.0. Please see the LICENSE file for details.

Change Log

All library changes, in descending order.

Version 1.1.0

Released August 12, 2016.

  • Dropping Python 3.3 support since Django doesn't support it in 1.10.
  • Supporting Python 3.5.
  • Dropping support for Django 1.6 / 1.7, since they are EOL by Django.
  • Fixing broken tests.
  • Adding coverage reporting.
  • Renaming management task sync_account -> sync_accounts_from_stormpath.
  • Adding option to sync_accounts_from_stormpath to sync Stormpath Groups in addition to accounts.
  • Various code cleanup.

Version 1.0.7

Released August 10, 2016.

  • Supporting new Django management command: sync_accounts`. This will synchronize all remote Stormpath Accounts with the local Django database. This helps developers keep things in sync (like in the Django admin). Thanks to Peter Novotnak for the PR!
  • Fixing some old, incorrect setup docs.

Version 1.0.6

Released February 18, 2016.

  • Version bump for Stormpath dependency.
  • Fixing error handling issues which now work better with underlying Python library fixes.
  • Refactoring our ID site callback handling to use our new Python bindings.

Version 1.0.5

Released November 13, 2015.

  • Version bump for Stormpath dependency.

Version 1.0.4

Released November 2, 2015.

  • Removing Python 3.2 support. Nobody uses it (buggy release).
  • Raising a proper DoesNotExist exception when a Resource 404 is returned from the Stormpath API.
  • Updating docs to reflect what versions of Django we support (1.6+).
  • Allowing users to update a user's password by working around the data mirroring issue with Django.
  • Supporting the check_password Django API, thanks to an awesome pull request from smcoll.
  • Fixing email verification bug.
  • Adding get-or-create support.
  • Updating stormpath dependency.

Version 1.0.3

Released on June 18, 2015.

  • Updating ID site docs slightly.
  • Fixing Travis CI builds.
  • Upgrading to the latest Stormpath release.

Version 1.0.2

Released on May 12, 2015.

  • Improving Travis CI builds so that tests are run against Django 1.6.x, 1.7.x, and 1.8.x. This will help flush out Django version issues (hopefully!).
  • Fixing old migration issue. This should make all new migrate commands run successfully regardless of database used.
  • Supporting User.first_name and User.last_name per Django's conventions. This makes our user model play nice with third party Django apps =)

Version 1.0.1

Released on April 30, 2015.

  • Adding missing migrations. This fixes issues when running migrate on a new Postgres database.
  • Making the built-in delete() method remove both copies of the account.

Version 1.0.0

Released on April 18, 2015.

  • Fixing issue with StormpathPermissionsMixin by replacing it with the built-in PermissionsMixin that Django provides. Thanks again, @davidmarquis!
  • The above change is a breaking change -- so users of earlier versions of django-stormpath are encouraged to stay on their current release unless they want to manually handle the database migrations. This breakage is very rare for our libraries, but was necessary in this case to fix the underlying library issues.
  • Updating broken test case for the new release.

Version 0.0.7

Released on April 15, 2015.

  • Fixing documentation issue in the README -- we had an incorrect code sample setting up urlpatterns. Thanks @espenak for the find!
  • Adding a StormpathUserManager.delete() method. This makes it possible to 'cleanly' delete users from both Django and Stormpath.
  • Fixing Group permission editing. Thanks @davidmarquis!
  • Fixing bug with maintaining the username field when editing user objects. Thanks again, @davidmarquis!
  • Adding in missing dependency: requests_oauthlib. This is required for our ID site functionality to work, but was missing.

Version 0.0.6

Released on February 11, 2015.

  • PEP-8 fixing imports, and making things python 3 compatible (thanks @rtrajano)!

Version 0.0.5

Released on February 5, 2015.

  • Adding support for social login.
  • Various test fixes.
  • PEP-8.

Version 0.0.4

Released on January 19, 2015.

  • Fixing incompatible arguments being passed from django-rest-framework-jwt to StormpathBackend.authenticate().
  • Changing unexpected behaviors (no return value) of StormpathuserManager.create().

All fixes thanks to @skolsuper!

Version 0.0.3

Released on December 9, 2014.

  • Adding cache support.
  • Fixing docs.
  • Adding docs on caching.
  • Adding support for ID site.

Version 0.0.2

Released on November 26, 2014.

  • Fixing README stuff :(

Version 0.0.1

Released on November 26, 2014.

  • First release!