Twitter authentication¶
Basic usage¶
Communications with Twitter are handled with Mike Verdone’s minimalist python twitter API library. Define two URLs, one to initiate the twitter login and the other for the OAuth callback:
from myapp import views
urlpatterns = patterns('',
url(r'^oauth/authorize/$',
views.authorize,
name='oauth_authorize'),
# use the following URL if you want to force authentication
# For example, if you're already authenticated, but want to
# reauthenticate as a different user.
url(r'^oauth/authorize/force/$',
views.authorize,
{'force_login': True},
name='oauth_force_authorize'),
url(r'^oauth/callback/$',
views.callback,
name='oauth_callback'),
)
Set your OAuth consumer key and secret in your settings:
CONSUMER_KEY = 'yayyaaa'
CONSUMER_SECRET = 'whoooooohooo'
And create the two views:
from django.http import HttpResponse
from django.shortcuts import redirect
from django.utils import simplejson as json
import twitter
from le_social.twitter import views
authorize = views.Authorize.as_view()
class Callback(views.Callback):
def error(self, message, exception=None):
return HttpResponse(message)
def success(self, auth):
api = twitter.Twitter(auth=auth)
user = api.account.verify_credentials()
dbuser, created = SomeModel.objects.get_or_create(
screen_name=user['screen_name']
)
user.token = auth.token
user.token_secret = auth.token_secret
user.save()
return redirect(reverse('some_view'))
callback = Callback.as_view()
On the Callback
view, you need to implement the
error(message, exception=None)
and success(auth)
methods.
Both must return an HTTP response.
Extension points¶
Authorize¶
The Authorize
is a django.views.generic.View
subclass. Customization
can be done using the extension points it provides. For instance, if one
doesn’t want to allow logged-in users to sign in with Twitter:
class Authorize(views.Authorize):
def get(self, request, *args, **kwargs):
if request.user.is_authenticated():
return redirect('/')
return super(Authorize, self).get(request, *args, **kwargs)
authorize = Authorize.as_view()
If you want Twitter to redirect your user to a custom location, specify it in
Authorize.build_callback
. This function needs to return an absolute URI,
including protocol and domain. For instance:
from django.contrib.sites.models import Site
# We're replacing the following line:
# authorize = views.Authorize.as_view()
class Authorize(views.Authorize):
def build_callback(self):
# build a custom callback URI
next = self.request.path
site = Site.objects.get_current()
return 'http://{0}{1}?next={2}'.format(
site.domain,
reverse('oauth_callback'),
next)
If you don’t implement build_callback
or if you return None
, your users
will be redirected to the default URL specified in the app’s settings on
twitter.com.
Although you can specify a default, it is good practice to always pass a callback URI when authorizing; this is the preferred way to preserve application state when the user’s browser returns from authenticating.
Don’t forget to update your urlconf after defining a custom callback URL. Returning browsers should be routed to the Callback view.
Callback¶
You can also special-case the Callback
view using the same technique, but
you really need to implement the error()
and success()
methods on this
class.
OAuth credentials¶
By default, the Authorize
and Callback
views look for the Twitter app
credentials in your settings (CONSUMER_KEY
, CONSUMER_SECRET
). You can
implement your own mixin instead. The default OAuth mixin looks for the
consumer key and secrets in this order:
consumer_key
andconsumer_secret
as attributes on the view class,settings.CONSUMER_KEY
andsettings.CONSUMER_SECRET
If you set consumer_key
and consumer_secret
on the class, you need to
do so on the two views, or make your custom views inherit from a mixin that
provides them.
For more logic, you can also re-implement get_consumer_key()
and
get_consumer_secret()
on the view classes to use different consumers under
certain conditions:
class OAuthMixin(views.OAuthMixin):
def get_consumer_key(self):
if self.request.user.username == 'bruno':
return 'hahahah'
return super(OAuthMixin, self).get_consumer_key()
class Authorize(OAuthMixin, views.Authorize):
pass
authorize = Authorize.as_view()
class Callback(OAuthMixin, views.Callback):
def success(self, auth):
do_some_stuff()
return something
callback = Callback.as_view()