Commits

Martin von Löwis  committed 9f37ef4

Issue #3: Interpret response parameter as literal QUERY_STRING.

  • Participants
  • Parent commits 8adb13c

Comments (0)

Files changed (3)

 1.3:
 
 * Add get_sreg. Deprecate get_username.
+* Specify that response parameters are always literal QUERY_STRINGs;
+  parse_qs results are still supported for compatibility.
 
 1.2 (2010-07-02):
 

File doc/index.rst

 
   Process an authentication response.  session must be the established
   session (minimally including assoc_handle and mac_key), response is
-  the query string as parsed by cgi.parse_qs.  If authentication
-  succeeds, return the list of signed fields.  If the user was not
-  authenticated, NotAuthenticated is raised.  If the HTTP request is
-  invalid (missing parameters, failure to validate signature),
-  different exceptions will be raised, typically ValueError.
+  the query string as given in the original URL (i.e. as the CGI
+  variable QUERY_STRING).  If authentication succeeds, return the
+  list of signed fields.  If the user was not authenticated,
+  NotAuthenticated is raised.  If the HTTP request is invalid (missing
+  parameters, failure to validate signature), different exceptions
+  will be raised, typically ValueError.
 
   Callers must check openid.response_nonce for replay attacks.
 

File openid2rp.py

 class NotAuthenticated(Exception):
     pass
 
+def _prepare_response(response):
+    if isinstance(response, str):
+        return cgi.parse_qs(response)
+    # backwards compatibility: allow caller to pass parse_qs result
+    # already
+    pass
+    return response
+
 def authenticate(session, response):
-    '''Process an authentication response.
-    session must be the established session (minimally including
-    assoc_handle and mac_key), response is the query string as parsed
-    by cgi.parse_qs.
-    If authentication succeeds, return the list of signed fields.
-    If the user was not authenticated, NotAuthenticated is raised.
-    If the HTTP request is invalid (missing parameters, failure to
-    validate signature), different exceptions will be raised, typically
-    ValueError.
+    '''Process an authentication response.  session must be the
+    established session (minimally including assoc_handle and
+    mac_key), response the query string as given in the original URL
+    (i.e. as the CGI variable QUERY_STRING).  If authentication
+    succeeds, return the list of signed fields.  If the user was not
+    authenticated, NotAuthenticated is raised.  If the HTTP request is
+    invalid (missing parameters, failure to validate signature),
+    different exceptions will be raised, typically ValueError.
 
     Callers must check openid.response_nonce for replay attacks.
     '''
 
+    response = _prepare_response(response)
+
     # 1.1 compat: openid.ns may not be sent
     # if response['openid.ns'][0] != 'http://specs.openid.net/auth/2.0':
     #    raise ValueError('missing openid.ns')
     return stamp
 
 def get_namespaces(resp):
+    resp = _prepare_response(resp)
     res = {}
     for k, v in resp.items():
         if k.startswith('openid.ns.'):
     ax = ns["http://openid.net/srv/ax/1.0"]+"."
     oax = "openid."+ax
     res = {}
+    resp = _prepare_response(resp)
     for k, v in resp.items():
         if k.startswith(oax+"type."):
             k = k.rsplit('.',1)[1]
     """Return the dictionary of simple registration parameters in resp,
     with the openid.sreg. prefix stripped."""
     res = {}
+    resp = _prepare_response(resp)
     for k, v in resp.items():
         if k.startswith('openid.sreg.'):
             k = k[len('openid.sreg.'):]
 def get_email(resp):
     "Return the email address embedded response, or None."
 
+    resp = _prepare_response(resp)
     validated = resp['openid.signed'][0]
 
     # SREG 1.0; doesn't require namespace, as the protocol doesn't
     This function is deprecated; use get_ax and get_sreg instead.
     """
 
+    resp = _prepare_response(resp)
     validated = resp['openid.signed'][0]
     if 'openid.sreg.nickname' in resp and \
        'sreg.nickname' in validated:
         path = self.path
         i = path.rfind('?')
         if i >= 0:
-            query = cgi.parse_qs(path[i+1:])
+            querystring = path[i+1:]
+            query = cgi.parse_qs(querystring)
             path = path[:i]
         else:
             query = {}
                 if not session:
                     return self.error('Not authenticated (no session)')
                 try:
-                    signed = authenticate(session, query)
+                    signed = authenticate(session, querystring)
                 except Exception, e:
                     self.error("Authentication failed: "+repr(e))
                     return
                         return self.error('Incomplete signature')
                     claimed = query['openid.identity'][0]
                 payload = "Hello "+claimed+"\n"
-                ax = get_ax(query, get_namespaces(query), signed)
-                sreg = get_sreg(query, signed)
-                email = get_email(query)
+                ax = get_ax(querystring, get_namespaces(querystring), signed)
+                sreg = get_sreg(querystring, signed)
+                email = get_email(querystring)
                 if email:
                     payload += 'Your email is '+email+"\n"
                 else: