Bitbucket is a code hosting site with unlimited public and private repositories. We're also free for small teams!

Close

Django Social Auth

Django Social Auth is an easy to setup social authentication/authorization mechanism for Django projects.

Crafted using base code from django-twitter-oauth and django-openid-auth, implements a common interface to define new authentication providers from third parties.

You can check this documentation on Read the Docs too.

Demo

There's a demo at http://social.matiasaguirre.net/. Note: It lacks some backends support at the moment.

Features

This application provides user registration and login using social sites credentials, some features are:

Dependencies

Dependencies that must be meet to use the application:

Installation

From pypi:

$ pip install django-social-auth

or:

$ easy_install django-social-auth

or clone from github:

$ git clone git://github.com/omab/django-social-auth.git

and add social_auth to PYTHONPATH:

$ export PYTHONPATH=$PYTHONPATH:$(pwd)/django-social-auth/

or:

$ cd django-social-auth
$ sudo python setup.py install

Configuration

  • Add social_auth to PYTHONPATH and installed applications:

    INSTALLED_APPS = (
        ...
        'social_auth'
    )
    
  • Add desired authentication backends to Django's AUTHENTICATION_BACKENDS setting:

    AUTHENTICATION_BACKENDS = (
        'social_auth.backends.twitter.TwitterBackend',
        'social_auth.backends.facebook.FacebookBackend',
        'social_auth.backends.google.GoogleOAuthBackend',
        'social_auth.backends.google.GoogleOAuth2Backend',
        'social_auth.backends.google.GoogleBackend',
        'social_auth.backends.yahoo.YahooBackend',
        'social_auth.backends.browserid.BrowserIDBackend',
        'social_auth.backends.contrib.linkedin.LinkedinBackend',
        'social_auth.backends.contrib.livejournal.LiveJournalBackend',
        'social_auth.backends.contrib.orkut.OrkutBackend',
        'social_auth.backends.contrib.foursquare.FoursquareBackend',
        'social_auth.backends.contrib.github.GithubBackend',
        'social_auth.backends.contrib.dropbox.DropboxBackend',
        'social_auth.backends.contrib.flickr.FlickrBackend',
        'social_auth.backends.OpenIDBackend',
        'django.contrib.auth.backends.ModelBackend',
    )
    

    Take into account that backends must be defined in AUTHENTICATION_BACKENDS or Django won't pick them when trying to authenticate the user.

    Don't miss django.contrib.auth.backends.ModelBackend if using django.auth user model or users won't be able to login.

  • Define desired backends for your site:

    SOCIAL_AUTH_ENABLED_BACKENDS = ('google', 'google-oauth', 'facebook', ...)
    

    All backends are enabled by default.

  • Setup needed OAuth keys (see OAuth section for details):

    TWITTER_CONSUMER_KEY         = ''
    TWITTER_CONSUMER_SECRET      = ''
    FACEBOOK_APP_ID              = ''
    FACEBOOK_API_SECRET          = ''
    LINKEDIN_CONSUMER_KEY        = ''
    LINKEDIN_CONSUMER_SECRET     = ''
    ORKUT_CONSUMER_KEY           = ''
    ORKUT_CONSUMER_SECRET        = ''
    GOOGLE_CONSUMER_KEY          = ''
    GOOGLE_CONSUMER_SECRET       = ''
    GOOGLE_OAUTH2_CLIENT_ID      = ''
    GOOGLE_OAUTH2_CLIENT_SECRET  = ''
    FOURSQUARE_CONSUMER_KEY      = ''
    FOURSQUARE_CONSUMER_SECRET   = ''
    GITHUB_APP_ID                = ''
    GITHUB_API_SECRET            = ''
    DROPBOX_APP_ID               = ''
    DROPBOX_API_SECRET           = ''
    FLICKR_APP_ID                = ''
    FLICKR_API_SECRET            = ''
    
  • Setup login URLs:

    LOGIN_URL          = '/login-form/'
    LOGIN_REDIRECT_URL = '/logged-in/'
    LOGIN_ERROR_URL    = '/login-error/'
    

    Check Django documentation at Login URL and Login redirect URL

    If a custom redirect URL is needed that must be different to LOGIN_URL, define the setting:

    SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/another-login-url/'
    

    A different URL could be defined for newly registered users:

    SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/new-users-redirect-url/'
    

    or for newly associated accounts:

    SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/new-association-redirect-url/'
    

    or for account disconnections:

    SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = '/account-disconnected-redirect-url/'
    

    In case of authentication error, the message can be stored in session if the following setting is defined:

    SOCIAL_AUTH_ERROR_KEY = 'social_errors'
    

    This defines the desired session key where last error message should be stored. It's disabled by default.

  • Configure authentication and association complete URL names to avoid possible clashes:

    SOCIAL_AUTH_COMPLETE_URL_NAME  = 'socialauth_complete'
    SOCIAL_AUTH_ASSOCIATE_URL_NAME = 'socialauth_associate_complete'
    
  • Add URLs entries:

    urlpatterns = patterns('',
        ...
        url(r'', include('social_auth.urls')),
        ...
    )
    

    All django-social-auth URLs names have socialauth_ prefix.

  • Define context processors if needed:

    TEMPLATE_CONTEXT_PROCESSORS = (
        ...
        'social_auth.context_processors.social_auth_by_name_backends',
        'social_auth.context_processors.social_auth_backends',
        'social_auth.context_processors.social_auth_by_type_backends',
    )
    
    • social_auth_by_name_backends: Adds a social_auth dict where each key is a provider name and its value is a UserSocialAuth instance if user has associated an account with that provider, otherwise None.
    • social_auth_backends: Adds a social_auth dict with keys are associated, not_associated and backends. associated key is a list of UserSocialAuth instances associated with current user. not_associated is a list of providers names that the current user doesn't have any association yet. backends holds the list of backend names supported.
    • social_auth_by_type_backends: Simiar to social_auth_backends but each value is grouped by backend type openid, oauth2 and oauth.

    Check social_auth.context_processors for details.

    Note: social_auth_backends and social_auth_by_type_backends don't play nice together.

  • Sync database to create needed models:

    ./manage.py syncdb
    
  • Not mandatory, but recommended:

    SOCIAL_AUTH_DEFAULT_USERNAME = 'new_social_auth_user'
    

    or:

    import random
    SOCIAL_AUTH_DEFAULT_USERNAME = lambda: random.choice(['Darth Vader', 'Obi-Wan Kenobi', 'R2-D2', 'C-3PO', 'Yoda'])
    

    or:

    from django.template.defaultfilters import slugify
    SOCIAL_AUTH_USERNAME_FIXER = lambda u: slugify(u)
    

    in case your user layout needs to purify username on some weird way.

    Final user name will have a random UUID-generated suffix in case it's already taken. The UUID token max length can be changed with the setting:

    SOCIAL_AUTH_UUID_LENGTH = 16
    
  • Backends will store extra values from response by default, set this to False to avoid such behavior:

    SOCIAL_AUTH_EXTRA_DATA = False
    

    Also more extra values will be stored if defined, details about this setting are listed below on OpenId and OAuth sections.

    Session expiration time is an special value, it's recommended to define:

    SOCIAL_AUTH_EXPIRATION = 'expires'
    

    and use such setting name where expiration times are returned. View that completes login process will set session expiration time using this name if it's present or expires by default. Expiration configuration can be disabled with setting:

    SOCIAL_AUTH_SESSION_EXPIRATION = False
    
  • It's possible to override the used User model if needed:

    SOCIAL_AUTH_USER_MODEL = 'myapp.CustomUser'
    

    This class must have a custom Model Manager with a create_user method that resembles the one on auth.UserManager.

    Also, it's highly recommended that this class define the following fields:

    username   = CharField(...)
    last_login = DateTimeField(blank=True)
    is_active  = BooleanField(...)
    

    and the method:

    is_authenticated():
        ...
    

    These are needed to ensure a better django-auth integration, in other case login_required won't be usable. A warning is displayed if any of these are missing. By default auth.User is used.

    Check example application for implementation details, but first, please take a look to User Profiles, it might be what you were looking for.

    It's possible to disable user creations by django-social-auth with:

    SOCIAL_AUTH_CREATE_USERS = False
    

    It is also possible to associate multiple user accounts with a single email address as long as the rest of the user data is unique. Set value as True to enable, otherwise set as False to disable. This behavior is disabled by default (false) unless specifically set:

    SOCIAL_AUTH_ASSOCIATE_BY_MAIL = True
    
  • You can send extra parameters on auth process by defining settings per provider, example to request Facebook to show Mobile authorization page, define:

    FACEBOOK_AUTH_EXTRA_ARGUMENTS = {'display': 'touch'}
    

    For other providers, just define settings in the form:

    <uppercase backend name>_AUTH_EXTRA_ARGUMENTS = {...}
    
  • Also, you can send extra parameters on request token process by defining settings per provider in the same way explained above but with this other suffix:

    <uppercase backend name>_REQUEST_TOKEN_EXTRA_ARGUMENTS = {...}
    
  • By default the application doesn't make redirects to different domains, to disable this behavior:

    SOCIAL_AUTH_SANITIZE_REDIRECTS = False
    
  • Inactive users can be redirected to a different page if this setting is defined:

    SOCIAL_AUTH_INACTIVE_USER_URL = '...'
    

    Defaults to LOGIN_ERROR_URL.

