Twitter OAuth 自動化 with GAE/Py (Python-twoauth 版)

以前、Twitter OAuth 対応(Python-twoauth 版)も書きましたが、機会があったので、それの自動化版を作ってみました。
今作ってるものの部品ですけどw

動作環境は Google App Engine for Python
ライブラリは Python-twoauth を使用してます。

アプリの設定

Twitter の「Application Settings」で
「Application Type」を「Browser」にして、
「Callback URL」をユーザ登録を行うページにすることを忘れないで下さい。
ここで指定した URL にユーザが「Allow」を押した後でリダイレクトされて返ってきます。
「Callback URL」の入力欄は「Application Type:Browser」を選択した時点で出ます。
でも「Callback URL」が空欄のまま登録すると、自動的に「Application Type:Client」になりますのでご注意ください。
マヂで。
# これで数日ハマった…。


今回はとりあえず「http://[application url]/add」としておきます。
[application url]は動かす環境に合わせてください。
多分ローカルでは動きませんです。

クラス準備

処理を書くクラスの準備だけしておきます。
Index がボタン表示ページ、
Add が Callback で戻ってきて登録処理を行うページです。
各メソッド内は後で。

# -*- coding: utf-8 -*-
import cgi, os
import twoauth, Cookie
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

class Index(webapp.RequestHandler):
    def get(self):
        # 認証URL発行処理書くよ
        pass

class Add(webapp.RequestHandler):
    def get(self):
        # 認証結果取得処理書くよ
        pass

application = webapp.WSGIApplication(
    [('/', Index),
     ('/add/*', Add)
    ], 
    debug=True)

def main():
    run_wsgi_app(application)
    
if __name__ == "__main__":
    main()

認証URLの発行

要するに「Signin with Twitter」ボタンの中身です。
ボタンの画像は Overview of "Sign in with Twitter" の下部などにあるので適当に。


まず、URL発行処理。
途中 Cookie もぐもぐしてますが、これは認証結果の受け取りに必要なものです。

class Index(webapp.RequestHandler):
    def get(self):
        ckey = "[your application's consumer Key]"
        csec = "[your application's consumer Secret]"
        oauth = twoauth.oauth(ckey, csec)
        req_token = oauth.request_token()
        url = oauth.authorize_url(req_token)
        
        # 使用した Request Token は認証後に使うので保持
        oauth_token = req_token['oauth_token']
        oauth_token_secret = req_token['oauth_token_secret']
        
        # Cookie(oauth_token_secret)もぐもぐ
        c = Cookie.SimpleCookie()
        c['oauth_token_secret'] = oauth_token_secret
        self.response.headers.add_header(
            'Set-Cookie', c.output(header='')
        )

        # テンプレートに渡す
        template_values = {'authorize_url' : url, }
        path = os.path.join(
               os.path.dirname(__file__), 
               '../templates/index.html'
        )
        return self.response.out.write(
               template.render(path, template_values))


続いて、ボタン表示するHTML「index.html」。
まぁ適当です。細かいところは省いてます。

<a href="{{ authorize_url }}">
    <img src="[ボタンの画像名].gif" width="165" height="28" border="0" />
</a>


この状態で、localhost で動かせば、OAuth の認証確認画面までは行く筈です。
Callback URLを忘れてるか、Callback URLが有効でない場合は、8桁の数字が表示されます。

認証結果取得

Twitterから認証結果が返ってきてるので取得します。
もぐもぐした Cookie から oauth_token_secret を取得します。

class Add(webapp.RequestHandler):
    def get(self):
        ckey = "[your application's consumer Key]"
        csec = "[your application's consumer Secret]"
        oauth = twoauth.oauth(ckey, csec)

        # Twitter からのレスポンスに oauth_token が含まれるので取得
        oauth_token = self.request.GET['oauth_token']
        
        # Cookie に渡した oauth_token_secret を取得
        c = Cookie.SimpleCookie(
              os.environ.get('HTTP_COOKIE', '' ))
        oauth_token_secret = c['oauth_token_secret'].value

        # Request Token 組み立て
        req_token = {"oauth_token" : oauth_token,
                     "oauth_token_secret": oauth_token_secret}
        # PIN は無いけど引数で要るのでダミー
        pin = "dummy"
        # Access Token 取得
        acc_token = oauth.access_token(req_token, pin)
        
        # 取得できるデータは以下の4つ
        user_id = acc_token["user_id"]
        screen_name = acc_token["screen_name"]
        token_key = acc_token["oauth_token"]
        token_sec = acc_token["oauth_token_secret"]

        # あとは BigTable に登録とか何とか。割愛。


以上で、認証処理が出来ました。
あとは取得した Access Token Key と Access Token Secret を BigTable に保存するなり何なりして、今後のログインに使用します。
ここまで出来れば、Deploy して確認すると、よく見る OAuth 認証の処理が出来ている! …ハズ!w


何か間違い等ありましたらご指摘下さい…。m(_ _)m

余談・雑感

  • Cookieに食わせるよりもまだ良いやり方があるかもしれない。
  • ボタンに直接認証URLを指定するんじゃなくて、処理内でリダイレクトする方法もありますが、GAEで外部へリダイレクトって出来たっけ?
  • Cookie 使ってるので、携帯からだと動作しない可能性あり。その辺の切り分けとか。
  • has_key とかのチェックは省略しましたw