2008年5月29日

oAuthをWSGIで。


oAuthについてるexampleがBaseHTTPServerベースだったので、wsgiに直してみた。
単にリクエストとレスポンスをWebObにしただけだが、clientはそのまま使って動作確認しながら、oAuthの流れを確認できた。

OAuthRequestの生成やOAuthErrorのハンドリングは、ミドルウェアにすべきだったかな。
そうすれば、Selectorあたりのディスパッチャが使えるしね。


class Application(object):
def __init__(self, *args, **kwargs):
self.oauth_server = oauth.OAuthServer(MockOAuthDataStore())
self.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT())
self.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1())

def __call__(self, environ, start_response):
request = webob.Request(environ)
response = webob.Response(request=request)
postdata = None
if request.method == 'POST':
length = int(request.content_length)
print 'content_length %d' % length
postdata = request.environ['wsgi.input'].read(length)
print 'postdata:: %s' % postdata
oauth_request = oauth.OAuthRequest.from_request(request.method,
request.url,
headers=request.headers,
postdata=postdata)
if request.path.startswith(REQUEST_TOKEN_URL):
try:
token = self.oauth_server.fetch_request_token(oauth_request)
response.status = 200
response.body = token.to_string()
return response(environ, start_response)
except oauth.OAuthError, err:
return self.errorResponse(response, err)

if request.path.startswith(AUTHORIZATION_URL):
try:
token = self.oauth_server.fetch_request_token(oauth_request)

callback = self.oauth_server.get_callback(oauth_request)
token = self.oauth_server.authorize_token(token, None)
token_key = urllib.urlencode({'oauth_token': token.key})

response.status = 200
response.body = """callback:%(callback)s
token key: %(token_key)s""" % dict(callback=callback, token=token, token_key=token_key)
return response(environ, start_response)
except oauth.OAuthError, err:
return self.errorResponse(response, err)

# access token
if request.path.startswith(ACCESS_TOKEN_URL):
try:
# create an access token
token = self.oauth_server.fetch_access_token(oauth_request)
# send okay response
response.status = 200
# return the token
response.body = token.to_string()
return response(environ, start_response)
except oauth.OAuthError, err:
return self.errorResponse(response, err)

if request.path.startswith(RESOURCE_URL):
try:
# verify the request has been oauth authorized
consumer, token, params = self.oauth_server.verify_request(oauth_request)
# send okay response
response.status = 200
# return the extra parameters - just for something to return
#response.body = str(params)
response.body = "OK auth."
return response(environ, start_response)
except oauth.OAuthError, err:
print err.message
return self.errorResponse(response, environ, start_response, err)

response.status = 404
response.body = response.status
return response(environ, start_response)


def errorResponse(self, response, environ, start_response, err=None):
response.status = 401
header = oauth.build_authenticate_header(realm=REALM)
for k, v in header.iteritems():
response.headers[k] = v
return response(environ, start_response)
Blogged with the Flock Browser