2010-05-02

GAEでgoogleさんにOAuth

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineでgoogleさんにOAuthしてみました。
Djangoを使ったpythonで実験しています。

まずは準備としてGoogleさんにサイトを登録して
Consumer Key

Consumer Secret
を手に入れる必要があります。

https://www.google.com/accounts/ManageDomains
で利用ドメインを登録します。すると
Manage registration
に登録したドメインが出るのでクリックします。
最初に登録したドメインのページにメタタグを埋め込んでサイトの確認を実行します。
すると
Target URL path prefix:
を入れる欄が出てくるようになるので
とりあえず
サイトでOAuthを利用するパスを入れてセーブします。
例:
 http://xxxx.xxxx.xxxx/oauth_test/index.html
 とかでOAuthを使ったもろもろをoauth_test配下に入れて置くならば、
 http://xxxx.xxxx.xxxx/oauth_test
 を登録します。
(実際は、どんなものを入れるのがよいのかいまいちよく分かっていません)

これで
Consumer Key

Consumer Secret
が発行されるのでメモしておきましょう。

今回OAuth関連の処理をするものとしてgdataを利用します。
http://code.google.com/p/gdata-python-client/
gdataは、OAuth用というよりもGoogleカレンダーとかドキュメントとかのAPIを扱う便利クライアントです。
OAuthしたらなんらかのgoogleのAPIを利用するのでこれを利用します。
取得したら、
Djangoプロジェクトディレクトリ直下に
atom
gdata
をコピーします。

今回、OAuthを試すアプリとして
oauth_test
を作ります。
これはgoogleドキュメントに登録してあるデータ一覧を取得するものにしてみます。
なのでsettings.pyに使えるように設定しておきます。
またoauth_testでは認証がかかるようにapp.yamlに以下を追加します。

- url: /oauth_test/.*
script: common/appenginepatch/main.py
login: required

なので今回用意したものは以下のような感じです
Djangoルート
|-atom
|-gdata
|-oauth_test
|-template
| |-index.html
|-settings.py
|-urls.py
|-urlsauto.py
|-views.py

oauth_test配下のものはざっと以下のような感じです。

settigns.py

from ragendja.settings_post import settings
settings.CONSUMER_KEY = '取得したConsumer Keyを入れます'
settings.CONSUMER_SECRET = '取得したConsumer Secretを入れます'


urlsauto.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
rootpatterns = patterns('',
(r'^oauth_test/', include('oauth_test.urls')),)


urls.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
urlpatterns = patterns('oauth_test.views',
(r'^$', 'index'),
(r'^oauth_set/$', 'oauth_set'),
(r'^oauth_callback/$', 'oauth_callback'),
(r'^oauth_revork/$', 'oauth_revork'),
)


view.py

# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from ragendja.template import render_to_response
from django.conf import settings
from google.appengine.api import users

import gdata.gauth
import gdata.docs.client
import gdata.docs.data

APP_NAME = 'oauthMyTest'
def index(request):
payload = dict()
login = users.get_current_user()
#すでに登録済みかどうかを確認します
#gdata.gauth.Ae*を利用することでGoogle App Engineのデータストアに
#取得したOAuthのトークンとシークレットをオブジェクトして格納して出し入れできます。
#memcacheのようにキーとtokenがセットになっています。
#ここではログインユーザのuser_idをキーにしています。
token = gdata.gauth.AeLoad(login.user_id())
if token == None:
payload['have_token'] = False
else:
payload['have_token'] = True
#ドキュメント一覧を取得します
#client.ssl = Trueを必ずつけましょう
#付け忘れるとInvalid Tokenとか言われて悩みます
client = gdata.docs.client.DocsClient(source=APP_NAME)
client.ssl = True
client.auth_token = gdata.gauth.AeLoad(login.user_id())
payload['feed'] = client.get_doclist()
return render_to_response(request, 'oauth_test/index.html',payload)

def oauth_set(request):
#googleにリダイレクト処理をします
SCOPES = ['https://docs.google.com/feeds/']
callback_url = 'http://%s/oauth_test/oauth_callback/' % request.get_host()
client = gdata.docs.client.DocsClient(source=APP_NAME)
request_token = client.GetOAuthToken(SCOPES, callback_url, settings.CONSUMER_KEY, consumer_secret=settings.CONSUMER_SECRET)
login = users.get_current_user()
#callbackしてきたときに利用できるように一時的にtokenを格納します。
gdata.gauth.AeSave(request_token, "tmp_" + login.user_id())
return HttpResponseRedirect(request_token.generate_authorization_url())

def oauth_callback(request):
#アクセス用のトークンとトークンシークレットを格納します
login = users.get_current_user()
#一時的に格納したtokenを取り出し削除しておきます。
saved_request_token = gdata.gauth.AeLoad("tmp_" + login.user_id())
gdata.gauth.AeDelete("tmp_" + login.user_id())
request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, request.build_absolute_uri())
client = gdata.docs.client.DocsClient(source=APP_NAME)
try:
#ここでアクセストークンを取得して格納
access_token = client.GetAccessToken(request_token)
gdata.gauth.AeSave(access_token, login.user_id())
except:
logging.info('cant get access token')
return HttpResponseRedirect('/oauth_test/')

def oauth_revork(request):
#取得したtokenを破棄します
login = users.get_current_user()
gdata.gauth.AeDelete(login.user_id())
return HttpResponseRedirect('/oauth_test/')


template/index.html

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
lang="{% firstof LANGUAGE_CODE 'en' %}">
<head>
<title>oauth_test</title>
</head>
<body>
{% if have_token %}
<a href="/oauth_test/oauth_set/">登録する</a>
{% else %}
<ul>
{% for entry in feed.entry %}
<li>{{ entry.title.text }}</li>
{% endfor %}
</ul>
<hr>
<a href="/oauth_test/oauth_revork/">登録を解除する</a>
{% endif %}
</body>
</html>


こんな感じです。
TwitterのOAuthと比べるとちょっとめんどっちい感じです。
コメントを投稿