Twitter’s Chris Fry on Unlocking the Power of Stable Teams

If you haven’t checked out First Round Review from First Round Capital yet, it’s definitely worth a look. They’re cranking out a ton of great content featuring notable startups and founders covering a variety of topics including design, engineering and management.

I especially enjoyed this recent article discussing the power of stable teams with Twitter Engineering SVP Chris Fry. In it he makes some great points on team building…

  • keep teams together for at least 6 months, if not a year
  • don’t run people at 100% utilization all the time
  • designate a communication point person
  • keep the team’s mission crystal clear
  • get folks sitting together

I couldn’t agree more. I’ve been running teams much the same way at various ad agencies for many years now with a great deal of success. The team structure within an integrated agency is a little different from a startup (art directory, copywriter, technologist, design/UX, producer), but the tactics and results are the same.

One point that isn’t explicitly called out is the importance of rotating people through great teams. This is especially true in ad agencies where many job functions do not directly participate with the team on a day-to-day basis (i.e. account manager, media buyer, strategist, etc.) and individuals often come from very traditional shops where this type of team structure doesn’t exist. By spending a few weeks with a great team, I’ve found that you can dramatically increase the effectiveness of the agency as a whole.

Django Register with Oauth – Twitter

Before we begin, read the overview / disclaimer. Now for Twitter…

For this tutorial you’ll need to install Tweepy.

First off, ensure that you have registered your application with Twitter and have created the following in your settings file:

# https://dev.twitter.com/apps
TWITTER_CONSUMER_KEY = 'YOUR-APP-ID'
TWITTER_CONSUMER_SECRET = 'YOUR-APP-SECRET'

view raw
settings.py
hosted with ❤ by GitHub

1) Create the redirect URL

The first step in the oauth handshake is to redirect to Twitter with the oauth token (generated when the request token is fetched below):

import tweepy
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.context_processors import csrf
def get_authorization_url(request):
# URL to where we will redirect to
redirect_url = settings.SITE_URL + reverse('register_twitter')
# create the handler
auth = tweepy.OAuthHandler(settings.TWITTER_CONSUMER_KEY, settings.TWITTER_CONSUMER_SECRET, redirect_url)
# get the authorization url (i.e. https://api.twitter.com/oauth/authorize?oauth_token=XXXXXXX)
# this method automatically grabs the request token first
# Note: must ensure a callback URL (can be any URL) is defined for the application at dev.twitter.com,
# otherwise this will fail (401 Unauthorized)
try:
url = auth.get_authorization_url()
except tweepy.TweepError:
# failed to get auth url (maybe twitter is down)
url = reverse('home')
return url
# store the returned values
request.session['twitter_request_token_key'] = auth.request_token.key
request.session['twitter_request_token_secret'] = auth.request_token.secret
return url

view raw
twitter.py
hosted with ❤ by GitHub

2) Redirect to provider’s site

This url can now be used to redirect to Twitter (i.e. HttpResponseRedirect(url)):

3) Handle the response (approved or denied)

Once the user makes their choice to approve or deny, Twitter will redirect back to your redirect_url. You will need to verify the user approved the application:

def verify(request):
# Twitter will direct with oauth_token and oauth_verifier in the URL
# ?oauth_token=EoSsg1…&oauth_verifier=NB3bvAkb…
# did the user deny the request
if 'denied' in request.GET:
return False
# ensure we have a session state and the state value is the same as what twitter returned
if 'twitter_request_token_key' not in request.session \
or 'oauth_token' not in request.GET \
or 'oauth_verifier' not in request.GET \
or request.session['twitter_request_token_key'] != request.GET['oauth_token']:
return False
else:
return True

view raw
twitter.py
hosted with ❤ by GitHub

If any of the above tests fail, we can safely assume the user either arrived at this page directly (i.e. by typing in the URL) or they denied the application. Either way we don’t want to proceed and should redirect them to the start of the registration flow (i.e. HttpResponseRedirect(reverse('register'))).

4 & 5) Get an access token and the user’s profile

At this point the user has authorized your application but you don’t have actual access to their data yet. To get that you’ll need to request an access token. Notice that we’re saving the access token to the user’s session as we don’t want to request it more than once during the registration flow.

Once you have the access token, you can then make the request for the user’s profile data:

import json
import tweepy
from django.conf import settings
from app.lib import RawJsonParser
def get_user_data(request):
data = {}
# create the connection
auth = tweepy.OAuthHandler(settings.TWITTER_CONSUMER_KEY, settings.TWITTER_CONSUMER_SECRET)
# set the token and verifier
auth.set_request_token(request.GET['oauth_token'], request.GET['oauth_verifier'])
# determine if we've already requested an access token
if 'twitter_access_token_key' not in request.session:
# get the access token
access_token = auth.get_access_token(request.GET['oauth_verifier'])
# update the stored values
request.session['twitter_access_token_key'] = access_token.key
request.session['twitter_access_token_secret'] = access_token.secret
else:
# set the access token
auth.set_access_token(request.session['twitter_access_token_key'], request.session['twitter_access_token_secret'])
# create the API instance
api = tweepy.API(auth_handler=auth, parser=RawJsonParser())
user = json.loads(api.me())
# split the name
full_name = user['name'].split(' ', 1)
# get the user's info
data['user_id'] = user['id']
data['username'] = user['screen_name']
data['full_name'] = user['name']
data['first_name'] = full_name[0] if len(full_name) > 0 else ''
data['last_name'] = full_name[1] if len(full_name) >= 2 else ''
data['timezone'] = 0 if user['utc_offset'] is None else user['utc_offset'] / 3600
data['picture'] = user['profile_image_url'].replace('_normal', '')
return data

view raw
twitter.py
hosted with ❤ by GitHub

One thing to notice is that a custom parser is being used to get the raw json data coming from Twitter. Here’s what that parser looks like:

from tweepy.parsers import Parser
class RawJsonParser(Parser):
def parse(self, method, payload):
return payload

view raw
lib.py
hosted with ❤ by GitHub

That’s it! You can now use the user’s profile information to pre-fill a registration form, perhaps skipping over fields where you already have a required value such as an email address or first and last name. Just be sure to save their Twitter ID along with their profile so you can use it validate them in the future. You should also save the access token key and secret so that you can make future requests to the API for this user. Note that Twitter does not currently expire access tokens like other providers.

In a future post I’ll be looking at how to detect an already registered user as well as provide a login with this provider button.