I've started to use web2py for a new project and I've found a couple of small
bugs on the gluon/contrib/login_methods/cas_auth.py file:

1. I'm serving the aplication using HTTPS, but the __init__ function hardcodes
   'http' as scheme; to fix it I've changed the following:

    @@ -57,7 +57,11 @@
             self.casusername = casusername
             http_host=current.request.env.http_x_forwarded_for
             if not http_host: http_host=current.request.env.http_host
    -        self.cas_my_url='http://%s%s'%( http_host, 
current.request.env.path_info )
    +        if current.request.env.wsgi_url_scheme in [ 'https', 'HTTPS' ]:
    +            scheme = 'https'
    +        else:
    +            scheme = 'http'
    +        self.cas_my_url='%s://%s%s'%( scheme, http_host, 
current.request.env.path_info )
         def login_url( self, next = "/" ):
             current.session.token=self._CAS_login()
             return next

2. I've developed a new login form (multi_cas_login_form) that allows the
   users to authenticate using the standard web2py authentication or use a
   remote CAS server from a list of configured servers; it works OK now, but
   while developing it I tested a chained authentication by mistake (a test
   application used the application configured to use the multi_cas_login_form
   as its CAS provider while I was logged using a remote CAS server, and the
   login failed).

   One of the problems was related to a simple typo: the _CAS_login function
   uses the ExpatError exception without importing it, to fix it I just moved
   the imports and qualified the exception:

    @@ -95,9 +99,9 @@
                         a,b,c = data[1].split( ':' )+[None,None]
                         return dict(user=a,email=b,username=c)
                     return None
    +            import xml.dom.minidom as dom
    +            import xml.parsers.expat as expat
                 try:
    -                import xml.dom.minidom as dom
    -                import xml.parsers.expat as expat
                     dxml=dom.parseString(data)
                     envelop = 
dxml.getElementsByTagName("cas:authenticationSuccess")
                     if len(envelop)>0:
    @@ -113,7 +117,7 @@
                                         res[key]=[res[key]]
                                     res[key].append(value)
                         return res
    -            except ExpatError: pass
    +            except expat.ExpatError: pass
                 return None # fallback
     
     
   Once the typo was fixed I found a real problem related to the XML
   processing: if there is a field without a value on the recived file, the
   line:

       value = x.childNodes[0].nodeValue.encode('utf8')
   
   fails because there are no elements on childNodes.
   
   My fix was also simple:

    @@ -103,7 +107,7 @@
                     if len(envelop)>0:
                         res = dict()
                         for x in envelop[0].childNodes:
    -                        if x.nodeName.startswith('cas:'):
    +                        if x.nodeName.startswith('cas:') and 
len(x.childNodes):
                                 key = x.nodeName[4:].encode('utf8')
                                 value = 
x.childNodes[0].nodeValue.encode('utf8')
                                 if not key in res:

   The problem was related to the standard way of generating a local user with
   CASAuth; the default mapping does not include the 'first_name' and
   'last_name' sent by the _CAS_login and that leaves the 'last_name' empty on
   the database (the 'first_name' is filled by the program using the
   'username' or the 'email') and when I called the nested authentication the
   _CAS_login received the XML 'last_name' with an empty value.
   
   For that bug I fixed my application by adding a full mapping to the CASAuth
   objects (I set the 'username' and copy the 'email', 'first_name' and
   'last_name' from the remote CAS server), but I believe that the fix is
   still valid anyway.

I'm attaching a full patch to this message with the described changes.

Greetings,

  Sergio.
   
-- 
Sergio Talens-Oliag <s...@iti.upv.es>       <http://www.iti.upv.es/>
Key fingerprint = FF77 A16B 9D09 FC7B 6656 CFAD 261D E19A 578A 36F2
--- web2py.orig/gluon/contrib/login_methods/cas_auth.py	2011-06-07 22:07:48.000000000 +0200
+++ web2py/gluon/contrib/login_methods/cas_auth.py	2011-06-21 19:09:12.549477656 +0200
@@ -57,7 +57,11 @@
         self.casusername = casusername
         http_host=current.request.env.http_x_forwarded_for
         if not http_host: http_host=current.request.env.http_host
-        self.cas_my_url='http://%s%s'%( http_host, current.request.env.path_info )
+        if current.request.env.wsgi_url_scheme in [ 'https', 'HTTPS' ]:
+            scheme = 'https'
+        else:
+            scheme = 'http'
+        self.cas_my_url='%s://%s%s'%( scheme, http_host, current.request.env.path_info )
     def login_url( self, next = "/" ):
         current.session.token=self._CAS_login()
         return next
@@ -95,15 +99,15 @@
                     a,b,c = data[1].split( ':' )+[None,None]
                     return dict(user=a,email=b,username=c)
                 return None
+            import xml.dom.minidom as dom
+            import xml.parsers.expat as expat
             try:
-                import xml.dom.minidom as dom
-                import xml.parsers.expat as expat
                 dxml=dom.parseString(data)
                 envelop = dxml.getElementsByTagName("cas:authenticationSuccess")
                 if len(envelop)>0:
                     res = dict()
                     for x in envelop[0].childNodes:
-                        if x.nodeName.startswith('cas:'):
+                        if x.nodeName.startswith('cas:') and len(x.childNodes):
                             key = x.nodeName[4:].encode('utf8')
                             value = x.childNodes[0].nodeValue.encode('utf8')
                             if not key in res:
@@ -113,7 +117,7 @@
                                     res[key]=[res[key]]
                                 res[key].append(value)
                     return res
-            except ExpatError: pass
+            except expat.ExpatError: pass
             return None # fallback
 
 

Reply via email to