Authentication Pipeline

The final process of the authentication workflow is handled by a operations pipeline where custom functions can be added or default items can be removed to provide a custom behavior.

The default pipeline mimics the user creation and basic data gathering from previous django-social-auth versions and a big set of settings (listed below) that were used to alter the default behavior are now deprecated in favor of pipeline overrides.

The default pipeline is composed by:

(
    'social_auth.backends.pipeline.social.social_auth_user',
    'social_auth.backends.pipeline.associate.associate_by_email',
    'social_auth.backends.pipeline.user.get_username',
    'social_auth.backends.pipeline.user.create_user',
    'social_auth.backends.pipeline.social.associate_user',
    'social_auth.backends.pipeline.social.load_extra_data',
    'social_auth.backends.pipeline.user.update_user_details'
)

But it's possible to override it by defining the setting SOCIAL_AUTH_PIPELINE, for example a pipeline that won't create users, just accept already registered ones would look like this:

SOCIAL_AUTH_PIPELINE = (
    'social_auth.backends.pipeline.social.social_auth_user',
    'social_auth.backends.pipeline.social.load_extra_data',
    'social_auth.backends.pipeline.user.update_user_details'
)
Each pipeline function will receive the following parameters:
  • Current social authentication backend

  • User ID given by authentication provider

  • User details given by authentication provider

  • is_new flag (initialized in False)

  • Any arguments passed to auth_complete backend method, default views pass this arguments:

    • current logged in user (if it's logged in, otherwise None)
    • current request

Each pipeline entry must return a dict or None, any value in the dict will be used in the kwargs argument for the next pipeline entry.

The workflow will be cut if the exception social_auth.backends.exceptions.StopPipeline is raised at any point.

If any function returns something else beside a dict or None, the workflow will be cut and the value returned immediately, this is useful to return HttpReponse instances like HttpResponseRedirect.

Partial Pipeline

It's possible to cut the pipeline process to return to the user asking for more data and resume the process later, to accomplish this add the entry social_auth.backends.pipeline.misc.save_status_to_session (or a similar implementation) to the pipeline setting before any entry that returns an HttpResponse instance:

SOCIAL_AUTH_PIPELINE = (
    ...
    social_auth.backends.pipeline.misc.save_status_to_session,
    app.pipeline.redirect_to_basic_user_data_form
    ...
)

When it's time to resume the process just redirect the user to /complete/<backend>/ view. By default the pipeline will be resumed in the next entry after save_status_to_session but this can be modified by setting the following setting to the import path of the pipeline entry to resume processing:

SOCIAL_AUTH_PIPELINE_RESUME_ENTRY = <a zero based index>

save_status_to_session saves needed data into user session, the key can be defined by SOCIAL_AUTH_PARTIAL_PIPELINE_KEY which default value is partial_pipeline:

SOCIAL_AUTH_PARTIAL_PIPELINE_KEY = 'partial_pipeline'

Check the example application to check a basic usage.

Deprecated bits

The following settings are deprecated in favor of pipeline functions.

  • These settings should be avoided and override get_username pipeline entry with the desired behavior:

    SOCIAL_AUTH_FORCE_RANDOM_USERNAME
    SOCIAL_AUTH_DEFAULT_USERNAME
    SOCIAL_AUTH_UUID_LENGTH
    SOCIAL_AUTH_USERNAME_FIXER
    
  • User creation setting should be avoided and remove the entry create_user from pipeline instead:

    SOCIAL_AUTH_CREATE_USERS
    
  • Automatic data update should be stopped by overriding update_user_details pipeline entry instead of using this setting:

    SOCIAL_AUTH_CHANGE_SIGNAL_ONLY
    
  • Extra data retrieval from providers should be stopped by removing load_extra_data from pipeline instead of using this setting:

    SOCIAL_AUTH_EXTRA_DATA
    
  • Automatic email association should be avoided by removing associate_by_email pipeline entry instead of using this setting:

    SOCIAL_AUTH_ASSOCIATE_BY_MAIL
    

Usage example

Authentication process starts with socialauth_begin URL.

Template code example:

<ul>
  <li>
    <a href="{% url socialauth_begin 'twitter' %}">Enter using Twitter</a>
  </li>
  <li>
    <a href="{% url socialauth_begin 'facebook' %}">Enter using Facebook</a>
  </li>
</ul>

In the example above we assume that Twitter and Facebook authentication backends enabled, and following settings provided:

TWITTER_CONSUMER_KEY = 'real key here'
TWITTER_CONSUMER_SECRET = 'real secret here'
FACEBOOK_APP_ID = 'real id here'
FACEBOOK_API_SECRET = 'real secret here'

Signals

A pre_update signal is sent when user data is about to be updated with new values from authorization service provider, this apply to new users and already existent ones. This is useful to update custom user fields or User Profiles, for example, to store user gender, location, etc. Example:

from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend

def facebook_extra_values(sender, user, response, details, **kwargs):
    user.gender = response.get('gender')
    return True

pre_update.connect(facebook_extra_values, sender=FacebookBackend)

New data updating is made automatically but could be disabled and left only to signal handler if this setting value is set to True:

SOCIAL_AUTH_CHANGE_SIGNAL_ONLY = False

Take into account that when defining a custom User model and declaring signal handler in models.py, the imports and handler definition must be made after the custom User model is defined or circular imports issues will be raised.

Also a new-user signal (socialauth_registered) is sent when new accounts are created:

from social_auth.signals import socialauth_registered

def new_users_handler(sender, user, response, details, **kwargs):
    user.is_new = True
    return False

socialauth_registered.connect(new_users_handler, sender=None)

OpenId

OpenId support is simpler to implement than OAuth. Google and Yahoo providers are supported by default, others are supported by POST method providing endpoint URL.

OpenId backends can store extra data in UserSocialAuth.extra_data field by defining a set of values names to retrieve from any of the used schemas, AttributeExchange and SimpleRegistration. As their keywords differ we need two settings.

Settings is per backend, so we have two possible values for each one. Name is dynamically checked using uppercase backend name as prefix:

<uppercase backend name>_SREG_EXTRA_DATA
<uppercase backend name>_AX_EXTRA_DATA

Example:

GOOGLE_SREG_EXTRA_DATA = [(..., ...)]
GOOGLE_AX_EXTRA_DATA = [(..., ...)]

Settings must be a list of tuples mapping value name in response and value alias used to store.

OAuth

OAuth communication demands a set of keys exchange to validate the client authenticity prior to user approbation. Twitter, Facebook and Orkut facilitates these keys by application registration, Google works the same, but provides the option for unregistered applications.

Check next sections for details.

OAuth backends also can store extra data in UserSocialAuth.extra_data field by defining a set of values names to retrieve from service response.

Settings is per backend and it's name is dynamically checked using uppercase backend name as prefix:

<uppercase backend name>_EXTRA_DATA

Example:

FACEBOOK_EXTRA_DATA = [(..., ...)]

Settings must be a list of tuples mapping value name in response and value alias used to store.

Twitter

Twitter offers per application keys named Consumer Key and Consumer Secret. To enable Twitter these two keys are needed. Further documentation at Twitter development resources:

  • Register a new application at Twitter App Creation,

  • mark the "Yes, use Twitter for login" checkbox, and

  • fill Consumer Key and Consumer Secret values:

    TWITTER_CONSUMER_KEY
    TWITTER_CONSUMER_SECRET
    
  • You need to specify an URL callback or the application will be marked as Client type instead of the Browser. Almost any dummy value will work if you plan some test.

Facebook

Facebook works similar to Twitter but it's simpler to setup and redirect URL is passed as a parameter when issuing an authorization. Further documentation at Facebook development resources:

  • Register a new application at Facebook App Creation, and

  • fill App Id and App Secret values in values:

    FACEBOOK_APP_ID
    FACEBOOK_API_SECRET
    
  • also it's possible to define extra permissions with:

    FACEBOOK_EXTENDED_PERMISSIONS = [...]
    

If you define a redirect URL in Facebook setup page, be sure to not define http://127.0.0.1:8000 or http://localhost:8000 because it won't work when testing. Instead I define http://myapp.com and setup a mapping on /etc/hosts or use dnsmasq.

Orkut

Orkut offers per application keys named Consumer Key and Consumer Secret. To enable Orkut these two keys are needed.

Check Google support and Orkut API for details on getting your consumer_key and consumer_secret keys.

  • fill Consumer Key and Consumer Secret values:

    ORKUT_CONSUMER_KEY
    ORKUT_CONSUMER_SECRET
    
  • add any needed extra data to:

    ORKUT_EXTRA_DATA = ''
    
  • configure extra scopes in:

    ORKUT_EXTRA_SCOPES = [...]
    

Google OAuth

Google provides Consumer Key and Consumer Secret keys to registered applications, but also allows unregistered application to use their authorization system with, but beware that this method will display a security banner to the user telling that the application is not trusted.

Check Google OAuth and make your choice.

  • fill Consumer Key and Consumer Secret values:

    GOOGLE_CONSUMER_KEY
    GOOGLE_CONSUMER_SECRET
    

anonymous values will be used if not configured as described in their OAuth reference

  • configure the display name to be used in the "grant permissions" dialog that Google will display to users in:

    GOOGLE_DISPLAY_NAME = ''
    

    shows 'Social Auth' by default, but that might not suite your application.

  • setup any needed extra scope in:

    GOOGLE_OAUTH_EXTRA_SCOPE = [...]
    

Check which applications can be included in their Google Data Protocol Directory

Google OAuth2

Recently Google launched OAuth2 support following the definition at OAuth2 draft. It works in a similar way to plain OAuth mechanism, but developers must register an application and apply for a set of keys. Check Google OAuth2 document for details.

Note:
This support is experimental as Google implementation may change and OAuth2 is still a draft.

To enable OAuth2 support:

  • fill Client ID and Client Secret settings, these values can be obtained easily as described on OAuth2 Registering doc:

    GOOGLE_OAUTH2_CLIENT_ID = ''
    GOOGLE_OAUTH2_CLIENT_SECRET = ''
    

    previous name GOOGLE_OAUTH2_CLIENT_KEY is supported for backward compatibility.

  • scopes are shared between OAuth mechanisms:

    GOOGLE_OAUTH_EXTRA_SCOPE = [...]
    

Check which applications can be included in their Google Data Protocol Directory

LinkedIn

LinkedIn setup is similar to any other OAuth service. To request extra fields using LinkedIn fields selectors just define the setting:

LINKEDIN_EXTRA_FIELD_SELECTORS = [...]

with the needed fields selectors, also define LINKEDIN_EXTRA_DATA properly, that way the values will be stored in UserSocialAuth.extra_data field.

By default id, first-name and last-name are requested and stored.

GitHub

GitHub works similar to Facebook (OAuth).

  • Register a new application at GitHub Developers, set your site domain as the callback URL or it might cause some troubles when associating accounts,

  • Fill App Id and App Secret values in the settings:

    GITHUB_APP_ID = ''
    GITHUB_API_SECRET = ''
    
  • Also it's possible to define extra permissions with:

    GITHUB_EXTENDED_PERMISSIONS = [...]
    

Dropbox

Dropbox uses OAuth v1.0 for authentication.

  • Register a new application at Dropbox Developers, and

  • fill App Key and App Secret values in the settings:

    DROPBOX_APP_ID = ''
    DROPBOX_API_SECRET = ''
    

Flickr

Flickr uses OAuth v1.0 for authentication.

  • Register a new application at the Flickr App Garden, and

  • fill Key and Secret values in the settings:

    FLICKR_APP_ID = ''
    FLICKR_API_SECRET = ''
    

BrowserID

Support for BrowserID is possible by posting the assertion code to /complete/browserid/ URL.

The setup doesn't need any setting, just the usual BrowserID javascript include in your document and the needed mechanism to trigger the POST to django-social-auth.

Check the second "Use Case" for an implementation example.

Testing

To test the app just run:

./manage.py test social_auth

This will run a bunch of tests, so far only login process is tested, more will come eventually.

User accounts on the different sites are needed to run tests, configure the credentials in the following way:

# twitter testing
TEST_TWITTER_USER = 'testing_account'
TEST_TWITTER_PASSWORD = 'password_for_testing_account'

# facebook testing
TEST_FACEBOOK_USER = 'testing_account'
TEST_FACEBOOK_PASSWORD = 'password_for_testing_account'

# google testing
TEST_GOOGLE_USER = 'testing_account@gmail.com'
TEST_GOOGLE_PASSWORD = 'password_for_testing_account'

There's support for Selenium tests too on root contrib directory. To run install selenium:

$ pip install selenium

and create a test_settings.py copying test_settings.py.template and fill the needed account information. Then run:

cd contrib/tests
./runtests.py

Use Cases

Some particular use cases are listed below.

  1. Use social auth just for account association (no login):

    urlpatterns += patterns('',
        url(r'^associate/(?P<backend>[^/]+)/$', associate,
            name='socialauth_associate_begin'),
        url(r'^associate/complete/(?P<backend>[^/]+)/$', associate_complete,
            name='socialauth_associate_complete'),
        url(r'^disconnect/(?P<backend>[^/]+)/$', disconnect,
            name='socialauth_disconnect'),
        url(r'^disconnect/(?P<backend>[^/]+)/(?P<association_id>[^/]+)/$',
            disconnect, name='socialauth_disconnect_individual'),
    )
    
  2. Include a similar snippet in your page to make BrowserID work::

    <!-- Include BrowserID JavaScript --> <script src="https://browserid.org/include.js" type="text/javascript"></script>

    <!-- Define a form to send the POST data --> <form method="post" action="{% url socialauth_complete "browserid" %}">

    <input type="hidden" name="assertion" value="" /> <a rel="nofollow" id="browserid" href="#">BrowserID</a>

    </form>

    <!-- Setup click handler that retieves BrowserID assertion code and sends

    POST data -->

    <script type="text/javascript">
    $(function () {
    $('#browserid').click(function (e) {

    e.preventDefault(); var self = $(this);

    navigator.id.get(function (assertion) {
    if (assertion) {
    self.parent('form')
    .find('input[type=hidden]')

    .attr('value', assertion) .end()

    .submit();

    } else {

    alert('Some error occurred');

    }

    });

    });

    });

    </script>

Miscellaneous

Join to django-social-auth community on Convore and bring any questions or suggestions that will improve this app.

If defining a custom user model, do not import social_auth from any models.py that would finally import from the models.py that defines your User class or it will make your project fail with a recursive import because social_auth uses get_model() to retrieve your User.

There's an ongoing movement to create a list of third party backends on djangopackages.com, so, if somebody doesn't want it's backend in the contrib directory but still wants to share, just split it in a separated package and link it there.

Bugs

Maybe several, please create issues in github

Contributors

Attributions to whom deserves:

  • caioariede (Caio Ariede):
    • Improvements and Orkut support
  • krvss (Stas Kravets):
    • Initial setup.py configuration
  • jezdez (Jannis Leidel):
    • Improvements and documentation update
  • alfredo (Alfredo Ramirez)
    • Facebook and Doc improvements
  • mattucf (Matt Brown)
    • Twitter and OAuth improvements
  • Quard (Vadym Zakovinko)
    • LinkedIn support
  • micrypt (Seyi Ogunyemi)
    • OAuth2 migration
  • bedspax
    • Foursquare support
  • revolunet (Julien Bouquillon)
    • GitHub support
  • danielgtaylor (Daniel G. Taylor)
    • Dropbox support
    • Flickr support
    • Provider name context processor

Copyrights

Base work is copyrighted by:

  • django-twitter-oauth:

    Original Copyright goes to Henrik Lied (henriklied)
    Code borrowed from https://github.com/henriklied/django-twitter-oauth
    
  • django-openid-auth:

    django-openid-auth -  OpenID integration for django.contrib.auth
    Copyright (C) 2007 Simon Willison
    Copyright (C) 2008-2010 Canonical Ltd.
    

Recent activity

Johannes Holmberg

Commits by Johannes Holmberg were pushed to rsalmaso/django-social-auth

7100056 - Add a BACKENDS dictionary for the basic OpenID backend, allowing it to be discovered by get_backends.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.