そろそろGAE上でユーザ登録が必要なサービスを作りたいのですが、ユーザ登録周りの実装はやりたくないので、twitterのOAuthを代わりに使ってみる事にしました。twitterのAPIを叩くのにこれまではtwythonを使っていたのですが,OAuthに対応していなかったので、今回はtweepyを使います。以前2-legged OAuthを試してみましたが、今回は3-legged OAuthです。
twitterのOAuth認証によるログイン、ログアウトとログイン後にユーザのタイムライン表示と、tweetを実装しています。ロジックのソースは以下になりますが、まず動作しているサンプルを見るのが早いと思います。
# -*- coding: utf-8 -*-
import os
import cgi
import logging
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
import wsgiref.handlers
from google.appengine.api import memcache
import uuid
import tweepy
from simple_cookie2 import Cookies
CONSUMER_KEY = 'your consumer key'
CONSUMER_SECRET = 'your consumer secret'
CALLBACK_URL = 'http://127.0.0.1:8080/oauth_cb'
SESSION_EXPIRE = 300
# ユーザがtwitter認証を行う際のリクエストトークンを保持するモデル
class RequestToken(db.Model):
token_key = db.StringProperty(required=True)
token_secret = db.StringProperty(required=True)
# ログインしている場合はタイムライン表示
class Home(webapp.RequestHandler):
def get(self):
cookie = Cookies(self, max_age=SESSION_EXPIRE)
if not cookie.has_key('sid'):
cookie['sid'] = str(uuid.uuid4()) # セッション開始
(timeline, username) = (None, None)
access_token = memcache.get(cookie['sid'])
if access_token:
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(access_token.key, access_token.secret)
username = auth.get_username()
api = tweepy.API(auth_handler=auth)
timeline = api.home_timeline(count=10)
self.response.out.write(template.render('timeline.html', {'username':username, 'timeline': timeline}))
# tweet
class Update(webapp.RequestHandler):
def post(self):
cookie = Cookies(self)
access_token = memcache.get(cookie['sid'])
if access_token:
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(access_token.key, access_token.secret)
api = tweepy.API(auth_handler=auth)
api.update_status(status=self.request.get('status'))
self.redirect('/')
# twitterのOAuth認証
class OAuth(webapp.RequestHandler):
def get(self):
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK_URL)
auth_url = auth.get_authorization_url()
request_token = RequestToken(token_key=auth.request_token.key, token_secret=auth.request_token.secret)
request_token.put()
self.redirect(auth_url) # twitterの認証画面へリダイレクト
# twitterのOAuth認証後のコールバック
class OAuthCB(webapp.RequestHandler):
def get(self):
request_token_key = self.request.get("oauth_token")
request_verifier = self.request.get('oauth_verifier')
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
request_token = RequestToken.gql("WHERE token_key=:1", request_token_key).get()
auth.set_request_token(request_token.token_key, request_token.token_secret)
access_token = auth.get_access_token(request_verifier)
cookie = Cookies(self)
memcache.set(cookie['sid'], access_token, SESSION_EXPIRE)
self.redirect('/')
# ログアウト
# twitter認証側のCookieはいじれないのでセッションを削除する
class Logout(webapp.RequestHandler):
def get(self):
cookie = Cookies(self)
if cookie.has_key('sid'):
memcache.delete(cookie['sid'])
del cookie['sid']
self.redirect('/')
application = webapp.WSGIApplication(
[
('/', Home),
('/update', Update),
('/logout', Logout),
('/oauth', OAuth),
('/oauth_cb', OAuthCB),
],
debug=True)
if __name__ == "__main__":
run_wsgi_app(application)
少しややこしいですね。tweepyはよく作られたライブラリなので、一度ソースを読んでみる事をお薦めしますが、OAuth認証が必要なtwitter apiを使う場合の処理シーケンスをおおざっぱに言うと、以下のようになります。
- tweepy.OAuthHandlerにConsumerKey、ConsumerSecret, RequestToken, ユーザの認証を示すVerifierを食わせてaccess tokenを得る
- tweepy.APIを作成する際に1のOAuthHandlerを食わせて、認証済みAPIオブジェクトを作成する
- 認証済みAPIオブジェクトを使って各種API呼出しを行う
access tokenがあれば認証済みOAuthHandlerを再構築できるので,僕はセッションIDをキーにaccess tokenをmemcacheに保存しています。@ITの入門記事やoauthの仕様と見比べながら読むと理解が早いかもしれません。
またセッション周りについては先ほどの記事のsimple_cookieを使用しています。
1 thought on “tweepyでtwitterの3-legged OAuth認証を試してみた(GoogleAppEngine)”