deb-python-pysaml2/src/saml2/ecp.py

198 lines
5.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
"""
Contains classes used in the SAML ECP profile
"""
import logging
from saml2.client_base import ACTOR
from saml2.ecp_client import SERVICE
from saml2 import element_to_extension_element
from saml2 import samlp
from saml2 import soap
from saml2 import BINDING_SOAP, BINDING_PAOS
from saml2.profile import paos
from saml2.profile import ecp
#from saml2.client import Saml2Client
from saml2.server import Server
from saml2.schema import soapenv
from saml2.response import authn_response
from saml2 import saml
logger = logging.getLogger(__name__)
def ecp_capable(headers):
if "application/vnd.paos+xml" in headers["Accept"]:
if "PAOS" in headers:
if 'ver="%s";"%s"' % (paos.NAMESPACE,
SERVICE) in headers["PAOS"]:
return True
return False
#noinspection PyUnusedLocal
def ecp_auth_request(cls, entityid=None, relay_state="", sign=False):
""" Makes an authentication request.
:param entityid: The entity ID of the IdP to send the request to
:param relay_state: To where the user should be returned after
successfull log in.
:param sign: Whether the request should be signed or not.
:return: AuthnRequest response
"""
eelist = []
# ----------------------------------------
# <paos:Request>
# ----------------------------------------
my_url = cls.service_urls(BINDING_PAOS)[0]
# must_understand and actor according to the standard
#
paos_request = paos.Request(must_understand="1", actor=ACTOR,
response_consumer_url=my_url,
service=SERVICE)
eelist.append(element_to_extension_element(paos_request))
# ----------------------------------------
# <samlp:AuthnRequest>
# ----------------------------------------
logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP))
location = cls._sso_location(entityid, binding=BINDING_SOAP)
req_id, authn_req = cls.create_authn_request(
location, binding=BINDING_PAOS, service_url_binding=BINDING_PAOS)
body = soapenv.Body()
body.extension_elements = [element_to_extension_element(authn_req)]
# ----------------------------------------
# <ecp:Request>
# ----------------------------------------
# idp = samlp.IDPEntry(
# provider_id = "https://idp.example.org/entity",
# name = "Example identity provider",
# loc = "https://idp.example.org/saml2/sso",
# )
#
# idp_list = samlp.IDPList(idp_entry= [idp])
idp_list = None
ecp_request = ecp.Request(
actor=ACTOR,
must_understand="1",
provider_name=None,
issuer=saml.Issuer(text=authn_req.issuer.text),
idp_list=idp_list)
eelist.append(element_to_extension_element(ecp_request))
# ----------------------------------------
# <ecp:RelayState>
# ----------------------------------------
relay_state = ecp.RelayState(actor=ACTOR, must_understand="1",
text=relay_state)
eelist.append(element_to_extension_element(relay_state))
header = soapenv.Header()
header.extension_elements = eelist
# ----------------------------------------
# The SOAP envelope
# ----------------------------------------
soap_envelope = soapenv.Envelope(header=header, body=body)
return req_id, "%s" % soap_envelope
def handle_ecp_authn_response(cls, soap_message, outstanding=None):
rdict = soap.class_instances_from_soap_enveloped_saml_thingies(
soap_message, [paos, ecp, samlp])
_relay_state = None
for item in rdict["header"]:
if item.c_tag == "RelayState" and item.c_namespace == ecp.NAMESPACE:
_relay_state = item
response = authn_response(cls.config, cls.service_urls(), outstanding,
allow_unsolicited=True)
response.loads("%s" % rdict["body"], False, soap_message)
response.verify()
cls.users.add_information_about_person(response.session_info())
return response, _relay_state
def ecp_response(target_url, response):
# ----------------------------------------
# <ecp:Response
# ----------------------------------------
ecp_response = ecp.Response(assertion_consumer_service_url=target_url)
header = soapenv.Header()
header.extension_elements = [element_to_extension_element(ecp_response)]
# ----------------------------------------
# <samlp:Response
# ----------------------------------------
body = soapenv.Body()
body.extension_elements = [element_to_extension_element(response)]
soap_envelope = soapenv.Envelope(header=header, body=body)
return "%s" % soap_envelope
class ECPServer(Server):
""" This deals with what the IdP has to do
TODO: Still tentative
"""
def __init__(self, config_file="", config=None, cache=None):
Server.__init__(self, config_file, config, cache)
def parse_ecp_authn_query(self):
pass
def ecp_response(self):
# ----------------------------------------
# <ecp:Response
# ----------------------------------------
target_url = ""
ecp_response = ecp.Response(assertion_consumer_service_url=target_url)
header = soapenv.Body()
header.extension_elements = [element_to_extension_element(ecp_response)]
# ----------------------------------------
# <samlp:Response
# ----------------------------------------
response = samlp.Response()
body = soapenv.Body()
body.extension_elements = [element_to_extension_element(response)]
soap_envelope = soapenv.Envelope(header=header, body=body)
return "%s" % soap_envelope