diff options
author | Ivan Kanakarakis <ivan.kanak@gmail.com> | 2020-11-18 01:12:01 +0200 |
---|---|---|
committer | Ivan Kanakarakis <ivan.kanak@gmail.com> | 2020-11-23 14:58:13 +0200 |
commit | 5cdd5c4ba5cba5fc41508c2866ebcb37e46c6140 (patch) | |
tree | 022ca9d78543e40578dd56bcb4be49f052fc4051 | |
parent | 0e5127056a954c4099e8929c3dce7abc7abf146e (diff) | |
download | pysaml2-5cdd5c4ba5cba5fc41508c2866ebcb37e46c6140.tar.gz |
Formatting
Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
-rw-r--r-- | src/saml2/client.py | 125 | ||||
-rw-r--r-- | src/saml2/client_base.py | 44 | ||||
-rw-r--r-- | src/saml2/entity.py | 84 | ||||
-rw-r--r-- | src/saml2/pack.py | 10 | ||||
-rw-r--r-- | src/saml2/server.py | 36 | ||||
-rw-r--r-- | src/saml2/sigver.py | 16 |
6 files changed, 207 insertions, 108 deletions
diff --git a/src/saml2/client.py b/src/saml2/client.py index 11c737c1..e8990a46 100644 --- a/src/saml2/client.py +++ b/src/saml2/client.py @@ -40,10 +40,18 @@ class Saml2Client(Base): """ The basic pySAML2 service provider class """ def prepare_for_authenticate( - self, entityid=None, relay_state="", - binding=saml2.BINDING_HTTP_REDIRECT, vorg="", nameid_format=None, - scoping=None, consent=None, extensions=None, sign=None, - response_binding=saml2.BINDING_HTTP_POST, **kwargs): + self, + entityid=None, + relay_state="", + binding=saml2.BINDING_HTTP_REDIRECT, + vorg="", + nameid_format=None, + scoping=None, + consent=None, extensions=None, + sign=None, + response_binding=saml2.BINDING_HTTP_POST, + **kwargs, + ): """ Makes all necessary preparations for an authentication request. :param entityid: The entity ID of the IdP to send the request to @@ -61,19 +69,19 @@ class Saml2Client(Base): :return: session id and AuthnRequest info """ - reqid, negotiated_binding, info = \ - self.prepare_for_negotiated_authenticate( - entityid=entityid, - relay_state=relay_state, - binding=binding, - vorg=vorg, - nameid_format=nameid_format, - scoping=scoping, - consent=consent, - extensions=extensions, - sign=sign, - response_binding=response_binding, - **kwargs) + reqid, negotiated_binding, info = self.prepare_for_negotiated_authenticate( + entityid=entityid, + relay_state=relay_state, + binding=binding, + vorg=vorg, + nameid_format=nameid_format, + scoping=scoping, + consent=consent, + extensions=extensions, + sign=sign, + response_binding=response_binding, + **kwargs, + ) if negotiated_binding != binding: raise ValueError( @@ -85,9 +93,19 @@ class Saml2Client(Base): return reqid, info def prepare_for_negotiated_authenticate( - self, entityid=None, relay_state="", binding=None, vorg="", - nameid_format=None, scoping=None, consent=None, extensions=None, - sign=None, response_binding=saml2.BINDING_HTTP_POST, **kwargs): + self, + entityid=None, + relay_state="", + binding=None, + vorg="", + nameid_format=None, + scoping=None, + consent=None, + extensions=None, + sign=None, + response_binding=saml2.BINDING_HTTP_POST, + **kwargs, + ): """ Makes all necessary preparations for an authentication request that negotiates which binding to use for authentication. @@ -116,12 +134,18 @@ class Saml2Client(Base): logger.info("destination to provider: %s", destination) reqid, request = self.create_authn_request( - destination, vorg, scoping, response_binding, nameid_format, - consent=consent, extensions=extensions, sign=sign, - **kwargs) + destination, + vorg, + scoping, + response_binding, + nameid_format, + consent=consent, + extensions=extensions, + sign=sign, + **kwargs, + ) _req_str = str(request) - logger.info("AuthNReq: %s", _req_str) try: @@ -129,13 +153,18 @@ class Saml2Client(Base): except KeyError: args = {} - http_info = self.apply_binding(binding, _req_str, destination, - relay_state, sign=sign, **args) + http_info = self.apply_binding( + binding, + _req_str, + destination, + relay_state, + sign=sign, + **args, + ) return reqid, binding, http_info else: - raise SignOnError( - "No supported bindings available for authentication") + raise SignOnError("No supported bindings available for authentication") def global_logout(self, name_id, reason="", expire=None, sign=None, sign_alg=None, digest_alg=None): @@ -232,43 +261,47 @@ class Saml2Client(Base): sigalg = None if sign: if binding == BINDING_HTTP_REDIRECT: - sigalg = kwargs.get( - "sigalg", ds.DefaultSignature().get_sign_alg()) + sigalg = kwargs.get("sigalg", ds.DefaultSignature().get_sign_alg()) # key = kwargs.get("key", self.signkey) srequest = str(request) else: - srequest = self.sign(request, sign_alg=sign_alg, - digest_alg=digest_alg) + srequest = self.sign( + request, sign_alg=sign_alg, digest_alg=digest_alg + ) else: srequest = str(request) relay_state = self._relay_state(req_id) - http_info = self.apply_binding(binding, srequest, destination, - relay_state, sign=sign, sigalg=sigalg) + http_info = self.apply_binding( + binding, + srequest, + destination, + relay_state, + sign=sign, + sigalg=sigalg, + ) if binding == BINDING_SOAP: response = self.send(**http_info) - if response and response.status_code == 200: not_done.remove(entity_id) response = response.text logger.info("Response: %s", response) - res = self.parse_logout_request_response(response, - binding) + res = self.parse_logout_request_response(response, binding) responses[entity_id] = res else: logger.info("NOT OK response from %s", destination) - else: - self.state[req_id] = {"entity_id": entity_id, - "operation": "SLO", - "entity_ids": entity_ids, - "name_id": code(name_id), - "reason": reason, - "not_on_or_after": expire, - "sign": sign} - + self.state[req_id] = { + "entity_id": entity_id, + "operation": "SLO", + "entity_ids": entity_ids, + "name_id": code(name_id), + "reason": reason, + "not_on_or_after": expire, + "sign": sign, + } responses[entity_id] = (binding, http_info) not_done.remove(entity_id) diff --git a/src/saml2/client_base.py b/src/saml2/client_base.py index 41df6585..d33bbbf0 100644 --- a/src/saml2/client_base.py +++ b/src/saml2/client_base.py @@ -281,13 +281,25 @@ class Base(Entity): else: return None - def create_authn_request(self, destination, vorg="", scoping=None, - binding=saml2.BINDING_HTTP_POST, - nameid_format=None, - service_url_binding=None, message_id=0, - consent=None, extensions=None, sign=None, - allow_create=None, sign_prepare=False, sign_alg=None, - digest_alg=None, requested_attributes=None, **kwargs): + def create_authn_request( + self, + destination, + vorg="", + scoping=None, + binding=BINDING_HTTP_POST, + nameid_format=None, + service_url_binding=None, + message_id=0, + consent=None, + extensions=None, + sign=None, + sign_prepare=False, + sign_alg=None, + digest_alg=None, + allow_create=None, + requested_attributes=None, + **kwargs, + ): """ Creates an authentication request. :param destination: Where the request should be sent. @@ -302,6 +314,8 @@ class Base(Entity): :param extensions: Possible extensions :param sign: Whether the request should be signed or not. :param sign_prepare: Whether the signature should be prepared or not. + :param sign_alg: The request signature algorithm + :param digest_alg: The request digest algorithm :param allow_create: If the identity provider is allowed, in the course of fulfilling the request, to create a new identifier to represent the principal. @@ -445,11 +459,11 @@ class Base(Entity): extensions, sign, sign_prepare, + sign_alg=sign_alg, + digest_alg=digest_alg, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, - sign_alg=sign_alg, - digest_alg=digest_alg, **args, ) else: @@ -461,11 +475,11 @@ class Base(Entity): extensions, sign, sign_prepare, + sign_alg=sign_alg, + digest_alg=digest_alg, protocol_binding=binding, scoping=scoping, nsprefix=nsprefix, - sign_alg=sign_alg, - digest_alg=digest_alg, **args, ) @@ -843,10 +857,12 @@ class Base(Entity): # The IDP publishes support for ECP by using the SOAP binding on # SingleSignOnService - _, location = self.pick_binding("single_sign_on_service", - [_binding], entity_id=entityid) + _, location = self.pick_binding( + "single_sign_on_service", [_binding], entity_id=entityid + ) req_id, authn_req = self.create_authn_request( - location, service_url_binding=BINDING_PAOS, **kwargs) + location, service_url_binding=BINDING_PAOS, **kwargs + ) # ---------------------------------------- # The SOAP envelope diff --git a/src/saml2/entity.py b/src/saml2/entity.py index 672ad6f7..af2d8ba4 100644 --- a/src/saml2/entity.py +++ b/src/saml2/entity.py @@ -190,8 +190,16 @@ class Entity(HTTPBase): return Issuer(text=self.config.entityid, format=NAMEID_FORMAT_ENTITY) - def apply_binding(self, binding, msg_str, destination="", relay_state="", - response=False, sign=False, **kwargs): + def apply_binding( + self, + binding, + msg_str, + destination="", + relay_state="", + response=False, + sign=None, + **kwargs, + ): """ Construct the necessary HTTP arguments dependent on Binding @@ -218,19 +226,25 @@ class Entity(HTTPBase): # info["url"] = destination # info["method"] = "POST" # else: - info = self.use_http_form_post(msg_str, destination, - relay_state, typ) + info = self.use_http_form_post(msg_str, destination, relay_state, typ) info["url"] = destination info["method"] = "POST" elif binding == BINDING_HTTP_REDIRECT: logger.info("HTTP REDIRECT") sigalg = kwargs.get("sigalg") - if sign and sigalg: - signer = self.sec.sec_backend.get_signer(sigalg) - else: - signer = None - info = self.use_http_get(msg_str, destination, relay_state, typ, - signer=signer, **kwargs) + signer = ( + self.sec.sec_backend.get_signer(sigalg) + if sign and sigalg + else None + ) + info = self.use_http_get( + msg_str, + destination, + relay_state, + typ, + signer=signer, + **kwargs, + ) info["url"] = str(destination) info["method"] = "GET" elif binding == BINDING_SOAP or binding == BINDING_PAOS: @@ -416,12 +430,19 @@ class Entity(HTTPBase): # -------------------------------------------------------------------------- - def sign(self, msg, mid=None, to_sign=None, sign_prepare=False, - sign_alg=None, digest_alg=None): + def sign( + self, + msg, + mid=None, + to_sign=None, + sign_prepare=False, + sign_alg=None, + digest_alg=None, + ): if msg.signature is None: - msg.signature = pre_signature_part(msg.id, self.sec.my_cert, 1, - sign_alg=sign_alg, - digest_alg=digest_alg) + msg.signature = pre_signature_part( + msg.id, self.sec.my_cert, 1, sign_alg=sign_alg, digest_alg=digest_alg + ) if sign_prepare: return msg @@ -437,9 +458,20 @@ class Entity(HTTPBase): logger.info("REQUEST: %s", msg) return signed_instance_factory(msg, self.sec, to_sign) - def _message(self, request_cls, destination=None, message_id=0, - consent=None, extensions=None, sign=False, sign_prepare=False, - nsprefix=None, sign_alg=None, digest_alg=None, **kwargs): + def _message( + self, + request_cls, + destination=None, + message_id=0, + consent=None, + extensions=None, + sign=False, + sign_prepare=False, + nsprefix=None, + sign_alg=None, + digest_alg=None, + **kwargs, + ): """ Some parameters appear in all requests so simplify by doing it in one place @@ -480,13 +512,17 @@ class Entity(HTTPBase): req = self.msg_cb(req) reqid = req.id - if sign: - return reqid, self.sign(req, sign_prepare=sign_prepare, - sign_alg=sign_alg, digest_alg=digest_alg) - else: - logger.info("REQUEST: %s", req) - return reqid, req + signed_req = self.sign( + req, + sign_prepare=sign_prepare, + sign_alg=sign_alg, + digest_alg=digest_alg, + ) + req = signed_req + + logger.info("REQUEST: %s", req) + return reqid, req @staticmethod def _filter_args(instance, extensions=None, **kwargs): diff --git a/src/saml2/pack.py b/src/saml2/pack.py index f8fdbfcb..7b693f28 100644 --- a/src/saml2/pack.py +++ b/src/saml2/pack.py @@ -186,13 +186,11 @@ def http_redirect_message(message, location, relay_state="", typ="SAMLRequest", ) args["SigAlg"] = sigalg - string = "&".join([urlencode({k: args[k]}) - for k in _order if k in args]).encode('ascii') - args["Signature"] = base64.b64encode(signer.sign(string)) - string = urlencode(args) - else: - string = urlencode(args) + string = "&".join(urlencode({k: args[k]}) for k in _order if k in args) + string_enc = string.encode('ascii') + args["Signature"] = base64.b64encode(signer.sign(string_enc)) + string = urlencode(args) glue_char = "&" if urlparse(location).query else "?" login_url = glue_char.join([location, string]) headers = [('Location', str(login_url))] diff --git a/src/saml2/server.py b/src/saml2/server.py index 50250c3a..bcdbd2bb 100644 --- a/src/saml2/server.py +++ b/src/saml2/server.py @@ -671,18 +671,30 @@ class Server(Entity): return args - def create_authn_response(self, identity, in_response_to, destination, - sp_entity_id, name_id_policy=None, userid=None, - name_id=None, authn=None, issuer=None, - sign_response=None, sign_assertion=None, - encrypt_cert_advice=None, - encrypt_cert_assertion=None, - encrypt_assertion=None, - encrypt_assertion_self_contained=True, - encrypted_advice_attributes=False, pefim=False, - sign_alg=None, digest_alg=None, - session_not_on_or_after=None, - **kwargs): + def create_authn_response( + self, + identity, + in_response_to, + destination, + sp_entity_id, + name_id_policy=None, + userid=None, + name_id=None, + authn=None, + issuer=None, + sign_response=None, + sign_assertion=None, + encrypt_cert_advice=None, + encrypt_cert_assertion=None, + encrypt_assertion=None, + encrypt_assertion_self_contained=True, + encrypted_advice_attributes=False, + pefim=False, + sign_alg=None, + digest_alg=None, + session_not_on_or_after=None, + **kwargs + ): """ Constructs an AuthenticationResponse :param identity: Information about an user diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py index 02daadc8..ee630340 100644 --- a/src/saml2/sigver.py +++ b/src/saml2/sigver.py @@ -566,8 +566,7 @@ def verify_redirect_signature(saml_msg, crypto, cert=None, sigkey=None): try: signer = crypto.get_signer(saml_msg['SigAlg'], sigkey) except KeyError: - raise Unsupported('Signature algorithm: {alg}'.format( - alg=saml_msg['SigAlg'])) + raise Unsupported('Signature algorithm: {alg}'.format(alg=saml_msg['SigAlg'])) else: if saml_msg['SigAlg'] in SIGNER_ALGS: if 'SAMLRequest' in saml_msg: @@ -576,13 +575,18 @@ def verify_redirect_signature(saml_msg, crypto, cert=None, sigkey=None): _order = RESP_ORDER else: raise Unsupported( - 'Verifying signature on something that should not be ' - 'signed') + 'Verifying signature on something that should not be signed' + ) + _args = saml_msg.copy() del _args['Signature'] # everything but the signature string = '&'.join( - [parse.urlencode({k: _args[k]}) for k in _order if k in - _args]).encode('ascii') + [ + parse.urlencode({k: _args[k]}) + for k in _order + if k in _args + ] + ).encode('ascii') if cert: _key = extract_rsa_key_from_x509_cert(pem_format(cert)) |