django-all-access¶
django-all-access is a reusable application for user registration and authentication from OAuth 1.0 and OAuth 2.0 providers such as Twitter and Facebook.
The goal of this project is to make it easy to create your own workflows for authenticating with these remote APIs. django-all-access will provide the simple views with sane defaults along with hooks to override the default behavior.
You can find a basic demo application running at http://django-all-access.mlavin.org/
Features¶
- Sane and secure defaults for OAuth authentication
- Easy customization through class-based views
- Built on the amazing requests library
Installation¶
It is easiest to install django-all-access from PyPi using pip:
pip install django-all-access
django-all-access requires Python 2.7 or 3.3+ along with the following Python packages:
django>=1.8
pycrypto>=2.4
requests>=2.0
requests_oauthlib>=0.4.2
oauthlib>=0.6.2
Documentation¶
Additional documentation on using django-all-access is available on Read The Docs.
License¶
django-all-access is released under the BSD License. See the LICENSE file for more details.
Contributing¶
If you have questions about using django-all-access or want to follow updates about the project you can join the mailing list through Google Groups.
If you think you’ve found a bug or are interested in contributing to this project check out django-all-access on Github.
Contents¶
Getting Started¶
Below are the basic steps need to get django-all-access integrated into your Django project.
Configure Settings¶
You need to add allaccess
to your installed apps as well as include an
additional authentication backend in your project settings. django-all-access requires
django.contrib.auth
, django.contrib.sessions
and django.contrib.messages
which are enabled in Django by default. django.contrib.admin
is recommended
for managing the set of providers, but is not required.
INSTALLED_APPS = (
# Required contrib apps
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
# Optional
'django.contrib.admin',
# Other installed apps would go here
'allaccess',
)
AUTHENTICATION_BACKENDS = (
# Default backend
'django.contrib.auth.backends.ModelBackend',
# Additional backend
'allaccess.backends.AuthorizedServiceBackend',
)
Note that AUTHENTICATION_BACKENDS
is not included in the default settings
created by startproject
. If you want to continue to use the default
username/password based authentication, you should be sure to include
django.contrib.auth.backends.ModelBackend
in this setting.
By default, django-all-access uses the built-in Django settings LOGIN_URL
and
LOGIN_REDIRECT_URL
. You should be sure that these are set to valid URLs for
your site.
Configure Urls¶
To use the default redirect and callback views, you should include them in your root URL configuration.
from django.conf.urls import include
urlpatterns = [
# Other URL patterns would go here
url(r'^accounts/', include('allaccess.urls')),
]
This makes the login URL for a particular provider /accounts/login/<provider>/
,
such as /accounts/login/twitter/
or /accounts/login/facebook/
. Once the user
has authenticated with the remote provider, they will be sent back to
/accounts/callback/<provider>/
, such as /accounts/callback/twitter/
or /accounts/callback/facebook/
.
Create Database Tables¶
You’ll need to create the necessary database tables for storing OAuth providers and
user associations with those providers. This is done with the migrate
management
command built into Django:
python manage.py migrate allaccess
Next Steps¶
At this point your project is configured to use the default django-all-access authentication, but no providers have been added. Continue reading to learn how to add providers for your project.
Configuring Providers¶
django-all-access configures and stores the set of OAuth providers in the database. To enable your users to authenticate with a particular provider, you will need to add the OAuth API URLs as well as your application’s consumer key and consumer secret. The process of registering your application with each provider will vary and you should refer to the provider’s API documentation for more information.
Note
While the consumer key/secret pairs are stored in the database
as opposed to putting them in the settings file, they are encrypted using the
AES specification.
Since this is a symmetric-key encryption the key/secret pairs can still be read
if the encryption key is compromised. In this case django-all-access uses a
key based on the standard SECRET_KEY
setting. You should take care to keep
this setting secret as its name would imply.
Common Providers¶
To get you started, there is an initial fixture of commonly used providers. This includes
the URLs needed for Facebook, Twitter, Google, Microsoft Live, Github and Bitbucket. Once you’ve
added allaccess
to your INSTALLED_APP
and created the tables with migrate
,
you can load this fixture via:
python manage.py loaddata common_providers.json
This does not include the consumer id/key or secret which will still need to be added to the records. The below examples will help you understand what these values mean and how they would be populated for additional providers you might want to use.
OAuth 1.0 Providers¶
OAuth 1.0 Protocol is defined by RFC 5849. It is sometimes referred to as 3-Legged OAuth due to the number of requests between the provider and consumer.
To enable an OAuth provider, you should add a Provider
record with the necessary
request_token_url
, authorization_url
and access_token_url
as defined
by the protocol. The provider’s API documentation should detail these for you. You
will also need to define a profile_url
which is the API endpoint for requesting
the currently authenticated user’s profile information. You will also need to
register for a key/secret pair from the provider.
This protocol is implemented by a number of providers. These providers include Twitter, Netflix, Yahoo, Linkedin, Flickr, Bitbucket, and Dropbox. Additional providers can be found on the OAuth.net Wiki.
Twitter Example¶
Twitter is a popular social website which provides a REST API with OAuth 1.0
authentication. If you wanted to enable Twitter authentication on your website
using django-all-access, you would create the following Provider
record:
name: twitter
request_token_url: https://api.twitter.com/oauth/request_token
authorization_url: https://api.twitter.com/oauth/authenticate
access_token_url: https://api.twitter.com/oauth/access_token
profile_url: https://api.twitter.com/1.1/account/verify_credentials.json
After adding your consumer key and secret to this record you should now be able
to authenticate with Twitter by visiting /accounts/login/twitter/
.
You can find more information on the Twitter API on their developer site.
OAuth 2.0 Providers¶
Unlike OAuth 1.0, OAuth 2.0 is only a working draft and not an official standard. In many ways it is much simpler than its predecessor. It is often referred to as 2-Legged OAuth because it removes the need for the request token step.
To enable an OAuth provider, you should add a Provider
record with the necessary
authorization_url
and access_token_url
as defined by the protocol.
The provider’s API documentation should detail these for you. You
will also need to define a profile_url
which is the API endpoint for requesting
the currently authenticated user’s profile information. You will also need to
register for a key/secret pair from the provider.
Providers which implement the OAuth 2.0 protocol include Facebook, Google, FourSquare, Meetup, Github, and Yammer.
Facebook Example¶
Facebook is a large social network which provides a REST API with OAuth 2.0
authentication. The below Provider
record will enable Facebook authentication:
name: facebook
authorization_url: https://www.facebook.com/v2.8/dialog/oauth
access_token_url: https://graph.facebook.com/v2.8/oauth/access_token
profile_url: https://graph.facebook.com/v2.8/me
As you can see, the request_token_url
is not included because it is not needed.
After adding your consumer key and secret to this record you should now be able
to authenticate with Facebook by visiting /accounts/login/facebook/
.
Facebook also has developer docs
for additional information on using their API.
Note
Facebook began using the version number in the URL as part of their 2.0 API. Since then very little has changed with regard to the OAuth flow but the version number is now required. The latest version of the API might not match the documentation here. For the most up to date info on the Facebook API you should consult their API docs.
Customizing Redirects and Callbacks¶
django-all-access provides default views/urls for authentication. These are built from Django’s class based views making them easy to extend or override the default behavior in your project.
OAuthRedirect View¶
The initial step for authenticating with any OAuth provider is redirecting the
user to the provider’s website. The OAuthRedirect
view extends from the
RedirectView
By default it is mapped to the allaccess-login
URL name. This view takes one
keyword argument from the URL pattern provider
which corresponds to the Provider.name
for an enabled provider. If no enabled provider is found for the name, this view
will return a 404.
-
class
OAuthRedirect
¶ -
client_class
¶ Used to change the
BaseOAuthClient
used by the view. SeeOAuthRedirect.get_client()
for more details.
New in version 0.8.
-
params
¶ Used to pass additional parameters to the authorization redirect (i.e.
scope
requests). SeeOAuthRedirect.get_additional_parameters()
for more details.
-
get_client
(provider)¶ Here you can override the OAuth client class which is used to generate the redirect URL. Another use case is to disable the enforcement of the OAuth 2.0
state
parameter for providers which don’t support it. If you are using the view for a single provider, it would be easiest to set theOAuthRedirect.client_class
attribute on the class instead.You should be sure to use the same client class for the callback view as well.
-
get_redirect_url
(**kwargs)¶ This method is originally defined by the RedirectView. The redirect URL is constructed from the
Provider.authorization_url
along with the necessary parameters to match the OAuth specifications. You should not need to override this method in your application.
-
get_additional_parameters
(provider)¶ Here you can return additional parameters for the authorization request. By default this returns
{}
. A common usage for overriding this method is to request additional permissions for the authorization. There is no standard for additional permissions in the OAuth 1.0 specification. For an OAuth 2.0 provider this is done with thescope
parameter.
-
get_callback_url
(provider)¶ This returns the URL which the remote provider should return the user after authentication. It is called by
OAuthRedirect.get_redirect_url()
to construct the appropriate redirect URL. By default the reverses theallaccess-callback
URL name with the passed provider name.You may want to override this method in your application if you wish to have a custom callback for a given provider, a different callback for login vs registration, or a different callback for an authenticated user associating a new provider with their account.
-
OAuthCallback View¶
After the user has authenticated with the remote provider or denied access to your application
request, they are returned to the callback specifed in the initial redirect. OAuthCallback
defines the default behaviour on this callback. This view extends from the base
View class.
By default it is mapped to the allaccess-callback
URL name. Similar to the OAuthRedirect
view,
this view takes one keyword argument provider
which corresponds to the Provider.name
for an enabled provider. If no enabled provider is found for the name, this view will return a 404.
-
class
OAuthCallback
¶ -
client_class
¶ Used to change the
BaseOAuthClient
used by the view. SeeOAuthCallback.get_client()
for more details.
New in version 0.8.
-
provider_id
¶ Used to customize how the user identifier is found from the user profile response from the provider. If the provider response includes a nested response then this value can include a dotted path to the id value.
For example if the response is {‘result’: {‘user’: {‘id’: ‘XXX’}}} then you can set this attribute to result.user.id to access the value. See
OAuthCallback.get_user_id()
for more details.
-
get_callback_url
(provider)¶ This returns the callback URL specified in the initial redirect if it is different than the current
request.path
. By default the callback URL will be the same and this view will returnNone
. You will most likely not need to change this in your project.
-
get_client
(provider)¶ Here you can override the OAuth client class which is used to fetch the access token and user information. Another use case is to disable the enforcement of the OAuth 2.0
state
parameter for providers which don’t support it. If you are using the view for a single provider, it would be easiest to set theOAuthCallback.client_class
attribute on the class instead.You should be sure to use the same client class for the redirect view as well.
-
get_error_redirect
(provider, reason)¶ Returns the URL to send the user in the case of an authentication failure. The
reason
is a brief text description of the problem. By default this will return the user to the original login URL as defined by theLOGIN_URL
setting.
-
get_login_redirect
(provider, user, access, new=False)¶ You can use this to customize the URL to send the user on a successful authentication. By default this will be the
LOGIN_REDIRECT_URL
setting. Thenew
parameter is there to indicate if this was a newly created or a previously existing user.
-
get_or_create_user
(provider, access, info)¶ This method is used by
OAuthCallback.handle_new_user()
to construct a new user with a random username, no email and an unusable password. You may want to override this user to complete more of their infomation or attempt to match them to an existing user by either their username or email.OAuthCallback.handle_new_user()
will connect the user to theaccess
record and does not need to be handled here.Note: If you are using Django 1.5 support for a custom User model, you should override this method to ensure the user is created correctly.
-
get_user_id
(provider, info)¶ This method should return the unique identifier from the profile information. If the id cannot be determined, this should return
None
. Theinfo
parameter will be the parsed JSON response from the user’s profile. If the response wasn’t JSON, it will be the plain text response. By default this looks for a keyid
in the JSON dictionary. This will work for a number of providers, but will need to be changed to fit more complex response structures.You can customize how this lookup is done by setting the
OAuthCallback.provider_id
. This can be done either in the class definition or when calling .as_view.
-
handle_existing_user
(provider, user, access, info)¶ At this point the
user
has been authenticated via theiraccess
model with this provider, but they have not been logged in. This method will login the user and redirect them to the URL returned byOAuthCallback.get_login_redirect()
withnew=False
.The user’s profile info is passed to this method to allow for updating their data from their provider profile, but this is not done by default.
-
handle_login_failure
(provider, reason)¶ In the case of a failure to fetch the user’s access token or remote profile information or determine their id from that info, this method will be called. It attachs a brief error message to the request via
contrib.messages
and redirects the user to the result of theOAuthCallback.get_error_redirect()
method. You should override this function to add any additional logging or handling.
-
handle_new_user
(provider, access, info)¶ If the user could not be matched to an existing
AccountAccess
record for this provider or that record did not contain a user, this method will be called. At this point theaccess
record has already been saved but is not tied to a user. This will callOAuthCallback.get_or_create_user()
to construct a new user record. The user is then logged in and redirected to the result of theOAuthCallback.get_login_redirect()
call withnew=True
You may want to override this user to complete more of their infomation or attempt to match them to an existing user by either their username or email. You may want to override this to redirect them without creating a new user in order to have them complete another registration form (i.e. pick a username or provide an email if not returned by the provider).
-
Customization in URLs¶
For some minor customizations to the redirects and callbacks, it’s possible to
handle that in the URL inclusion rather than by creating a subclass of the view.
The most common customizations are adding additional scope on the redirect
and changing how the provider identifier is found on the callback. Below is an example
urls.py
which handles both of these cases.
from django.conf.urls import include, url
from allaccess.views import OAuthRedirect, OAuthCallback
urlpatterns = [
# Customize Facebook redirect to request additional scope
url(r'^accounts/login/(?P<provider>facebook)/$',
OAuthRedirect.as_view(params={'scope': 'email'})),
# Customize Foursqaure callback to handle nested response
url(r'^accounts/callback/(?P<provider>foursquare)/$',
OAuthCallback.as_view(provider_id='response.user.id')),
# All other provider cases are handled by the defaults
url(r'^accounts/', include('allaccess.urls')),
]
Additional Scope Example¶
As noted above, the default OAuthRedirect
redirect does not request any additional
permissions from the provider. It is recommended by most providers that you limit
the number of additional permissions that you request. The user will see the list
of permissions you are requesting and if they see a long list of permissions they
may decline the authorization. The below example shows how you can request
additional parameters for various providers.
from allaccess.views import OAuthRedirect
class AdditionalPermissionsRedirect(OAuthRedirect):
def get_additional_parameters(self, provider):
if provider.name == 'facebook':
# Request permission to see user's email
return {'scope': 'email'}
if provider.name == 'google':
# Request permission to see user's profile and email
perms = ['userinfo.email', 'userinfo.profile']
scope = ' '.join(['https://www.googleapis.com/auth/' + p for p in perms])
return {'scope': scope}
return super(AdditionalPermissionsRedirect, self).get_additional_parameters(provider)
This would be used instead of the default OAuthRedirect
for the allaccess-login
URL.
Remember that this logic can be based on the provider or even the current request. That
would allow your project to A/B test requesting more or less permissions to see its
impact on user registrations.
Additional Accounts Example¶
You may want to allow a user to associate their account on your website with multiple providers. This example will show a basic outline of how you can customize these views for that purpose.
First we will define a new callback which will associate the provider with the current user rather than creating a new user. This view will also have to handle the case that another user is associated with the new provider. For this the view will just return an error.
from allaccess.views import OAuthCallback
class AssociateCallback(OAuthCallback):
def get_or_create_user(self, provider, access, info):
return self.request.user
def handle_existing_user(self, provider, user, access, info):
if user != self.request.user:
return self.handle_login_failure(provider, "Another user is associated with this account")
# User was already associated with this account
return super(AssociateCallback, self).handle_existing_user(provider, user, access, info)
This view will require authentication which is handled in the URL pattern. There are multiple methods for decorating class based views which are detailed in the Django docs.
Next we will need a redirect view to send the user to this callback. This view will also require that the user already be authenticated which can be handled in the URL pattern.
from django.core.urlresolvers import reverse
from allaccess.views import OAuthRedirect
class AssociateRedirect(OAuthRedirect):
def get_callback_url(self, provider):
return reverse('associate-callback', kwargs={'provider': provider.name})
This assumes that we named the pattern for the above callback associate-callback
. An
example set of URL patterns is given below.
from django.contrib.auth.decorators import login_required
from .views import AssociateRedirect, AssociateCallback
urlpatterns = [
url(r'^associate/(?P<provider>(\w|-)+)/$', login_required(AssociateRedirect.as_view()), name='associate'),
url(r'^associate-callback/(?P<provider>(\w|-)+)/$', login_required(AssociateCallback.as_view()), name='associate-callback'),
]
That is the basic outline of how you would allow multiple account associations. This could be further customized using the hooks described earlier.
Additional API Calls¶
django-all-access requests the user’s access token and fetches their profile information during the authentication process. If you want to make additional API calls on behalf of the user, it is easy to do and you have the full power of the python-requests library.
Getting the API¶
You can access the API client through the AccountAccess.api_client
property.
This will return either a OAuthClient
or OAuth2Client
based on the
provider. API requests can be made using either the BaseOAuthClient.request()
method. This takes
the HTTP method as the first parameter and the URL as the second. An example for the
Twitter API is given below:
from allaccess.views import OAuthCallback
class NewTweetCallback(OAuthCallback):
def get_login_redirect(self, provider, user, access, new=False):
"Send a tweet for new Twitter users."
if new and provider.name == 'twitter':
api = access.api_client
url = 'https://api.twitter.com/1/statuses/update.json'
data = {'status': 'I just joined an awesome new site!'}
response = api.request('post', url, data=data)
# Check for errors in the response?
return super(NewTweetCallback, self).get_login_redirect(provider, user, access, new)
This assumes that you have requested sufficient permissions to tweet on behalf of the
user. While this example is done in the callback, you can access the API client at
any time by querying the AccountAccess
table. There is a catch in that the
access token from the provider might have been revoked by the user or expired.
You should refer to the provider’s API documentation for information regarding
available endpoints and the access token expiration.
The BaseOAuthClient.request()
method is a thin wrapper around the underlying
python-requests
library which sets up the appropriate authenication for OAuth 1.0 or OAuth 2.0. For
more information on additional hooks available, you should refer to the python-requests
documentation.
API Client¶
The OAuthClient
or OAuth2Client
classes define methods centered around OAuth
specifications and the authentication and registration workflow. The common methods
are defined in a BaseOAuthClient
. If you are going to extend the client for
a particular provider, it is recommended that you extend the appropriate OAuth 1.0 or
2.0 client rather than the BaseOAuthClient
.
-
class
BaseOAuthClient
¶ -
__init__
(provider, token='')¶ The client classes are created with an associated provider model record. The provider is used to provide the necessary URL (request token, access token, profile URL) information to the client.
-
get_access_token
(request, callback=None)¶ Used to fetch the access token from the callback URL. Unless you are familiar with the OAuth specifications, it is not recommended that you override this method.
-
get_profile_info
(raw_token)¶ Fetches and parses the profile information from the provider’s profile URL. This assumes that the response is JSON. If not, you may need to override this method.
-
get_redirect_args
(request, callback)¶ Builds the necessary query string parameters for the initial redirect based on the OAuth specification. Additional parameters are better added using
OAuthRedirect.get_additional_parameters()
. Unless you are familiar with the OAuth specifications, it is not recommended that you override this method.
-
get_redirect_url
(request, callback)¶ Builds the appropriate OAuth callback URL based on the provider information and the result of
BaseOAuthClient.get_redirect_args()
. Unless you are familiar with the OAuth specifications, it is not recommended that you override this method.
-
parse_raw_token
(raw_token)¶ Parses the token (key, secret) information from the raw token response.
-
request
(method, url, **kwargs)¶ A thin wrapper around
python-requests
, this also sets up the appropriate authentication headers/parameters.
-
session_key
¶ Returns a key for storing information in the user’s session. For OAuth 1.0 this would be used to store the request token information. For OAuth 2.0 this is used for enforcing the
state
parameter.
-
Beyond the methods above, the OAuthClient
also defines the below methods.
-
class
OAuthClient
¶ -
get_request_token
(request, callback)¶ Retrieves the request token prior to the initial redirect to the provider. This is stored in the session using the
BaseOAuthClient.session_key
which is unique per provider. Unless you are familiar with the OAuth 1.0 specification, it is not recommended that you override this method.
-
OAuth2Client
extends BaseOAuthClient
to include these additional methods.
-
class
OAuth2Client
¶ -
check_application_state
(request, callback)¶ On the callback this method is called to enforce the use of the
state
parameter. The use ofstate
is optional in the OAuth 2.0 spec but it is recommended and enforced by default by django-all-access. If you do not want to enforce the use ofstate
, you should overrideOAuth2Client.get_application_state()
and leave this method alone.
-
get_application_state
(request, callback)¶ Prior to the redirect, this method is used to generate a random
state
parameter which is stored in the session based on theBaseOAuthClient.session_key
. By default it generates a secure random 32 character string. If you wish to make it longer you can override this method. If you do not want to enforce thestate
parameter or the provider you are using does not allow it, you can override this to returnNone
.
-
Contributing Guide¶
There are a number of ways to contribute to django-all-access. If you are interested in making django-all-access better then this guide will help you find a way to contribute.
Ways to Contribute¶
Not all contributions are source code related. You can contribute to the project by writing a blog post on using django-all-access and sharing with the mailing list. You can also submit bug reports, feature requests or documentation updates through the Github issues.
Getting the Source¶
You can clone the repository from Github:
git clone git://github.com/mlavin/django-all-access.git
However this checkout will be read only. If you want to contribute code you should create a fork and clone your fork. You can then add the main repository as a remote:
git clone git@github.com:<your-username>/django-all-access.git
git remote add upstream git://github.com/mlavin/django-all-access.git
git fetch upstream
Running the Tests¶
When making changes to the code, either fixing bugs or adding features, you’ll want to run the tests to ensure that you have not broken any of the existing functionality. With the code checked out and Django installed you can run the tests via:
python setup.py test
or:
python runtests.py
Note that the tests require the mock library.
To test against multiple versions of Django you can use install and use tox>=1.4
. The
tox
command will run the tests against the currently supported Python and Django versions.
# Build all environments tox # Build a single environment tox -e py27-django18-normal
Building all environments will also build the documentation. More on that in the next section.
Building the Documentation¶
This project aims to have a minimal core with hooks for customization. That makes documentation an important part of the project. Useful examples and notes on common use cases are a great way to contribute and improve the documentation.
The docs are written in ReST and built using Sphinx. As noted above, you can use tox to build the documentation or you can build them on their own via:
tox -e docs
or:
make html
from inside the docs/
directory.
Coding Standards¶
Code contributions should follow the PEP8 and Django contributing style standards. Please note that these are only guidelines. Overall code consistency and readability are more important than strict adherence to these guides.
Submitting a Pull Request¶
The easiest way to contribute code or documentation changes is through a pull request. For information on submitting a pull request you can read the Github help page https://help.github.com/articles/using-pull-requests.
Pull requests are a place for the code to be reviewed before it is merged. This review will go over the coding style as well as if it solves the problem intended and fits in the scope of the project. It may be a long discussion or it might just be a simple thank you.
Not necessarily every request will be merged but you should not take it personally if your change is not accepted. If you want to increase the chances of your change being incorporated, here are some tips.
- Address a known issue. Preference is given to a request that fixes a currently open issue.
- Include documentation and tests when appropriate. New features should be tested and documented. Bugfixes should include tests which demonstrate the problem.
- Keep it simple. It’s difficult to review a large block of code, so try to keep the scope of the change small.
If you aren’t sure if a particular change is a good idea, or if it would be helpful to other users, just ask. You should also feel free to ask for help writing tests or writing documentation if you aren’t sure how to go about it.
Release History¶
Release and change history for django-all-access
v0.9.0 (2016-11-12)¶
Encrypted fields for storing the provider configurations and access tokens now sign the values after encryption to dectect if the key is valid before attempting to decrypt. This was added thanks to Florian Demmer (@fdemmer).
Other small changes include:
- Added Django 1.10 and Python 3.5 to the test suite coverage.
- Updated documentation on Facebook version numbers.
- Update provider fixtures to include the latest version number for Facebook.
v0.8.0 (2016-01-23)¶
Minor clean up release which drops support for outdated versions of Django. As such it also removes the old South migrations and the commands related to django-social-auth.
- Added support for additional parameters in the redirect view.
- Added support for more complex id lookups in the callback view.
- Additional documentation examples for customizing the views.
- Added support for Django 1.9.
- Tracking code coverage reports with Codecov.io.
Backwards Incompatible Changes¶
- Python 3.2 is no longer officially supported or tested.
- Django < 1.8 is no longer officially supported or tested.
- requests_oauthlib < 0.4.2 is no longer officially supported.
migrate_social_accounts
andmigrate_social_accounts
commands have been removed.
v0.7.2 (2015-05-13)¶
- Model updates for Django 1.8 compatibility. Requires a non-DB altering migration.
v0.7.1 (2015-04-19)¶
- Fixed issue in
migrate_social_accounts
where output was overly verbose. - Fixed issue in
migrate_social_accounts
with handling skipped providers.
v0.7.0 (2014-09-07)¶
This release adds support for 1.7 and the new style migrations. If you are using Django < 1.7 and South >= 1.0 this should continue to work without issue.
For those using Django < 1.7 and South < 1.0 you’ll need
to add the SOUTH_MIGRATION_MODULES
setting to point to the old South migrations.
SOUTH_MIGRATION_MODULES = {
'allaccess': 'allaccess.south_migrations',
}
No new migrations were added for this release, but this will be the new location for future migrations. If your DB tables are up to date from v0.6, upgrading to 1.7 and running:
python manage.py migrate allaccess
should automatically fake the initial migration using the new-style migrations.
Backwards Incompatible Changes¶
- Python 2.6 is no longer officially supported or tested.
v0.6.0 (2014-02-01)¶
This release adds a better migration path for moving from django-social-auth and includes changes to support running on the Google App Engine. There are two South migrations included with this release. To upgrade, you should run:
python manage.py migrate allaccess
More details for this change are noted under the “Backwards Incompatible Changes”.
- Added
migrate_social_accounts
andmigrate_social_providers
management commands to help migrate data from django-social-auth. - Updated
Provider
model for compatibility with running on the Google App Engine. Thanks to Marco Seguri for the report and fix. - Increased the URL lengths for the fields on the
Provider
model. Thanks to Marco Seguri for the fix. - Added support for serialization of
Provider
andAccountAccess
records by natural keys. - Included a fixture of common providers (Facebook, Twitter, Google, Microsoft Live, Github and Bitbucket). Thanks to Marco Seguri for the initial patch.
Backwards Incompatible Changes¶
- The
key
andsecret
columns onProvider
were renamed toconsumer_key
andconsumer_secret
.key
is a reserved property
name when using Google App Engine and secret
was changed as well for consistency. A migration has been added for the change but
if you were referencing the key
/secret
explicitly in your code those references need to be updated as well.
- ProviderManager.enabled
has been removed. This was a short-cut method for filtering out providers with key or secret values. However,
it doesn’t work on Google App Engine. It was only used in a few places internally so it was removed. The equivalent query is
Provider.objects.filter(consumer_secret__isnull=False, consumer_key__isnull=False)
v0.5.1 (2013-08-16)¶
- Fix incompatibility with the existing South migrations and a customized User model. Thanks to Jharrod LaFon for the report and fix.
v0.5.0 (2013-03-18)¶
This release adds additional hooks for changing the OAuth client behaviors. It also adds support for Python 3.2+.
- New view hooks for customizing the OAuth client
- Fixed issue with including oauth_verifier in POST when fetching the access token
- Documented the API for
OAuthClient
andOAuth2Client
- Updated requirements to requests >= 1.0 and requests_oauthlib >= 0.3.0
- Updated requirement for PyCrypto >= 2.4
Backwards Incompatible Changes¶
- Dropped support for requests < 1.0
- Dropped support for Django < 1.4.2
v0.4.1 (2013-01-02)¶
There were incompatibilty issues with requests-oauthlib (0.2) and requests which required dropping requests 1.0 support. The requirement of oauthlib was also raised to 0.3.4 due to similar issues. For more detail see the below issues.
v0.4.0 (2012-12-19)¶
This release is largely to keep pace with features/changes to some of the dependencies. This also helps work toward Python 3.0 support.
- Updated for compatibility with Django 1.4 timezone support
- Updated for compatibility with Django 1.5 swappable
auth.User
- Updated for compatibility with Requests 1.0
- Added requests_oauthlib requirement
- Updated requirement of oauthlib to 0.3 or higher
v0.3.0 (2012-07-13)¶
This release added some basic logging to django-all-access. To enable this logging
in your project, you should update your LOGGING
configuration to include
allaccess
in the loggers
section. Below is an example:
LOGGING = {
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins', ],
'level': 'ERROR',
'propagate': True,
},
'allaccess': {
'handlers': ['console', ],
'level': 'INFO',
}
}
}
For more information on logging please see the Django documentation or the Python documentation.
Features¶
- Added access to simple API wrapper through the
AccountAccess
model - Added state parameter for OAuth 2.0 by default
- Added basic error logging to OAuth clients and views
- Added contributing guide and mailing list info
v0.2.1 (2012-06-29)¶
Bug Fixes¶
- Fixes missing Content-Length header when requesting OAuth 2.0 access token
v0.2.0 (2012-06-24)¶
There are two South migrations included with this release. To upgrade you should run:
python manage.py migrate allaccess
If you are not using South, you will not need to change your database schema because
the underlying field type did not change. However, you should re-save all existing
AccountAccess
instances to ensure that their access tokens go through the encryption step
from allaccess.models import AccountAccess
for access in AccountAccess.objects.all():
access.save()
Features¶
OAuthRedirect
view can now specify a callback URLOAuthRedirect
view can now specify additional permissions- Context processor for adding enabled providers to the template context
- User access tokens are stored with AES encryption
- Documentation on customizing the view workflow behaviors
- Travis CI integration
Bug Fixes¶
- Fixed OAuth2Client to include
grant_type
paramater when requesting access token - Fixed OAuth2Client to match current OAuth draft for access token response as well as legacy response from Facebook
Backwards Incompatible Changes¶
- Moving the construction on the callback from the client to the view changed the signature of the client
get_redirect_url
,get_redirect_args
,get_request_token
(OAuth 1.0 only) andget_access_token
to include the callback. These are largely internal functions and likely will not impact existing applications. - The
AccountAccess.access_token
field was changed from a plain text field to an encrypted field. See previous note on migrating this data.
v0.1.1 (2012-06-22)¶
- Fixed bug with passing incorrect callback parameter for OAuth 1.0
- Additional documentation on configuring
LOGIN_URL
andLOGIN_REDIRECT_URL
- Additional view tests
- Handled poor
LOGIN_URL
andLOGIN_REDIRECT_URL
settings in view tests
v0.1.0 (2012-06-21)¶
- Initial public release.