[openid-test commit] r44 - trunk/janrain-python

4 views
Skip to first unread message

codesite...@google.com

unread,
Jan 31, 2008, 5:15:19 AM1/31/08
to openi...@googlegroups.com
Author: heaven
Date: Thu Jan 31 02:15:04 2008
New Revision: 44

Modified:
trunk/janrain-python/janrain_python.py

Log:
fixed the consumer. it works and supports all assoc_mode options now.
next on
the todo list is support for 1.1 in addition to 2.0.


Modified: trunk/janrain-python/janrain_python.py
==============================================================================
--- trunk/janrain-python/janrain_python.py (original)
+++ trunk/janrain-python/janrain_python.py Thu Jan 31 02:15:04 2008
@@ -30,6 +30,8 @@

import BaseHTTPServer
import cgi
+import Cookie
+import cPickle
import datetime
import logging
import os
@@ -43,7 +45,7 @@
import wsgiref.util

from openid.server.server import Server as OpenIDServer
-from openid.store.filestore import FileOpenIDStore
+from openid.store import filestore
from openid.consumer import discover
from openid.consumer.consumer import Consumer as OpenIDConsumer

@@ -136,6 +138,8 @@
"""

OK = 'OK\n'
+CANCELLED = 'Cancelled\n'
+SETUP_NEEDED = 'Setup needed\n'

DISCOVERY = """
user_specified_url: %(claimed_id)s
@@ -245,10 +249,10 @@
self.output = [encoded_response.body]

def render(self, template, message='', status_code='200 OK',
- content_type='text/html', data={}):
+ content_type='text/html', headers=[], data={}):
"""Render the given template, including the extra (optional) values.
"""
- self.start_response(status_code, [('Content-Type', content_type)])
+ self.start_response(status_code, [('Content-Type', content_type)]
+ headers)
form = cgi.FieldStorage()
data_dict = {
'uri': self.uri,
@@ -302,7 +306,7 @@
Handler.__init__(self, environ, start_response)
self.checkid_immediate = checkid_immediate
self.checkid_setup = checkid_setup
- self.openid_server = OpenIDServer(FileOpenIDStore('.'), self.uri)
+ self.openid_server = OpenIDServer(filestore.FileOpenIDStore('.'), self.uri)

def post(self):
"""Handles associate and check_authentication requests."""
@@ -350,26 +354,58 @@
"""The base consumer handler."""
def __init__(self, *args):
Handler.__init__(self, *args)
+ arg_dict = self.arg_dict()

# set up the association store based on the assoc_mode query parameter
- store = None
- assoc_mode = self.arg_dict().get('assoc_mode')
+ store = filestore.FileOpenIDStore('.')
+
+ assoc_mode = arg_dict.get('assoc_mode')
if assoc_mode:
if assoc_mode == 'stateful':
- store = FileOpenIDStore('.')
- elif assoc_mode == 'stateful_new':
- # TODO(ryanb)
- store = FileOpenIDStore('.')
+ pass
+ elif assoc_mode in ('stateful_new', 'use_handle'):
+ # remove the other associations
+ for file, assoc in store._allAssocs():
+ if not (assoc_mode == 'use_handle' and
+ assoc.handle == arg_dict.get('assoc_handle')):
+ filestore._removeIfPresent(file)
+ store = filestore.FileOpenIDStore('.')
elif assoc_mode == 'stateless':
store = None
- elif assoc_mode == 'use_handle':
- # TODO(ryanb)
- pass
else:
assert False, 'bad assoc_mode value: %s' % assoc_mode

- # note that we don't support persistent session data
- self.openid_consumer = OpenIDConsumer({}, store)
+ # retrieve the session from the cookie, if available. obviously
not secure.
+ session = self.get_session_from_cookie()
+ self.openid_consumer = OpenIDConsumer(session, store)
+
+ def make_session_cookie(self):
+ """Pickles the session and returns it as a cookie value."""
+ expires = datetime.datetime.now() + datetime.timedelta(minutes=5)
+ expires_rfc822 = expires.strftime('%a, %d %b %Y %H:%M:%S -0800')
+
+ encoded = urllib.quote(cPickle.dumps(self.openid_consumer.session))
+ return 'janrain-python-session=%s; expires=%s' % (encoded, expires_rfc822)
+
+ def get_session_from_cookie(self):
+ """Recovers the user's session from their cookie and returns it.
If they
+ don't have a session cookie, returns None."""
+ cookies = os.environ.get('HTTP_COOKIE')
+ if cookies:
+ morsel = Cookie.BaseCookie(cookies).get('janrain-python-session')
+ if morsel:
+ session = cPickle.loads(urllib.unquote(morsel.value))
+ assert isinstance(session, dict)
+ return session
+
+ return {}
+
+ def render(self, *args, **kwargs):
+ """Adds the session cookie header, then passes through to Handler.render."""
+ # *optionally* stores the session in a cookie. if the client doesn't
+ # support cookies, no matter, the consumer flow will still work.
+ kwargs['headers'] = [('Set-Cookie', self.make_session_cookie())]
+ Handler.render(self, *args, **kwargs)

def get(self):
"""Handles consumer GET requests."""
@@ -380,8 +416,13 @@
response = self.openid_consumer.complete(args, self.uri)
if response.status == 'success':
self.render(OK, content_type='text/plain')
+ elif response.status == 'cancel':
+ self.render(CANCELLED, content_type='text/plain')
+ elif response.status == 'setup_needed':
+ self.render(SETUP_NEEDED, content_type='text/plain')
else:
- self.render(ERROR, 'Provider responded: %s' % response.status)
+ self.render(ERROR, 'Provider responded: %s %s' %
+ (response.status, response.message))

elif 'openid_identifier' in args:
# start with discovery
@@ -415,7 +456,9 @@
# start the flow!
return_to = self.uri + '.return_to'
redirect_to = auth_request.redirectURL(TRUST_ROOT, return_to)
- self.start_response('302 Found', [('Location', redirect_to)])
+ headers = [('Location', redirect_to),
+ ('Set-Cookie', self.make_session_cookie())]
+ self.start_response('302 Found', headers)

else:
# this is an initial GET. show the form.

Reply all
Reply to author
Forward
0 new messages