From 76f3384aae23df6d59ffdf6d99515ba6a9cbc559 Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Thu, 1 Feb 2018 14:04:47 +0000 Subject: [PATCH 1/3] Allow choosing a saml entityid Allows you to pick an entityid when using federation XML data or an MDQ with many entries. Pysaml2's MDQ metadata is loaded lazily, after you provide a key, so it's necessary to pass the entityid as a key --- gluon/contrib/login_methods/saml2_auth.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/gluon/contrib/login_methods/saml2_auth.py b/gluon/contrib/login_methods/saml2_auth.py index 462d9845..d80a13ba 100644 --- a/gluon/contrib/login_methods/saml2_auth.py +++ b/gluon/contrib/login_methods/saml2_auth.py @@ -104,11 +104,12 @@ def obj2dict(obj, processed=None): types.BuiltinFunctionType, types.BuiltinMethodType)) -def saml2_handler(session, request, config_filename = None): +def saml2_handler(session, request, config_filename = None, entityid = None): config_filename = config_filename or os.path.join(request.folder,'private','sp_conf') client = Saml2Client(config_file = config_filename) - idps = client.metadata.with_descriptor("idpsso") - entityid = idps.keys()[0] + if not entityid: + idps = client.metadata.with_descriptor("idpsso") + entityid = idps.keys()[0] bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST] binding, destination = client.pick_binding( "single_sign_on_service", bindings, "idpsso", entity_id=entityid) @@ -145,7 +146,7 @@ class Saml2Auth(object): username=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0], email=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0], user_id=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0], - ), logout_url=None, change_password_url=None): + ), logout_url=None, change_password_url=None, entityid=None): self.config_file = config_file self.maps = maps @@ -154,9 +155,12 @@ class Saml2Auth(object): # URL to let users change their password in the IDP system self.saml_change_password_url = change_password_url + + # URL to specify an IDP if using federation metadata or an MDQ + self.entityid = entityid def login_url(self, next="/"): - d = saml2_handler(current.session, current.request) + d = saml2_handler(current.session, current.request, entityid=self.entityid) if 'url' in d: redirect(d['url']) elif 'error' in d: From 5dcbae0b379cc78373cb55a84d66e96cfb2199e1 Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Fri, 2 Feb 2018 11:03:04 +0000 Subject: [PATCH 2/3] Update saml2_auth.py Pass along any _next url var as part of the outstanding queries, so web2py will know where to send the user once they come back from singing on. Useful if the SAML auth is part of a CAS, because otherwise the user is sent from the CAS consumer -> CAS -> SSO -> CAS, and is never returned to the consumer application --- gluon/contrib/login_methods/saml2_auth.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gluon/contrib/login_methods/saml2_auth.py b/gluon/contrib/login_methods/saml2_auth.py index d80a13ba..9439443d 100644 --- a/gluon/contrib/login_methods/saml2_auth.py +++ b/gluon/contrib/login_methods/saml2_auth.py @@ -121,6 +121,8 @@ def saml2_handler(session, request, config_filename = None, entityid = None): req_id, req = client.create_authn_request(destination, binding=binding) relay_state = web2py_uuid().replace('-','') session.saml_outstanding_queries = {req_id: request.url} + if '_next' in request.vars: + session.saml_outstanding_queries += '?%s' % request.vars._next session.saml_req_id = req_id http_args = client.apply_binding(binding, str(req), destination, relay_state=relay_state) From 072311fd2c8a6e404cb80c7c24af60e119477baa Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Fri, 2 Feb 2018 11:23:48 +0000 Subject: [PATCH 3/3] Revert Committed in error --- gluon/contrib/login_methods/saml2_auth.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gluon/contrib/login_methods/saml2_auth.py b/gluon/contrib/login_methods/saml2_auth.py index 9439443d..ea650463 100644 --- a/gluon/contrib/login_methods/saml2_auth.py +++ b/gluon/contrib/login_methods/saml2_auth.py @@ -120,9 +120,7 @@ def saml2_handler(session, request, config_filename = None, entityid = None): if not request.vars.SAMLResponse: req_id, req = client.create_authn_request(destination, binding=binding) relay_state = web2py_uuid().replace('-','') - session.saml_outstanding_queries = {req_id: request.url} - if '_next' in request.vars: - session.saml_outstanding_queries += '?%s' % request.vars._next + session.saml_outstanding_queries = {req_id: request.url} session.saml_req_id = req_id http_args = client.apply_binding(binding, str(req), destination, relay_state=relay_state)