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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pip install Flask-OAuth |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% 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 %} |
- 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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@twitter.tokengetter | |
def get_twitter_oauth_token(): | |
return session.get('oauth_token') |
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.
flask sessions are only signed, not encrypted, you shouldn't be storing oauth tokens there unless you flip over to an actual encrypted serialization
ReplyDeleteQuite right.
ReplyDeleteYou could i suppose just encrypt in the twitter_authorized and decrypt in get_twitter_oauth_token using the flask secret. More lines.
This comment has been removed by a blog administrator.
ReplyDeleteSo... twitter_factory...
ReplyDeleteWhere does that come from? It looks like it has lots of shiny things, but neither Google nor Github are turning up anything.
ryepdx - best way is just to show you -
ReplyDeleteHave a look at https://gist.github.com/4085206
Could you please post the full code in one place, including all imports. Thanks
ReplyDelete