diff options
author | Scott Koranda <skoranda@gmail.com> | 2017-09-23 10:00:33 -0500 |
---|---|---|
committer | Scott Koranda <skoranda@gmail.com> | 2017-09-23 10:00:33 -0500 |
commit | 1952da2596f733d2aa80f1c9b0f95daa77dfcfd2 (patch) | |
tree | 7c0e41251c83924896918012152c44fc3c12c3a5 | |
parent | 9cbbd9bd9f6bfa5e9ceace064dd1af4e2ff2f68c (diff) | |
download | pysaml2-1952da2596f733d2aa80f1c9b0f95daa77dfcfd2.tar.gz |
Fix for 459 HTTP_POST form nonconforming and shows submit
Fix for issue 459 "Form used with HTTP_POST binding nonconforming and
shows submit button". The fix introduces an HTML5 DOCTYPE declaration
and uses noscript tags appropriately to hide the submit button when
Javascript is enabled.
Modification of tests were necessary because the tests unecessarily
relied on the response being a list of strings with the <form> element
being the fourth item in the list, in order to unpack the form and pull
out the SAMLResponse and relay state for comparison. The new tests do not
require the response to be arbitrarily broken up as a list of
strings.
-rw-r--r-- | src/saml2/pack.py | 49 | ||||
-rw-r--r-- | tests/test_51_client.py | 12 | ||||
-rw-r--r-- | tests/test_65_authn_query.py | 2 | ||||
-rw-r--r-- | tests/test_68_assertion_id.py | 2 |
4 files changed, 43 insertions, 22 deletions
diff --git a/src/saml2/pack.py b/src/saml2/pack.py index 728a516f..3bf39fc8 100644 --- a/src/saml2/pack.py +++ b/src/saml2/pack.py @@ -40,12 +40,35 @@ except ImportError: import defusedxml.ElementTree NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/" -FORM_SPEC = """<form method="post" action="%s"> - <input type="hidden" name="%s" value="%s" /> - <input type="hidden" name="RelayState" value="%s" /> - <input type="submit" value="Submit" /> -</form>""" +FORM_SPEC = """\ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + </head> + <body onload="document.forms[0].submit()"> + <noscript> + <p> + <strong>Note:</strong> Since your browser does not support JavaScript, + you must press the Continue button once to proceed. + </p> + </noscript> + + <form action="{action}" method="post"> + <div> + <input type="hidden" name="RelayState" value="{relay_state}"/> + + <input type="hidden" name="{saml_type}" value="{saml_response}"/> + </div> + <noscript> + <div> + <input type="submit" value="Continue"/> + </div> + </noscript> + </form> + </body> +</html>""" def http_form_post_message(message, location, relay_state="", typ="SAMLRequest", **kwargs): @@ -58,8 +81,6 @@ def http_form_post_message(message, location, relay_state="", :param relay_state: for preserving and conveying state information :return: A tuple containing header information and a HTML message. """ - response = ["<head>", """<title>SAML 2.0 POST</title>""", "</head><body>"] - if not isinstance(message, six.string_types): message = str(message) if not isinstance(message, six.binary_type): @@ -71,17 +92,17 @@ def http_form_post_message(message, location, relay_state="", _msg = message _msg = _msg.decode('ascii') - response.append(FORM_SPEC % (location, typ, _msg, relay_state)) + args = { + 'action' : location, + 'saml_type' : typ, + 'relay_state' : relay_state, + 'saml_response' : _msg + } - response.append("""<script type="text/javascript">""") - response.append(" window.onload = function ()") - response.append(" { document.forms[0].submit(); }") - response.append("""</script>""") - response.append("</body>") + response = FORM_SPEC.format(**args) return {"headers": [("Content-type", "text/html")], "data": response} - def http_post_message(message, relay_state="", typ="SAMLRequest", **kwargs): """ diff --git a/tests/test_51_client.py b/tests/test_51_client.py index 937e0e20..bcc535af 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -1398,7 +1398,7 @@ class TestClient: binding, info = resp[entity_ids[0]] assert binding == BINDING_HTTP_POST - _dic = unpack_form(info["data"][3]) + _dic = unpack_form(info["data"]) res = self.server.parse_logout_request(_dic["SAMLRequest"], BINDING_HTTP_POST) assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr @@ -1428,7 +1428,7 @@ class TestClient: binding, info = resp[entity_ids[0]] assert binding == BINDING_HTTP_POST - _dic = unpack_form(info["data"][3]) + _dic = unpack_form(info["data"]) res = self.server.parse_logout_request(_dic["SAMLRequest"], BINDING_HTTP_POST) assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr @@ -1525,7 +1525,7 @@ class TestClientWithDummy(): sid, http_args = self.client.prepare_for_authenticate( "urn:mace:example.com:saml:roland:idp", relay_state="really", binding=binding, response_binding=response_binding) - _dic = unpack_form(http_args["data"][3]) + _dic = unpack_form(http_args["data"]) req = self.server.parse_authn_request(_dic["SAMLRequest"], binding) resp_args = self.server.response_args(req.message, [response_binding]) @@ -1543,7 +1543,7 @@ class TestClientWithDummy(): response = self.client.send(**http_args) print(response.text) - _dic = unpack_form(response.text[3], "SAMLResponse") + _dic = unpack_form(response.text, "SAMLResponse") resp = self.client.parse_authn_request_response(_dic["SAMLResponse"], BINDING_HTTP_POST, {sid: "/"}) @@ -1558,7 +1558,7 @@ class TestClientWithDummy(): sid, auth_binding, http_args = self.client.prepare_for_negotiated_authenticate( "urn:mace:example.com:saml:roland:idp", relay_state="really", binding=binding, response_binding=response_binding) - _dic = unpack_form(http_args["data"][3]) + _dic = unpack_form(http_args["data"]) assert binding == auth_binding @@ -1578,7 +1578,7 @@ class TestClientWithDummy(): response = self.client.send(**http_args) print(response.text) - _dic = unpack_form(response.text[3], "SAMLResponse") + _dic = unpack_form(response.text, "SAMLResponse") resp = self.client.parse_authn_request_response(_dic["SAMLResponse"], BINDING_HTTP_POST, {sid: "/"}) diff --git a/tests/test_65_authn_query.py b/tests/test_65_authn_query.py index 54d529f8..68af10a1 100644 --- a/tests/test_65_authn_query.py +++ b/tests/test_65_authn_query.py @@ -28,7 +28,7 @@ def get_msg(hinfo, binding): if binding == BINDING_SOAP: xmlstr = hinfo["data"] elif binding == BINDING_HTTP_POST: - _inp = hinfo["data"][3] + _inp = hinfo["data"] i = _inp.find(TAG1) i += len(TAG1) + 1 j = _inp.find('"', i) diff --git a/tests/test_68_assertion_id.py b/tests/test_68_assertion_id.py index 52959f3a..283b4da6 100644 --- a/tests/test_68_assertion_id.py +++ b/tests/test_68_assertion_id.py @@ -27,7 +27,7 @@ def get_msg(hinfo, binding, response=False): if binding == BINDING_SOAP: msg = hinfo["data"] elif binding == BINDING_HTTP_POST: - _inp = hinfo["data"][3] + _inp = hinfo["data"] i = _inp.find(TAG1) i += len(TAG1) + 1 j = _inp.find('"', i) |