def parse_request_response(self, reqresp, response, body_type, state="", verify=True, **kwargs): if reqresp.status_code in SUCCESSFUL: body_type = verify_header(reqresp, body_type) elif reqresp.status_code in [302, 303]: # redirect return reqresp elif reqresp.status_code == 500: logger.error("(%d) %s" % (reqresp.status_code, sanitize(reqresp.text))) raise ParseError("ERROR: Something went wrong: %s" % reqresp.text) elif reqresp.status_code in [400, 401]: # expecting an error response if issubclass(response, ErrorResponse): pass else: logger.error("(%d) %s" % (reqresp.status_code, sanitize(reqresp.text))) raise HttpError("HTTP ERROR: %s [%s] on %s" % (reqresp.text, reqresp.status_code, reqresp.url)) if response: if body_type == 'txt': # no meaning trying to parse unstructured text return reqresp.text if not verify: # AymRod: skip parsing return reqresp.text else: return self.parse_response(response, reqresp.text, body_type, state, **kwargs) # could be an error response if reqresp.status_code in [200, 400, 401]: if body_type == 'txt': body_type = 'urlencoded' try: err = ErrorResponse().deserialize(reqresp.message, method=body_type) try: err.verify() except PyoidcError: pass else: return err except Exception: pass return reqresp
def provider_config( self, issuer: str, keys: bool = True, endpoints: bool = True, serv_pattern: str = OIDCONF_PATTERN, ) -> ASConfigurationResponse: response_cls = self.message_factory.get_response_type("configuration_endpoint") if issuer.endswith("/"): _issuer = issuer[:-1] else: _issuer = issuer url = serv_pattern % _issuer pcr = None r = self.http_request(url, allow_redirects=True) if r.status_code == 200: try: pcr = response_cls().from_json(r.text) except Exception as e: # FIXME: This should catch specific exception from `from_json()` _err_txt = "Faulty provider config response: {}".format(e) logger.error(sanitize(_err_txt)) raise ParseError(_err_txt) else: raise CommunicationError("Trying '%s', status %s" % (url, r.status_code)) self.store_response(pcr, r.text) self.handle_provider_config(pcr, issuer, keys, endpoints) return pcr
def do_access_token_request(self, request=AccessTokenRequest, scope="", state="", body_type="json", method="POST", request_args=None, extra_args=None, http_args=None, response_cls=AccessTokenResponse, authn_method="", **kwargs): kwargs['authn_endpoint'] = 'token' # method is default POST url, body, ht_args, csi = self.request_info(request, method=method, request_args=request_args, extra_args=extra_args, scope=scope, state=state, authn_method=authn_method, **kwargs) if http_args is None: http_args = ht_args else: http_args.update(ht_args) if self.events is not None: self.events.store('request_url', url) self.events.store('request_http_args', http_args) self.events.store('Request', body) logger.debug("<do_access_token> URL: %s, Body: %s" % (url, sanitize(body))) logger.debug("<do_access_token> response_cls: %s" % response_cls) return self.request_and_return(url, response_cls, method, body, body_type, state=state, http_args=http_args, **kwargs)
def do_access_token_request(self, request=AccessTokenRequest, scope="", state="", body_type="json", method="POST", request_args=None, extra_args=None, http_args=None, response_cls=AccessTokenResponse, authn_method="", **kwargs): kwargs['authn_endpoint'] = 'token' # method is default POST url, body, ht_args, csi = self.request_info(request, method=method, request_args=request_args, extra_args=extra_args, scope=scope, state=state, authn_method=authn_method, **kwargs) if http_args is None: http_args = ht_args else: http_args.update(ht_args) if self.events is not None: self.events.store('request_url', url) self.events.store('request_http_args', http_args) self.events.store('Request', body) logger.debug("<do_access_token> URL: %s, Body: %s" % (url, sanitize(body))) logger.debug("<do_access_token> response_cls: %s" % response_cls) return self.request_and_return(url, response_cls, method, body, body_type, state=state, http_args=http_args, **kwargs)
def parse_request_response(self, reqresp, response, body_type, state="", **kwargs): if reqresp.status_code in SUCCESSFUL: body_type = verify_header(reqresp, body_type) elif reqresp.status_code in [302, 303]: # redirect return reqresp elif reqresp.status_code == 500: logger.error("(%d) %s" % (reqresp.status_code, sanitize(reqresp.text))) raise ParseError("ERROR: Something went wrong: %s" % reqresp.text) elif reqresp.status_code in [400, 401]: # expecting an error response if issubclass(response, ErrorResponse): pass else: logger.error("(%d) %s" % (reqresp.status_code, sanitize(reqresp.text))) raise HttpError("HTTP ERROR: %s [%s] on %s" % ( reqresp.text, reqresp.status_code, reqresp.url)) if response: if body_type == 'txt': # no meaning trying to parse unstructured text return reqresp.text return self.parse_response(response, reqresp.text, body_type, state, **kwargs) # could be an error response if reqresp.status_code in [200, 400, 401]: if body_type == 'txt': body_type = 'urlencoded' try: err = ErrorResponse().deserialize(reqresp.message, method=body_type) try: err.verify() except PyoidcError: pass else: return err except Exception: pass return reqresp
def do_access_token_request( self, scope: str = "", state: str = "", body_type: ENCODINGS = "json", method="POST", request_args=None, extra_args=None, http_args=None, authn_method="", **kwargs, ) -> AccessTokenResponse: request = self.message_factory.get_request_type("token_endpoint") response_cls = self.message_factory.get_response_type("token_endpoint") if extra_args is None: extra_args = {} kwargs["authn_endpoint"] = "token" if http_args is not None and "password" in http_args: extra_args["password"] = http_args.pop("password") # method is default POST url, body, ht_args, csi = self.request_info( request, method=method, request_args=request_args, extra_args=extra_args, scope=scope, state=state, authn_method=authn_method, **kwargs, ) if http_args is None: http_args = ht_args else: http_args.update(ht_args) if self.events is not None: self.events.store("request_url", url) self.events.store("request_http_args", http_args) self.events.store("Request", body) logger.debug("<do_access_token> URL: %s, Body: %s" % (url, sanitize(body))) logger.debug("<do_access_token> response_cls: %s" % response_cls) return self.request_and_return( url, response_cls, method, body, body_type, state=state, http_args=http_args, **kwargs, )
def construct_request(self, request, request_args=None, extra_args=None): if request_args is None: request_args = {} kwargs = self._parse_args(request, **request_args) if extra_args: kwargs.update(extra_args) logger.debug("request: %s" % sanitize(request)) return request(**kwargs)
def construct_request(self, request, request_args=None, extra_args=None): if request_args is None: request_args = {} kwargs = self._parse_args(request, **request_args) if extra_args: kwargs.update(extra_args) logger.debug("request: %s" % sanitize(request)) return request(**kwargs)
def error_response(error, descr=None, status="400 Bad Request"): logger.error("%s" % sanitize(error)) response = ErrorResponse(error=error, error_description=descr) return Response(response.to_json(), content="application/json", status=status)
def parse_response(self, response, info="", sformat="json", state="", **kwargs): """ Parse a response :param response: Response type :param info: The response, can be either in a JSON or an urlencoded format :param sformat: Which serialization that was used :param state: The state :param kwargs: Extra key word arguments :return: The parsed and to some extend verified response """ _r2e = self.response2error if sformat == "urlencoded": info = self.get_urlinfo(info) # if self.events: # self.events.store('Response', info) resp = response().deserialize(info, sformat, **kwargs) msg = 'Initial response parsing => "{}"' logger.debug(msg.format(sanitize(resp.to_dict()))) if self.events: self.events.store('Response', resp.to_dict()) if "error" in resp and not isinstance(resp, ErrorResponse): resp = None try: errmsgs = _r2e[response.__name__] except KeyError: errmsgs = [ErrorResponse] try: for errmsg in errmsgs: try: resp = errmsg().deserialize(info, sformat) resp.verify() break except Exception: resp = None except KeyError: pass elif resp.only_extras(): resp = None else: kwargs["client_id"] = self.client_id try: kwargs['iss'] = self.provider_info['issuer'] except (KeyError, AttributeError): if self.issuer: kwargs['iss'] = self.issuer if "key" not in kwargs and "keyjar" not in kwargs: kwargs["keyjar"] = self.keyjar logger.debug("Verify response with {}".format(sanitize(kwargs))) verf = resp.verify(**kwargs) if not verf: logger.error('Verification of the response failed') raise PyoidcError("Verification of the response failed") if resp.type() == "AuthorizationResponse" and "scope" not in resp: try: resp["scope"] = kwargs["scope"] except KeyError: pass if not resp: logger.error('Missing or faulty response') raise ResponseError("Missing or faulty response") self.store_response(resp, info) if resp.type() in ["AuthorizationResponse", "AccessTokenResponse"]: try: _state = resp["state"] except (AttributeError, KeyError): _state = "" if not _state: _state = state try: self.grant[_state].update(resp) except KeyError: self.grant[_state] = self.grant_class(resp=resp) return resp
def error_response(error, descr=None, status_code=400): logger.error("%s" % sanitize(error)) response = ErrorResponse(error=error, error_description=descr) return Response(response.to_json(), content="application/json", status_code=status_code)
def parse_response(self, response, info="", sformat="json", state="", **kwargs): """ Parse a response :param response: Response type :param info: The response, can be either in a JSON or an urlencoded format :param sformat: Which serialization that was used :param state: The state :param kwargs: Extra key word arguments :return: The parsed and to some extend verified response """ _r2e = self.response2error if sformat == "urlencoded": info = self.get_urlinfo(info) resp = response().deserialize(info, sformat, **kwargs) msg = 'Initial response parsing => "{}"' logger.debug(msg.format(sanitize(resp.to_dict()))) if self.events: self.events.store('Response', resp.to_dict()) if "error" in resp and not isinstance(resp, ErrorResponse): resp = None try: errmsgs = _r2e[response.__name__] except KeyError: errmsgs = [ErrorResponse] try: for errmsg in errmsgs: try: resp = errmsg().deserialize(info, sformat) resp.verify() break except Exception: resp = None except KeyError: pass elif resp.only_extras(): resp = None else: kwargs["client_id"] = self.client_id try: kwargs['iss'] = self.provider_info['issuer'] except (KeyError, AttributeError): if self.issuer: kwargs['iss'] = self.issuer if "key" not in kwargs and "keyjar" not in kwargs: kwargs["keyjar"] = self.keyjar logger.debug("Verify response with {}".format(sanitize(kwargs))) verf = resp.verify(**kwargs) if not verf: logger.error('Verification of the response failed') raise PyoidcError("Verification of the response failed") if resp.type() == "AuthorizationResponse" and "scope" not in resp: try: resp["scope"] = kwargs["scope"] except KeyError: pass if not resp: logger.error('Missing or faulty response') raise ResponseError("Missing or faulty response") self.store_response(resp, info) if resp.type() in ["AuthorizationResponse", "AccessTokenResponse"]: try: _state = resp["state"] except (AttributeError, KeyError): _state = "" if not _state: _state = state try: self.grant[_state].update(resp) except KeyError: self.grant[_state] = self.grant_class(resp=resp) return resp
def do_access_token_request(self, request=None, scope: str = "", state: str = "", body_type: ENCODINGS = "json", method="POST", request_args=None, extra_args=None, http_args=None, response_cls=None, authn_method="", **kwargs) -> AccessTokenResponse: if request is not None: warnings.warn( "Passing `request` is deprecated. Please use `message_factory` instead.", DeprecationWarning, stacklevel=2, ) else: # TODO: This can be moved to the call once we remove the kwarg request = self.message_factory.get_request_type("token_endpoint") if response_cls is not None: warnings.warn( "Passing `response_cls` is deprecated. Please use `message_factory` instead.", DeprecationWarning, stacklevel=2, ) else: # TODO: This can be moved to the call once we remove the kwarg response_cls = self.message_factory.get_response_type( "token_endpoint") kwargs["authn_endpoint"] = "token" # method is default POST url, body, ht_args, csi = self.request_info(request, method=method, request_args=request_args, extra_args=extra_args, scope=scope, state=state, authn_method=authn_method, **kwargs) if http_args is None: http_args = ht_args else: http_args.update(ht_args) if self.events is not None: self.events.store("request_url", url) self.events.store("request_http_args", http_args) self.events.store("Request", body) logger.debug("<do_access_token> URL: %s, Body: %s" % (url, sanitize(body))) logger.debug("<do_access_token> response_cls: %s" % response_cls) return self.request_and_return(url, response_cls, method, body, body_type, state=state, http_args=http_args, **kwargs)