Fixed so it works with the SP only supporting HTTP-Redirect binding.
This commit is contained in:
@@ -156,10 +156,19 @@ class Service(object):
|
|||||||
return self.do(request, BINDING_HTTP_ARTIFACT)
|
return self.do(request, BINDING_HTTP_ARTIFACT)
|
||||||
|
|
||||||
def response(self, binding, http_args):
|
def response(self, binding, http_args):
|
||||||
|
resp = None
|
||||||
if binding == BINDING_HTTP_ARTIFACT:
|
if binding == BINDING_HTTP_ARTIFACT:
|
||||||
resp = Redirect()
|
resp = Redirect()
|
||||||
else:
|
elif http_args["data"]:
|
||||||
resp = Response(http_args["data"], headers=http_args["headers"])
|
resp = Response(http_args["data"], headers=http_args["headers"])
|
||||||
|
else:
|
||||||
|
for header in http_args["headers"]:
|
||||||
|
if header[0] == "Location":
|
||||||
|
resp = Redirect(header[1])
|
||||||
|
|
||||||
|
if not resp:
|
||||||
|
resp = ServiceError("Don't know how to return response")
|
||||||
|
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
def do(self, query, binding, relay_state="", encrypt_cert=None):
|
def do(self, query, binding, relay_state="", encrypt_cert=None):
|
||||||
@@ -254,7 +263,7 @@ class SSO(Service):
|
|||||||
self.binding_out, self.destination = IDP.pick_binding(
|
self.binding_out, self.destination = IDP.pick_binding(
|
||||||
"assertion_consumer_service",
|
"assertion_consumer_service",
|
||||||
bindings=self.response_bindings,
|
bindings=self.response_bindings,
|
||||||
entity_id=_authn_req.issuer.text)
|
entity_id=_authn_req.issuer.text, request=_authn_req)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error("Couldn't find receiver endpoint: %s" % err)
|
logger.error("Couldn't find receiver endpoint: %s" % err)
|
||||||
raise
|
raise
|
||||||
|
@@ -522,14 +522,22 @@ class SSO(object):
|
|||||||
logger.info("Chosen IdP: '%s'" % idp_entity_id)
|
logger.info("Chosen IdP: '%s'" % idp_entity_id)
|
||||||
return 0, idp_entity_id
|
return 0, idp_entity_id
|
||||||
|
|
||||||
def redirect_to_auth(self, _cli, entity_id, came_from, vorg_name=""):
|
def redirect_to_auth(self, _cli, entity_id, came_from):
|
||||||
try:
|
try:
|
||||||
|
# Picks a binding to use for sending the Request to the IDP
|
||||||
_binding, destination = _cli.pick_binding(
|
_binding, destination = _cli.pick_binding(
|
||||||
"single_sign_on_service", self.bindings, "idpsso",
|
"single_sign_on_service", self.bindings, "idpsso",
|
||||||
entity_id=entity_id)
|
entity_id=entity_id)
|
||||||
logger.debug("binding: %s, destination: %s" % (_binding,
|
logger.debug("binding: %s, destination: %s" % (_binding,
|
||||||
destination))
|
destination))
|
||||||
req_id, req = _cli.create_authn_request(destination, vorg=vorg_name)
|
# Binding here is the response binding that is which binding the
|
||||||
|
# IDP should use to return the response.
|
||||||
|
acs = _cli.config.getattr("endpoints", "sp")[
|
||||||
|
"assertion_consumer_service"]
|
||||||
|
# just pick one
|
||||||
|
endp, return_binding = acs[0]
|
||||||
|
req_id, req = _cli.create_authn_request(destination,
|
||||||
|
binding=return_binding)
|
||||||
_rstate = rndstr()
|
_rstate = rndstr()
|
||||||
self.cache.relay_state[_rstate] = came_from
|
self.cache.relay_state[_rstate] = came_from
|
||||||
ht_args = _cli.apply_binding(_binding, "%s" % req, destination,
|
ht_args = _cli.apply_binding(_binding, "%s" % req, destination,
|
||||||
@@ -553,14 +561,6 @@ class SSO(object):
|
|||||||
came_from = geturl(self.environ)
|
came_from = geturl(self.environ)
|
||||||
logger.debug("[sp.challenge] RelayState >> '%s'" % came_from)
|
logger.debug("[sp.challenge] RelayState >> '%s'" % came_from)
|
||||||
|
|
||||||
# Am I part of a virtual organization or more than one ?
|
|
||||||
try:
|
|
||||||
vorg_name = _cli.vorg._name
|
|
||||||
except AttributeError:
|
|
||||||
vorg_name = ""
|
|
||||||
|
|
||||||
logger.debug("[sp.challenge] VO: %s" % vorg_name)
|
|
||||||
|
|
||||||
# If more than one idp and if none is selected, I have to do wayf
|
# If more than one idp and if none is selected, I have to do wayf
|
||||||
(done, response) = self._pick_idp(came_from)
|
(done, response) = self._pick_idp(came_from)
|
||||||
# Three cases: -1 something went wrong or Discovery service used
|
# Three cases: -1 something went wrong or Discovery service used
|
||||||
@@ -575,7 +575,7 @@ class SSO(object):
|
|||||||
else:
|
else:
|
||||||
entity_id = response
|
entity_id = response
|
||||||
# Do the AuthnRequest
|
# Do the AuthnRequest
|
||||||
resp = self.redirect_to_auth(_cli, entity_id, came_from, vorg_name)
|
resp = self.redirect_to_auth(_cli, entity_id, came_from)
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
@@ -598,12 +598,6 @@ def main(environ, start_response, _sp):
|
|||||||
return _sso.do()
|
return _sso.do()
|
||||||
|
|
||||||
|
|
||||||
#noinspection PyUnusedLocal
|
|
||||||
def verify_login_cookie(environ, start_response, _sp):
|
|
||||||
_sso = SSO(_sp, environ, start_response, cache=CACHE, **ARGS)
|
|
||||||
return _sso.do()
|
|
||||||
|
|
||||||
|
|
||||||
def disco(environ, start_response, _sp):
|
def disco(environ, start_response, _sp):
|
||||||
query = parse_qs(environ["QUERY_STRING"])
|
query = parse_qs(environ["QUERY_STRING"])
|
||||||
entity_id = query["entityID"][0]
|
entity_id = query["entityID"][0]
|
||||||
@@ -624,7 +618,6 @@ urls = [
|
|||||||
# Hmm, place holder, NOT used
|
# Hmm, place holder, NOT used
|
||||||
('place', ("holder", None)),
|
('place', ("holder", None)),
|
||||||
(r'^$', main),
|
(r'^$', main),
|
||||||
(r'^login', verify_login_cookie),
|
|
||||||
(r'^disco', disco)
|
(r'^disco', disco)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -655,6 +648,7 @@ def application(environ, start_response):
|
|||||||
path = environ.get('PATH_INFO', '').lstrip('/')
|
path = environ.get('PATH_INFO', '').lstrip('/')
|
||||||
logger.debug("<application> PATH: '%s'" % path)
|
logger.debug("<application> PATH: '%s'" % path)
|
||||||
|
|
||||||
|
|
||||||
logger.debug("Finding callback to run")
|
logger.debug("Finding callback to run")
|
||||||
try:
|
try:
|
||||||
for regex, spec in urls:
|
for regex, spec in urls:
|
||||||
|
@@ -530,7 +530,7 @@ class Base(Entity):
|
|||||||
"allow_unsolicited": self.allow_unsolicited,
|
"allow_unsolicited": self.allow_unsolicited,
|
||||||
"want_assertions_signed": self.want_assertions_signed,
|
"want_assertions_signed": self.want_assertions_signed,
|
||||||
"want_response_signed": self.want_response_signed,
|
"want_response_signed": self.want_response_signed,
|
||||||
"return_addrs": self.service_urls(),
|
"return_addrs": self.service_urls(binding=binding),
|
||||||
"entity_id": self.config.entityid,
|
"entity_id": self.config.entityid,
|
||||||
"attribute_converters": self.config.attribute_converters,
|
"attribute_converters": self.config.attribute_converters,
|
||||||
"allow_unknown_attributes":
|
"allow_unknown_attributes":
|
||||||
|
@@ -228,7 +228,10 @@ class Entity(HTTPBase):
|
|||||||
sfunc = getattr(self.metadata, service)
|
sfunc = getattr(self.metadata, service)
|
||||||
|
|
||||||
if bindings is None:
|
if bindings is None:
|
||||||
bindings = self.config.preferred_binding[service]
|
if request and request.protocol_binding:
|
||||||
|
bindings = [request.protocol_binding]
|
||||||
|
else:
|
||||||
|
bindings = self.config.preferred_binding[service]
|
||||||
|
|
||||||
if not descr_type:
|
if not descr_type:
|
||||||
if self.entity_type == "sp":
|
if self.entity_type == "sp":
|
||||||
@@ -236,11 +239,31 @@ class Entity(HTTPBase):
|
|||||||
else:
|
else:
|
||||||
descr_type = "spsso"
|
descr_type = "spsso"
|
||||||
|
|
||||||
|
_url = _index = None
|
||||||
|
if request:
|
||||||
|
try:
|
||||||
|
_url = getattr(request, "%s_url" % service)
|
||||||
|
except AttributeError:
|
||||||
|
_url = None
|
||||||
|
try:
|
||||||
|
_index = getattr(request, "%s_index" % service)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
for binding in bindings:
|
for binding in bindings:
|
||||||
try:
|
try:
|
||||||
srvs = sfunc(entity_id, binding, descr_type)
|
srvs = sfunc(entity_id, binding, descr_type)
|
||||||
if srvs:
|
if srvs:
|
||||||
return binding, destinations(srvs)[0]
|
if _url:
|
||||||
|
for srv in srvs:
|
||||||
|
if srv["location"] == _url:
|
||||||
|
return binding, _url
|
||||||
|
elif _index:
|
||||||
|
for srv in srvs:
|
||||||
|
if srv["index"] == _index:
|
||||||
|
return binding, srv["location"]
|
||||||
|
else:
|
||||||
|
return binding, destinations(srvs)[0]
|
||||||
except UnsupportedBinding:
|
except UnsupportedBinding:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user