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 <[email protected]> <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