1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
from contextlib import closing
from saml2 import BINDING_HTTP_POST
from saml2.client import Saml2Client
from saml2.server import Server
import sys
if sys.version_info.major < 3:
from HTMLParser import HTMLParser
else:
from html.parser import HTMLParser
# Typical RelayState used by Shibboleth SP.
SHIB_SP_RELAY_STATE = """\
ss:mem:ab1e6a31f3bd040ffd1d64a2d0e15d61ce517f5e1a94a41ea4fae32cc8d70a04"""
class RelayStateHTMLParser(HTMLParser, object):
"""Class used to parse HTML from a HTTP-POST binding response
and determine if the HTML includes the expected relay state."""
def __init__(self, expected_relay_state):
super(RelayStateHTMLParser, self).__init__()
self.expected_relay_state = expected_relay_state
self.expected_relay_state_found = False
self.input_relay_state_element_found = False
def handle_starttag(self, tag, attrs):
"""If the <input> tag is found and it includes the correct value
for the relay state set the relay state found flag to true."""
if tag == 'input':
if ('name', 'RelayState') in attrs:
self.input_relay_state_found = True
if ('value', self.expected_relay_state) in attrs:
self.expected_relay_state_found = True
def test_relay_state():
# Identity information about a mock user.
identity = {
"eduPersonEntitlement": "Short stop",
"surName": "Jeter",
"givenName": "Derek",
"mail": "derek.jeter@nyy.mlb.com",
"title": "The man"
}
# Create a service provider using the servera_conf.py configuration.
sp = Saml2Client(config_file="servera_conf")
# Create an identity providver using the idp_all_conf.py configuration.
with closing(Server(config_file="idp_all_conf")) as idp:
# Create a response to an authentication request as if
# it came from the SP.
name_id = idp.ident.transient_nameid(sp.config.entityid, "id12")
binding, destination = idp.pick_binding("assertion_consumer_service",
bindings=[BINDING_HTTP_POST],
entity_id=sp.config.entityid)
resp = idp.create_authn_response(identity,
"id-123456789",
destination,
sp.config.entityid,
name_id=name_id)
# Apply the HTTP_POST binding to the response with a relay state
# typical from a Shibboleth SP to create the HTML that carries
# the SAML response.
relay_state = SHIB_SP_RELAY_STATE
html = idp.apply_binding(BINDING_HTTP_POST,
"%s" % resp, destination, relay_state)['data']
# Parse the HTML and verify that it contains the correct relay state.
parser = RelayStateHTMLParser(relay_state)
parser.feed(html)
assert parser.expected_relay_state_found
# Apply the HTTP_POST binding to the response with relay state None.
relay_state = None
html = idp.apply_binding(BINDING_HTTP_POST,
"%s" % resp, destination, relay_state)['data']
# Parse the HTML and verify that it does not contain a relay state.
parser = RelayStateHTMLParser(relay_state)
parser.feed(html)
assert not parser.input_relay_state_element_found
# Apply the HTTP_POST binding to the response with empty
# string relay state.
relay_state = ""
html = idp.apply_binding(BINDING_HTTP_POST,
"%s" % resp, destination, relay_state)['data']
# Parse the HTML and verify that it does not contain a relay state.
parser = RelayStateHTMLParser(relay_state)
parser.feed(html)
assert not parser.input_relay_state_element_found
if __name__ == "__main__":
test_relay_state()
|