This code was originally forked from Leah Culver and Andy Smith's oauth.py code. Some of the tests come from a fork by Vic Fryzel, while a revamped Request class and more tests were merged in from Mark Paschal's fork. A number of notable differences exist between this code and its forefathers:
import oauth2 as oauth import time # Set the API endpoint url = "http://example.com/photos" # Set the base oauth_* parameters along with any other parameters required # for the API call. params = { 'oauth_version': "1.0", 'oauth_nonce': oauth.generate_nonce(), 'oauth_timestamp': int(time.time()) 'user': 'joestump', 'photoid': 555555555555 } # Set up instances of our Token and Consumer. The Consumer.key and # Consumer.secret are given to you by the API provider. The Token.key and # Token.secret is given to you after a three-legged authentication. token = oauth.Token(key="tok-test-key", secret="tok-test-secret") consumer = oauth.Consumer(key="con-test-key", secret="con-test-secret") # Set our token/key parameters params['oauth_token'] = token.key params['oauth_consumer_key'] = consumer.key # Create our request. Change method, etc. accordingly. req = oauth.Request(method="GET", url=url, parameters=params) # Sign the request. signature_method = oauth.SignatureMethod_HMAC_SHA1() req.sign_request(signature_method, consumer, token)
The oauth2.Client is based on httplib2 and works just as you'd expect it to. The only difference is the first two arguments to the constructor are an instance of oauth2.Consumer and oauth2.Token (oauth2.Token is only needed for three-legged requests).
import oauth2 as oauth # Create your consumer with the proper key/secret. consumer = oauth.Consumer(key="your-twitter-consumer-key", secret="your-twitter-consumer-secret") # Request token URL for Twitter. request_token_url = "http://twitter.com/oauth/request_token" # Create our client. client = oauth.Client(consumer) # The OAuth Client request works just like httplib2 for the most part. resp, content = client.request(request_token_url, "GET") print resp print content
Below is an example of how one would go through a three-legged OAuth flow to gain access to protected resources on Twitter. This is a simple CLI script, but can be easily translated to a web application.
import urlparse import oauth2 as oauth consumer_key = 'my_key_from_twitter' consumer_secret = 'my_secret_from_twitter' request_token_url = 'http://twitter.com/oauth/request_token' access_token_url = 'http://twitter.com/oauth/access_token' authorize_url = 'http://twitter.com/oauth/authorize' consumer = oauth.Consumer(consumer_key, consumer_secret) client = oauth.Client(consumer) # Step 1: Get a request token. This is a temporary token that is used for # having the user authorize an access token and to sign the request to obtain # said access token. resp, content = client.request(request_token_url, "GET") if resp['status'] != '200': raise Exception("Invalid response %s." % resp['status']) request_token = dict(urlparse.parse_qsl(content)) print "Request Token:" print " - oauth_token = %s" % request_token['oauth_token'] print " - oauth_token_secret = %s" % request_token['oauth_token_secret'] print # Step 2: Redirect to the provider. Since this is a CLI script we do not # redirect. In a web application you would redirect the user to the URL # below. print "Go to the following link in your browser:" print "%s?oauth_token=%s" % (authorize_url, request_token['oauth_token']) print # After the user has granted access to you, the consumer, the provider will # redirect you to whatever URL you have told them to redirect to. You can # usually define this in the oauth_callback argument as well. accepted = 'n' while accepted.lower() == 'n': accepted = raw_input('Have you authorized me? (y/n) ') oauth_verifier = raw_input('What is the PIN? ') # Step 3: Once the consumer has redirected the user back to the oauth_callback # URL you can request the access token the user has approved. You use the # request token to sign this request. After this is done you throw away the # request token and use the access token returned. You should store this # access token somewhere safe, like a database, for future use. token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret']) token.set_verifier(oauth_verifier) client = oauth.Client(consumer, token) resp, content = client.request(access_token_url, "POST") access_token = dict(urlparse.parse_qsl(content)) print "Access Token:" print " - oauth_token = %s" % access_token['oauth_token'] print " - oauth_token_secret = %s" % access_token['oauth_token_secret'] print print "You may now access protected resources using the access tokens above." print
Twitter also has the ability to authenticate a user via an OAuth flow. This flow is exactly like the three-legged OAuth flow, except you send them to a slightly different URL to authorize them.
In this example we'll look at how you can implement this login flow using Django and python-oauth2.
You‘ll need a place to store all of your Twitter OAuth credentials after the user has logged in. In your app’s models.py
file you should add something that resembles the following model.
class Profile(models.Model): user = models.ForeignKey(User) oauth_token = models.CharField(max_length=200) oauth_secret = models.CharField(max_length=200)
urls.py
Your urls.py
should look something like the following. Basically, you need to have a login URL, a callback URL that Twitter will redirect your users back to, and a logout URL.
In this example ^login/
and twitter_login
will send the user to Twitter to be logged in, ^login/authenticated/
and twitter_authenticated
will confirm the login, create the account if necessary, and log the user into the application, and ^logout
/ logs the user out in the twitter_logout
view.
from django.conf.urls.defaults import * from django.contrib import admin from mytwitterapp.views import twitter_login, twitter_logout, \ twitter_authenticated admin.autodiscover() urlpatterns = patterns('', url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^login/?$', twitter_login), url(r'^logout/?$', twitter_logout), url(r'^login/authenticated/?$', twitter_authenticated), )
views.py
NOTE: The following code was coded for Python 2.4 so some of the libraries and code here might need to be updated if you are using Python 2.6+.
# Python import oauth2 as oauth import cgi # Django from django.shortcuts import render_to_response from django.http import HttpResponseRedirect from django.conf import settings from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required # Project from mytwitterapp.models import Profile # It's probably a good idea to put your consumer's OAuth token and # OAuth secret into your project's settings. consumer = oauth.Consumer(settings.TWITTER_TOKEN, settings.TWITTER_SECRET) client = oauth.Client(consumer) request_token_url = 'http://twitter.com/oauth/request_token' access_token_url = 'http://twitter.com/oauth/access_token' # This is the slightly different URL used to authenticate/authorize. authenticate_url = 'http://twitter.com/oauth/authenticate' def twitter_login(request): # Step 1. Get a request token from Twitter. resp, content = client.request(request_token_url, "GET") if resp['status'] != '200': raise Exception("Invalid response from Twitter.") # Step 2. Store the request token in a session for later use. request.session['request_token'] = dict(cgi.parse_qsl(content)) # Step 3. Redirect the user to the authentication URL. url = "%s?oauth_token=%s" % (authenticate_url, request.session['request_token']['oauth_token']) return HttpResponseRedirect(url) @login_required def twitter_logout(request): # Log a user out using Django's logout function and redirect them # back to the homepage. logout(request) return HttpResponseRedirect('/') def twitter_authenticated(request): # Step 1. Use the request token in the session to build a new client. token = oauth.Token(request.session['request_token']['oauth_token'], request.session['request_token']['oauth_token_secret']) client = oauth.Client(consumer, token) # Step 2. Request the authorized access token from Twitter. resp, content = client.request(access_token_url, "GET") if resp['status'] != '200': print content raise Exception("Invalid response from Twitter.") """ This is what you'll get back from Twitter. Note that it includes the user's user_id and screen_name. { 'oauth_token_secret': 'IcJXPiJh8be3BjDWW50uCY31chyhsMHEhqJVsphC3M', 'user_id': '120889797', 'oauth_token': '120889797-H5zNnM3qE0iFoTTpNEHIz3noL9FKzXiOxwtnyVOD', 'screen_name': 'heyismysiteup' } """ access_token = dict(cgi.parse_qsl(content)) # Step 3. Lookup the user or create them if they don't exist. try: user = User.objects.get(username=access_token['screen_name']) except User.DoesNotExist: # When creating the user I just use their screen_name@twitter.com # for their email and the oauth_token_secret for their password. # These two things will likely never be used. Alternatively, you # can prompt them for their email here. Either way, the password # should never be used. user = User.objects.create_user(access_token['screen_name'], '%s@twitter.com' % access_token['screen_name'], access_token['oauth_token_secret']) # Save our permanent token and secret for later. profile = Profile() profile.user = user profile.oauth_token = access_token['oauth_token'] profile.oauth_secret = access_token['oauth_token_secret'] profile.save() # Authenticate the user and log them in using Django's pre-built # functions for these things. user = authenticate(username=access_token['screen_name'], password=access_token['oauth_token_secret']) login(request, user) return HttpResponseRedirect('/')
settings.py
LOGIN_URL
to /login/
so that users are properly redirected to your Twitter login handler when you use @login_required
in other parts of your Django app.AUTH_PROFILE_MODULE = 'mytwitterapp.Profile'
so that you can easily access the Twitter OAuth token/secret for that user using the User.get_profile()
method in Django.Gmail supports OAuth over IMAP and SMTP via a standard they call XOAUTH. This allows you to authenticate against Gmail's IMAP and SMTP servers using an OAuth token and secret. It also has the added benefit of allowing you to use vanilla SMTP and IMAP libraries. The python-oauth2
package provides both IMAP and SMTP libraries that implement XOAUTH and wrap imaplib.IMAP4_SSL
and smtplib.SMTP
. This allows you to connect to Gmail with OAuth credentials using standard Python libraries.
import oauth2 as oauth import oauth2.clients.imap as imaplib # Set up your Consumer and Token as per usual. Just like any other # three-legged OAuth request. consumer = oauth.Consumer('your_consumer_key', 'your_consumer_secret') token = oauth.Token('your_users_3_legged_token', 'your_users_3_legged_token_secret') # Setup the URL according to Google's XOAUTH implementation. Be sure # to replace the email here with the appropriate email address that # you wish to access. url = "https://mail.google.com/mail/b/your_users_email@gmail.com/imap/" conn = imaplib.IMAP4_SSL('imap.googlemail.com') conn.debug = 4 # This is the only thing in the API for impaplib.IMAP4_SSL that has # changed. You now authenticate with the URL, consumer, and token. conn.authenticate(url, consumer, token) # Once authenticated everything from the impalib.IMAP4_SSL class will # work as per usual without any modification to your code. conn.select('INBOX') print conn.list()
import oauth2 as oauth import oauth2.clients.smtp as smtplib # Set up your Consumer and Token as per usual. Just like any other # three-legged OAuth request. consumer = oauth.Consumer('your_consumer_key', 'your_consumer_secret') token = oauth.Token('your_users_3_legged_token', 'your_users_3_legged_token_secret') # Setup the URL according to Google's XOAUTH implementation. Be sure # to replace the email here with the appropriate email address that # you wish to access. url = "https://mail.google.com/mail/b/your_users_email@gmail.com/smtp/" conn = smtplib.SMTP('smtp.googlemail.com', 587) conn.set_debuglevel(True) conn.ehlo('test') conn.starttls() # Again the only thing modified from smtplib.SMTP is the authenticate # method, which works identically to the imaplib.IMAP4_SSL method. conn.authenticate(url, consumer, token)