Monday, 2 July 2012

Using Twitter As Your Flask Login Provider in 6 Lines

First off, I lied about the 6 lines, but it got you here and now you can see how simple it is yourself. There are actually 40 lines I think.

When I was building Flask Ahoy! I wanted to use Twitter as the login provider. I could spend a while boring you about why (as opposed to say Google, Facebook, OpenID or Roll-Your-Own), but I'l save that for another exciting post.

I have used the extremely handy Flask-OAuth to do all the legwork so you need to install that:

pip install Flask-OAuth
view raw gistfile1.sh hosted with ❤ by GitHub
Next we need some html for users to click on to sign in and sign out. Try this simple block :

{% block user %}
{% if 'twitter_user' not in session %}
<a href="/login">Sign in with Twitter</a>
{% else %}
<a href="/logout">Sign Out {{session['twitter_user']}}</a>
{% endif %}
{% endblock %}
Next the real code begins. In your views module you need three views:

  • One to send you off to Twitter to get authorized (login)
  • One to get the callback from Twitter and store your authorization credentials (twitter_authorized)
  • One to log you out and tidy up (logout)

from flask import redirect, url_for, session, request, flash, Blueprint, current_app
simple = Blueprint('simple', __name__)
oauth = OAuth()
twitter = twitter_factory(oauth)
@simple.route('/login')
def login():
url = url_for('.twitter_authorized', next=request.args.get('home') or request.referrer or None)
resp = twitter.authorize( callback=url )
return resp
@simple.route('/twitter/authorized')
@twitter.authorized_handler
def twitter_authorized(resp):
next_url = request.args.get('next') or url_for('.index')
if resp is None:
flash(u'You denied the request to sign in.')
return redirect(next_url)
session['twitter_token'] = (
resp['oauth_token'],
resp['oauth_token_secret']
)
session['twitter_user'] = resp['screen_name']
current_app.logger.info(resp)
flash('You were signed in as %s' % resp['screen_name'])
return redirect(next_url)
@simple.route('/logout')
def logout():
session.pop('twitter_user')
return redirect(request.args.get('next') or url_for('.home'))
view raw gistfile1.py hosted with ❤ by GitHub
Finally we need a special little method which remembers your credentials:

@twitter.tokengetter
def get_twitter_oauth_token():
return session.get('oauth_token')
view raw gistfile1.py hosted with ❤ by GitHub

Now for the sake of safety I'm going to point out a couple of things here:

  • This scenario uses flask sessions (encrypted cookies) to store your Twitter OAuth token.
  • When you logout, you are only destroying the twitter_user flag, you should probably destroy your credentials as well.


Good luck fellow travelers.

6 comments:

  1. flask sessions are only signed, not encrypted, you shouldn't be storing oauth tokens there unless you flip over to an actual encrypted serialization

    ReplyDelete
  2. Quite right.

    You could i suppose just encrypt in the twitter_authorized and decrypt in get_twitter_oauth_token using the flask secret. More lines.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
  4. So... twitter_factory...

    Where does that come from? It looks like it has lots of shiny things, but neither Google nor Github are turning up anything.

    ReplyDelete
  5. ryepdx - best way is just to show you -

    Have a look at https://gist.github.com/4085206

    ReplyDelete
  6. Could you please post the full code in one place, including all imports. Thanks

    ReplyDelete