better cas compliance
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 1.99.3 (2011-12-02 17:48:23) dev
|
Version 1.99.3 (2011-12-02 23:27:41) dev
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class CasAuth( object ):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, g=None, ### g for backward compatibility ###
|
def __init__(self, g=None, ### g for backward compatibility ###
|
||||||
urlbase = "https://web2py.com/cas/cas",
|
urlbase = "https://web2py.com/cas/cas",
|
||||||
actions=['login','check','logout'],
|
actions=['login','validate','logout'],
|
||||||
maps=dict(username=lambda v:v.get('username',v['user']),
|
maps=dict(username=lambda v:v.get('username',v['user']),
|
||||||
email=lambda v:v.get('email',None),
|
email=lambda v:v.get('email',None),
|
||||||
user_id=lambda v:v['user']),
|
user_id=lambda v:v['user']),
|
||||||
@@ -97,7 +97,7 @@ class CasAuth( object ):
|
|||||||
if data.startswith('yes') or data.startswith('no'):
|
if data.startswith('yes') or data.startswith('no'):
|
||||||
data = data.split('\n')
|
data = data.split('\n')
|
||||||
if data[0]=='yes':
|
if data[0]=='yes':
|
||||||
a,b,c = data[1].split( ':' )+[None,None]
|
a=b=c = data[1]
|
||||||
return dict(user=a,email=b,username=c)
|
return dict(user=a,email=b,username=c)
|
||||||
return None
|
return None
|
||||||
import xml.dom.minidom as dom
|
import xml.dom.minidom as dom
|
||||||
|
|||||||
+66
-32
@@ -880,6 +880,8 @@ class Auth(object):
|
|||||||
settings.cas_provider = cas_provider
|
settings.cas_provider = cas_provider
|
||||||
settings.cas_actions = {'login':'login',
|
settings.cas_actions = {'login':'login',
|
||||||
'validate':'validate',
|
'validate':'validate',
|
||||||
|
'servicevalidate':'serviceValidate',
|
||||||
|
'proxyvalidate':'proxyValidate',
|
||||||
'logout':'logout'}
|
'logout':'logout'}
|
||||||
settings.cas_maps = None
|
settings.cas_maps = None
|
||||||
settings.extra_fields = {}
|
settings.extra_fields = {}
|
||||||
@@ -1141,7 +1143,11 @@ class Auth(object):
|
|||||||
if args(1) == self.settings.cas_actions['login']:
|
if args(1) == self.settings.cas_actions['login']:
|
||||||
return self.cas_login(version=2)
|
return self.cas_login(version=2)
|
||||||
elif args(1) == self.settings.cas_actions['validate']:
|
elif args(1) == self.settings.cas_actions['validate']:
|
||||||
return self.cas_validate(version=2)
|
return self.cas_validate(version=1)
|
||||||
|
elif args(1) == self.settings.cas_actions['servicevalidate']:
|
||||||
|
return self.cas_validate(version=2, proxy=False)
|
||||||
|
elif args(1) == self.settings.cas_actions['proxyvalidate']:
|
||||||
|
return self.cas_validate(version=2, proxy=True)
|
||||||
elif args(1) == self.settings.cas_actions['logout']:
|
elif args(1) == self.settings.cas_actions['logout']:
|
||||||
return self.logout(next=request.vars.service or DEFAULT)
|
return self.logout(next=request.vars.service or DEFAULT)
|
||||||
else:
|
else:
|
||||||
@@ -1381,8 +1387,9 @@ class Auth(object):
|
|||||||
Field('user_id', settings.table_user, default=None,
|
Field('user_id', settings.table_user, default=None,
|
||||||
label=self.messages.label_user_id),
|
label=self.messages.label_user_id),
|
||||||
Field('created_on','datetime',default=now),
|
Field('created_on','datetime',default=now),
|
||||||
Field('url',requires=IS_URL()),
|
Field('service',requires=IS_URL()),
|
||||||
Field('uuid'),
|
Field('ticket'),
|
||||||
|
Field('renew', 'boolean', default=False),
|
||||||
*settings.extra_fields.get(settings.table_cas_name,[]),
|
*settings.extra_fields.get(settings.table_cas_name,[]),
|
||||||
**dict(
|
**dict(
|
||||||
migrate=self.__get_migrate(
|
migrate=self.__get_migrate(
|
||||||
@@ -1509,52 +1516,79 @@ class Auth(object):
|
|||||||
log=DEFAULT,
|
log=DEFAULT,
|
||||||
version=2,
|
version=2,
|
||||||
):
|
):
|
||||||
request, session = current.request, current.session
|
request = current.request
|
||||||
|
response = current.response
|
||||||
|
session = current.session
|
||||||
db, table = self.db, self.settings.table_cas
|
db, table = self.db, self.settings.table_cas
|
||||||
session._cas_service = request.vars.service or session._cas_service
|
session._cas_service = request.vars.service or session._cas_service
|
||||||
if not request.env.http_host in self.settings.cas_domains or \
|
if not request.env.http_host in self.settings.cas_domains or \
|
||||||
not session._cas_service:
|
not session._cas_service:
|
||||||
raise HTTP(403,'not authorized')
|
raise HTTP(403,'not authorized')
|
||||||
def allow_access():
|
def allow_access(interactivelogin=False):
|
||||||
row = table(url=session._cas_service,user_id=self.user.id)
|
row = table(service=session._cas_service,user_id=self.user.id)
|
||||||
if row:
|
if row:
|
||||||
row.update_record(created_on=request.now)
|
row.update_record(created_on=request.now)
|
||||||
uuid = 'LT-'+row.uuid
|
ticket = row.ticket
|
||||||
else:
|
else:
|
||||||
uuid = 'LT-'+web2py_uuid()
|
ticket = 'ST-'+web2py_uuid()
|
||||||
table.insert(url=session._cas_service, user_id=self.user.id,
|
table.insert(service=session._cas_service, user_id=self.user.id,
|
||||||
uuid=uuid, created_on=request.now)
|
ticket=ticket, created_on=request.now, renew=interactivelogin)
|
||||||
url = session._cas_service
|
service = session._cas_service
|
||||||
del session._cas_service
|
del session._cas_service
|
||||||
redirect(url+"?ticket="+uuid)
|
if request.vars.has_key('warn'):
|
||||||
if self.is_logged_in():
|
response.headers['refresh'] = "5;URL=%s"%service+"?ticket="+ticket
|
||||||
allow_access()
|
return A("Continue to %s"%service,
|
||||||
|
_href=service+"?ticket="+ticket)
|
||||||
|
else:
|
||||||
|
redirect(service+"?ticket="+ticket)
|
||||||
|
if self.is_logged_in() and not request.vars.has_key('renew'):
|
||||||
|
return allow_access()
|
||||||
|
elif not self.is_logged_in() and request.vars.has_key('gateway'):
|
||||||
|
redirect(service)
|
||||||
def cas_onaccept(form, onaccept=onaccept):
|
def cas_onaccept(form, onaccept=onaccept):
|
||||||
if not onaccept is DEFAULT: onaccept(form)
|
if not onaccept is DEFAULT: onaccept(form)
|
||||||
allow_access()
|
return allow_access(interactivelogin=True)
|
||||||
return self.login(next,onvalidation,cas_onaccept,log)
|
return self.login(next,onvalidation,cas_onaccept,log)
|
||||||
|
|
||||||
|
|
||||||
def cas_validate(self, version=2):
|
def cas_validate(self, version=2, proxy=False):
|
||||||
request = current.request
|
request = current.request
|
||||||
db, table = self.db, self.settings.table_cas
|
db, table = self.db, self.settings.table_cas
|
||||||
current.response.headers['Content-Type']='text'
|
current.response.headers['Content-Type']='text'
|
||||||
ticket = table(uuid=request.vars.ticket)
|
ticket = request.vars.ticket
|
||||||
if ticket: # and ticket.created_on>request.now-datetime.timedelta(60):
|
renew = True if request.vars.has_key('renew') else False
|
||||||
user = self.settings.table_user(ticket.user_id)
|
row = table(ticket=ticket)
|
||||||
fullname = user.first_name+' '+user.last_name
|
if row:
|
||||||
if version == 1:
|
if self.settings.login_userfield:
|
||||||
raise HTTP(200,'yes\n%s:%s:%s'%(user.id,user.email,fullname))
|
userfield = self.settings.login_userfield
|
||||||
# assume version 2
|
elif 'username' in table.fields:
|
||||||
username = user.get('username',user.email)
|
userfield = 'username'
|
||||||
raise HTTP(200,'<?xml version="1.0" encoding="UTF-8"?>\n'+\
|
else:
|
||||||
TAG['cas:serviceResponse'](
|
userfield = 'email'
|
||||||
TAG['cas:authenticationSuccess'](
|
# If ticket is a service Ticket and RENEW flag respected
|
||||||
TAG['cas:user'](username),
|
if ticket[0:3] == 'ST-' and not ((row.renew and renew) ^ renew):
|
||||||
*[TAG['cas:'+field.name](user[field.name]) \
|
user = self.settings.table_user(row.user_id)
|
||||||
for field in self.settings.table_user \
|
row.delete_record()
|
||||||
if field.readable]),
|
if version == 1:
|
||||||
**{'_xmlns:cas':'http://www.yale.edu/tp/cas'}).xml())
|
raise HTTP(200,'yes\n%s'%(user[userfield]))
|
||||||
|
# assume version 2
|
||||||
|
username = user.get('username',user[userfield])
|
||||||
|
raise HTTP(200,'<?xml version="1.0" encoding="UTF-8"?>\n'+\
|
||||||
|
TAG['cas:serviceResponse'](
|
||||||
|
TAG['cas:authenticationSuccess'](
|
||||||
|
TAG['cas:user'](username),
|
||||||
|
*[TAG['cas:'+field.name](user[field.name]) \
|
||||||
|
for field in self.settings.table_user \
|
||||||
|
if field.readable]),
|
||||||
|
**{'_xmlns:cas':'http://www.yale.edu/tp/cas'}).xml())
|
||||||
|
else:
|
||||||
|
raise HTTP(200,'<?xml version="1.0" encoding="UTF-8"?>\n'+\
|
||||||
|
TAG['cas:serviceResponse'](
|
||||||
|
TAG['cas:authenticationFailure'](),
|
||||||
|
**{'_xmlns:cas':'http://www.yale.edu/tp/cas'}).xml())
|
||||||
|
# Delete ticket if not already done
|
||||||
|
row.delete_record()
|
||||||
|
|
||||||
if version == 1:
|
if version == 1:
|
||||||
raise HTTP(200,'no\n')
|
raise HTTP(200,'no\n')
|
||||||
# assume version 2
|
# assume version 2
|
||||||
|
|||||||
Reference in New Issue
Block a user