def operation(self, saml_msg, binding): logger.debug("_operation: %s" % saml_msg) if not (saml_msg and 'SAMLRequest' in saml_msg): resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: # saml_msg may also contain Signature and SigAlg if "Signature" in saml_msg: try: kwargs = {"signature": saml_msg["Signature"], "sigalg": saml_msg["SigAlg"]} except KeyError: resp = BadRequest( 'Signature Algorithm specification is missing') return resp(self.environ, self.start_response) else: kwargs = {} try: _encrypt_cert = encrypt_cert_from_item( saml_msg["req_info"].message) return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], encrypt_cert=_encrypt_cert, **kwargs) except KeyError: # Can live with no relay state return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], **kwargs)
def post(self): """ The HTTP-Post endpoint """ logger.info("--- In SSO POST ---") _info = self.unpack_either() cert_str = None if self.idphandler.copy_sp_cert: with lock: self.req_info = self.idphandler.idp_server.parse_authn_request(_info["SAMLRequest"], BINDING_HTTP_POST) cert_str = self.idphandler.idp_server.getvalid_certificate_str() else: self.req_info = self.idphandler.idp_server.parse_authn_request(_info["SAMLRequest"], BINDING_HTTP_POST) _req = self.req_info.message _encrypt_cert = None if self.idphandler.copy_sp_key: _encrypt_cert = encrypt_cert_from_item(_info["req_info"].message) if self.user: if _req.force_authn: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_POST) else: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert)
def operation(self, saml_msg, binding): logger.debug("_operation: %s", saml_msg) if not (saml_msg and 'SAMLRequest' in saml_msg): resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: # saml_msg may also contain Signature and SigAlg if "Signature" in saml_msg: try: kwargs = { "signature": saml_msg["Signature"], "sigalg": saml_msg["SigAlg"] } except KeyError: resp = BadRequest( 'Signature Algorithm specification is missing') return resp(self.environ, self.start_response) else: kwargs = {} try: kwargs['encrypt_cert'] = encrypt_cert_from_item( saml_msg["req_info"].message) except KeyError: pass try: kwargs['relay_state'] = saml_msg['RelayState'] except KeyError: pass return self.do(saml_msg["SAMLRequest"], binding, **kwargs)
def sso_operation(self, msg, binding, uid=None): log.debug("Msg: " + str(msg)) log.debug("Inbound binding: " + str(binding)) if not (msg and "SAMLRequest" in msg): return BadRequest("Error parsing request or no request") else: if "Signature" in msg: try: kwargs = { "signature": msg["Signature"], "sigalg": msg["SigAlg"] } except KeyError: return BadRequest( "Signature Algorithm specification is missing") else: kwargs = {} try: kwargs["encrypt_cert"] = encrypt_cert_from_item( msg["req_info"].message) except KeyError: pass try: kwargs["relay_state"] = msg["RelayState"] except KeyError: pass if not uid is None: kwargs["uid"] = uid return self.do(msg["SAMLRequest"], binding, **kwargs)
def operation(self, saml_msg, binding): logger.debug("_operation: %s" % saml_msg) if not (saml_msg and 'SAMLRequest' in saml_msg): resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: # saml_msg may also contain Signature and SigAlg if "Signature" in saml_msg: kwargs = { "signature": saml_msg["signature"], "sigalg": saml_msg["SigAlg"] } else: kwargs = {} try: _encrypt_cert = encrypt_cert_from_item( saml_msg["req_info"].message) return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], encrypt_cert=_encrypt_cert, **kwargs) except KeyError: # Can live with no relay state return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], **kwargs)
def post(self): """ The HTTP-Post endpoint """ logger.info("--- In SSO POST ---") _info = self.unpack_either() cert_str = None if self.idphandler.copy_sp_cert: with lock: self.req_info = self.idphandler.idp_server.parse_authn_request( _info["SAMLRequest"], BINDING_HTTP_POST) cert_str = self.idphandler.idp_server.getvalid_certificate_str( ) else: self.req_info = self.idphandler.idp_server.parse_authn_request( _info["SAMLRequest"], BINDING_HTTP_POST) _req = self.req_info.message _encrypt_cert = None if self.idphandler.copy_sp_key: _encrypt_cert = encrypt_cert_from_item(_info["req_info"].message) if self.user: if _req.force_authn: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_POST) else: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert)
def handle_authn_request(self, saml_request, relay_state, binding, userid): self.authn_req = self.idp.parse_authn_request(saml_request, binding) _encrypt_cert = encrypt_cert_from_item(self.authn_req.message) self.binding_out, self.destination = self.idp.pick_binding( "assertion_consumer_service", bindings=None, entity_id=self.authn_req.message.issuer.text, request=self.authn_req.message) resp_args = self.idp.response_args(self.authn_req.message) AUTHN_BROKER = AuthnBroker() AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), username_password_authn_dummy, 10, "http://test.idp.se") AUTHN_BROKER.get_authn_by_accr(PASSWORD) resp_args["authn"] = AUTHN_BROKER.get_authn_by_accr(PASSWORD) _resp = self.idp.create_authn_response(TestIdP.USERS[userid], userid=userid, encrypt_cert=_encrypt_cert, encrypt_assertion_self_contained=True, encrypted_advice_attributes=True, **resp_args) kwargs = {} http_args = self.idp.apply_binding(BINDING_HTTP_POST, "%s" % _resp, self.destination, relay_state, response=True, **kwargs) action, body = get_post_action_body(http_args["data"][3]) return action, urllib.urlencode(body)
def verify_request(self, query, binding): """ Parses and verifies the SAML Authentication Request :param query: The SAML authn request, transport encoded :param binding: Which binding the query came in over :returns: dictionary """ if not query: logger.info("Missing QUERY") resp = Unauthorized('Unknown user') return {"response": resp} req_info = self.idp.parse_authn_request(query, binding) encrypt_cert = encrypt_cert_from_item(req_info.message) logger.info("parsed OK") _authn_req = req_info.message logger.debug("%s" % _authn_req) # Check that I know where to send the reply to try: binding_out, destination = self.idp.pick_binding( "assertion_consumer_service", bindings=self.response_bindings, entity_id=_authn_req.issuer.text, request=_authn_req) except Exception as err: logger.error("Couldn't find receiver endpoint: %s" % err) raise logger.debug("Binding: %s, destination: %s" % (binding_out, destination)) resp_args = {} try: resp_args = self.idp.response_args(_authn_req) _resp = None except UnknownPrincipal as excp: _resp = self.idp.create_error_response(_authn_req.id, destination, excp) except UnsupportedBinding as excp: _resp = self.idp.create_error_response(_authn_req.id, destination, excp) req_args = {} for key in ["subject", "name_id_policy", "conditions", "requested_authn_context", "scoping", "force_authn", "is_passive"]: try: val = getattr(_authn_req, key) except AttributeError: pass else: if val is not None: req_args[key] = val return {"resp_args": resp_args, "response": _resp, "authn_req": _authn_req, "req_args": req_args, "encrypt_cert": encrypt_cert}
def redirect(self): """ This is the HTTP-redirect endpoint """ logger.info("--- In SSO Redirect ---") _info = self.unpack_redirect() cert_str = None try: _key = _info["key"] _info = self.idphandler.idp_server.ticket[_key] self.req_info = _info["req_info"] del self.idphandler.idp_server.ticket[_key] except KeyError: if self.idphandler.copy_sp_cert: with lock: self.req_info = self.idphandler.idp_server.parse_authn_request( _info["SAMLRequest"], BINDING_HTTP_REDIRECT) cert_str = self.idphandler.idp_server.getvalid_certificate_str( ) else: self.req_info = self.idphandler.idp_server.parse_authn_request( _info["SAMLRequest"], BINDING_HTTP_REDIRECT) _req = self.req_info.message if "SigAlg" in _info and "Signature" in _info: # Signed request issuer = _req.issuer.text _certs = self.idphandler.idp_server.metadata.certs( issuer, "any", "signing") verified_ok = False for cert in _certs: if verify_redirect_signature(_info, cert): verified_ok = True break if not verified_ok: resp = BadRequest("Message signature verification failure") return resp(self.environ, self.start_response) _encrypt_cert = None if self.idphandler.copy_sp_key: _encrypt_cert = encrypt_cert_from_item(self.req_info.message) if self.user: if _req.force_authn: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_REDIRECT) else: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_REDIRECT)
def operation(self, saml_msg, binding): logger.debug("_operation: %s" % saml_msg) if not saml_msg or not "SAMLRequest" in saml_msg: resp = BadRequest("Error parsing request or no request") return resp(self.environ, self.start_response) else: try: _encrypt_cert = encrypt_cert_from_item(saml_msg["req_info"].message) return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], encrypt_cert=_encrypt_cert) except KeyError: # Can live with no relay state return self.do(saml_msg["SAMLRequest"], binding)
def operation(self, _dict, binding): logger.debug("_operation: %s" % _dict) if not _dict or not 'SAMLRequest' in _dict: resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: try: _encrypt_cert = encrypt_cert_from_item(_dict["req_info"].message) return self.do(_dict["SAMLRequest"], binding, _dict["RelayState"], encrypt_cert=_encrypt_cert) except KeyError: # Can live with no relay state return self.do(_dict["SAMLRequest"], binding)
def redirect(self): """ This is the HTTP-redirect endpoint for SSO """ logger.info("--- In SSO Redirect ---") _info = self.unpack_redirect() cert_str = None try: _key = _info["key"] _info = self.idphandler.idp_server.ticket[_key] self.req_info = _info["req_info"] del self.idphandler.idp_server.ticket[_key] except KeyError: if self.idphandler.copy_sp_cert: with lock: self.req_info = self.idphandler.idp_server.parse_authn_request(_info["SAMLRequest"], BINDING_HTTP_REDIRECT) cert_str = self.idphandler.idp_server.getvalid_certificate_str() else: self.req_info = self.idphandler.idp_server.parse_authn_request(_info["SAMLRequest"], BINDING_HTTP_REDIRECT) _req = self.req_info.message if "SigAlg" in _info and "Signature" in _info: # Signed request issuer = _req.issuer.text _certs = self.idphandler.idp_server.metadata.certs(issuer, "any", "signing") verified_ok = False for cert in _certs: if verify_redirect_signature(_info, cert): verified_ok = True break if not verified_ok: resp = BadRequest("Message signature verification failure") return resp(self.environ, self.start_response) _encrypt_cert = None if self.idphandler.copy_sp_key: _encrypt_cert = encrypt_cert_from_item(self.req_info.message) if self.user: if _req.force_authn: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_REDIRECT) else: _info["req_info"] = self.req_info key = self._store_request(_info) return self.not_authn(key, _req.requested_authn_context, cert_str, _encrypt_cert) else: return self.operation(_info, BINDING_HTTP_REDIRECT)
def operation(self, saml_msg, binding): logger.debug("_operation: %s" % saml_msg) if not saml_msg or not 'SAMLRequest' in saml_msg: resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: try: _encrypt_cert = encrypt_cert_from_item( saml_msg["req_info"].message) return self.do(saml_msg["SAMLRequest"], binding, saml_msg["RelayState"], encrypt_cert=_encrypt_cert) except KeyError: # Can live with no relay state return self.do(saml_msg["SAMLRequest"], binding)
def operation(self, _dict, binding): self.logger.debug("_operation: %s" % _dict) if not _dict: resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: try: _relay_state = _dict["RelayState"] except KeyError: _relay_state = "" _encrypt_cert = None try: _encrypt_cert = encrypt_cert_from_item(_dict["req_info"].message) except: pass if "SAMLResponse" in _dict: return self.do(_dict["SAMLResponse"], binding, _relay_state, mtype="response", encrypt_cert=_encrypt_cert) elif "SAMLRequest" in _dict: return self.do(_dict["SAMLRequest"], binding, _relay_state, mtype="request", encrypt_cert=_encrypt_cert)