Simple, scalable, user authentication for Django (powered by Stormpath).
Note
This is a beta release, if you run into any issues, please file a report on our Issue Tracker.
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 :(
To install the library, you'll need to use pip:
$ pip install django-stormpath
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:
- 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.
- 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.
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'
If you have custom fields in you user model, you can update it while sign up or sign in by defining STORMPATH_RETRIEVE_SOCIAL_CUSTOM_DATA variable like this:
STORMPATH_RETRIEVE_SOCIAL_CUSTOM_DATA = {
'facebook': "users.utils.retrieve_custom_data_facebook"
}
Where users.utils.retrieve_custom_data_facebook is a function that return dict. Key is the field name with django prefix, and value is the field. This function Will be responsible for connecting to the provider and process the data.
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:
$ # NOTE: python manage.py syncdb is not required if you're using a newer
# version of Django
$ python manage.py syncdb
$ python manage.py migrate
And that's it! You're now ready to get started =)
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 = '[email protected]',
given_name = 'John',
surname = 'Doe',
password = 'password123!'
)
The above example just calls the create_user
method:
UserModel.objects.create_user('[email protected]', 'John', 'Doe', 'Password123!')
To create a super user, you can use manage.py
:
$ python manage.py createsuperuser --username=joe [email protected]
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 syncdb
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.
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.
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
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 © 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.
All library changes, in descending order.
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.
Released November 13, 2015.
- Version bump for Stormpath dependency.
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.
Released on June 18, 2015.
- Updating ID site docs slightly.
- Fixing Travis CI builds.
- Upgrading to the latest Stormpath release.
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
syncdb
commands run successfully regardless of database used. - Supporting
User.first_name
andUser.last_name
per Django's conventions. This makes our user model play nice with third party Django apps =)
Released on April 30, 2015.
- Adding missing migrations. This fixes issues when running
syncdb
on a new Postgres database. - Making the built-in
delete()
method remove both copies of the account.
Released on April 18, 2015.
- Fixing issue with
StormpathPermissionsMixin
by replacing it with the built-inPermissionsMixin
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.
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.
Released on February 11, 2015.
- PEP-8 fixing imports, and making things python 3 compatible (thanks @rtrajano)!
Released on February 5, 2015.
- Adding support for social login.
- Various test fixes.
- PEP-8.
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!
Released on December 9, 2014.
- Adding cache support.
- Fixing docs.
- Adding docs on caching.
- Adding support for ID site.
Released on November 26, 2014.
- Fixing README stuff :(
Released on November 26, 2014.
- First release!