Fixed so it works with the SP only supporting HTTP-Redirect binding.

This commit is contained in:
Roland Hedberg
2014-06-18 12:49:07 +02:00
parent ce93950ad8
commit 2ee73258f9
4 changed files with 49 additions and 23 deletions

View File

@@ -156,10 +156,19 @@ class Service(object):
return self.do(request, BINDING_HTTP_ARTIFACT)
def response(self, binding, http_args):
resp = None
if binding == BINDING_HTTP_ARTIFACT:
resp = Redirect()
else:
elif http_args["data"]:
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)
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(
"assertion_consumer_service",
bindings=self.response_bindings,
entity_id=_authn_req.issuer.text)
entity_id=_authn_req.issuer.text, request=_authn_req)
except Exception as err:
logger.error("Couldn't find receiver endpoint: %s" % err)
raise

View File

@@ -522,14 +522,22 @@ class SSO(object):
logger.info("Chosen IdP: '%s'" % 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:
# Picks a binding to use for sending the Request to the IDP
_binding, destination = _cli.pick_binding(
"single_sign_on_service", self.bindings, "idpsso",
entity_id=entity_id)
logger.debug("binding: %s, destination: %s" % (_binding,
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()
self.cache.relay_state[_rstate] = came_from
ht_args = _cli.apply_binding(_binding, "%s" % req, destination,
@@ -553,14 +561,6 @@ class SSO(object):
came_from = geturl(self.environ)
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
(done, response) = self._pick_idp(came_from)
# Three cases: -1 something went wrong or Discovery service used
@@ -575,7 +575,7 @@ class SSO(object):
else:
entity_id = response
# 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)
@@ -598,12 +598,6 @@ def main(environ, start_response, _sp):
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):
query = parse_qs(environ["QUERY_STRING"])
entity_id = query["entityID"][0]
@@ -624,7 +618,6 @@ urls = [
# Hmm, place holder, NOT used
('place', ("holder", None)),
(r'^$', main),
(r'^login', verify_login_cookie),
(r'^disco', disco)
]
@@ -655,6 +648,7 @@ def application(environ, start_response):
path = environ.get('PATH_INFO', '').lstrip('/')
logger.debug("<application> PATH: '%s'" % path)
logger.debug("Finding callback to run")
try:
for regex, spec in urls:

View File

@@ -530,7 +530,7 @@ class Base(Entity):
"allow_unsolicited": self.allow_unsolicited,
"want_assertions_signed": self.want_assertions_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,
"attribute_converters": self.config.attribute_converters,
"allow_unknown_attributes":

View File

@@ -228,7 +228,10 @@ class Entity(HTTPBase):
sfunc = getattr(self.metadata, service)
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 self.entity_type == "sp":
@@ -236,11 +239,31 @@ class Entity(HTTPBase):
else:
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:
try:
srvs = sfunc(entity_id, binding, descr_type)
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:
pass