Commits

Anonymous committed 57e9d10

Update demo app to reuse associations.

Comments (0)

Files changed (1)

 ################ Test Server #################################
 import BaseHTTPServer, cgi, Cookie, socket
 from openid2rp import *
+from time import time
 
 # supported providers
 providers = (
 # is authorized to make assertions about, but that the user doesn't control
 disco = {}
 
-# Mapping from OP Endpoint URL and association handle to association response
+# Mapping from OP Endpoint URL to association responses
 sessions = {}
 
 class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
                     return self.not_found()
                 prov = prov[0]
                 services, url, op_local = discover(prov[2])
+
+                # Get most recent association.  Establish association if it
+                # expired, or if none exist
+                now = time()
                 try:
-                    session = associate(services, url)
-                except ValueError, e:
-                    return self.error(str(e))
-                sessions[url, session['assoc_handle']] = session
+                    session, expire = sessions[url][-1]
+                except KeyError:
+                    try:
+                        session = associate(services, url)
+                    except ValueError, e:
+                        return self.error(str(e))
+                    try:
+                        sessions[url].append((session, now+int(session['expires_in'])))
+                    except KeyError:
+                        sessions[url] = [(session, now+int(session['expires_in']))]
+                else:
+                    if now > expire:
+                        try:
+                            session = associate(services, url)
+                        except ValueError, e:
+                            return self.error(str(e))
+                        sessions[url].append((session, now+int(session['expires_in'])))
+
                 self.send_response(307) # temporary redirect - do not cache
                 self.send_header("Location", request_authentication
                                  (services, url, session['assoc_handle'],
                 # Avoid repeating discovery when verifying assertions
                 disco[claimed] = url, op_local or claimed
 
+                # Get most recent association.  Establish association if it
+                # expired, or if none exist
+                now = time()
                 try:
-                    session = associate(services, url)
-                except ValueError, e:
-                    return self.error(str(e))
-                sessions[url, session['assoc_handle']] = session
+                    session, expire = sessions[url][-1]
+                except KeyError:
+                    try:
+                        session = associate(services, url)
+                    except ValueError, e:
+                        return self.error(str(e))
+                    try:
+                        sessions[url].append((session, now+int(session['expires_in'])))
+                    except KeyError:
+                        sessions[url] = [(session, now+int(session['expires_in']))]
+                else:
+                    if now > expire:
+                        try:
+                            session = associate(services, url)
+                        except ValueError, e:
+                            return self.error(str(e))
+                        sessions[url].append((session, now+int(session['expires_in'])))
+
                 self.send_response(307)
                 self.send_header("Location", request_authentication
                                  (services, url, session['assoc_handle'],
                 # signature on the assertion itself.  If it does not have an
                 # association stored, it MUST request that the OP verify the
                 # signature via Direct Verification
-                handle = query['openid.assoc_handle'][0]
                 try:
-                    session = sessions[disco_endpoint, handle]
+                    session = sessions[disco_endpoint]
                 except KeyError:
                     try:
                         verify_signature_directly(disco_endpoint, query)
                     except Exception, e:
-                        return self.error('Authentication failed: '+repr(e))
+                        return self.error('Verifying signature directly failed: '+repr(e))
                     signed, = query['openid.signed']
                     signed = signed.split(',')
                 else:
-                    try:
-                        signed = authenticate(session, querystring)
-                    except Exception, e:
-                        return self.error('Authentication failed: '+repr(e))
+                    assoc_handle, = query['openid.assoc_handle']
+                    for session, _ in session:
+                        if assoc_handle == session['assoc_handle']:
+                            try:
+                                signed = authenticate(session, querystring)
+                            except Exception, e:
+                                return self.error('Verifying signature with an association failed: '+repr(e))
+                            break
+                    else:
+                        try:
+                            verify_signature_directly(disco_endpoint, query)
+                        except Exception, e:
+                            return self.error('Verifying signature directly failed: '+repr(e))
+                        signed, = query['openid.signed']
+                        signed = signed.split(',')
 
                 payload = "Hello "+claimed_id+"\n"
                 ax = get_ax(querystring, get_namespaces(querystring), signed)