def test_error_response(self):
        err = ResponseMessage(error='Illegal')
        http_resp = MockResponse(400, err.to_urlencoded())
        resp = self.client.parse_request_response(
            self.client.service['authorization'], http_resp)

        assert resp['error'] == 'Illegal'
        assert resp['status_code'] == 400
    def test_error_response_2(self):
        err = ResponseMessage(error='Illegal')
        http_resp = MockResponse(
            400,
            err.to_json(),
            headers={'content-type': 'application/x-www-form-urlencoded'})

        with pytest.raises(OidcServiceError):
            self.client.parse_request_response(
                self.client.service['authorization'], http_resp)
Example #3
0
    def test_error_message(self):
        err = ResponseMessage(error="invalid_request",
                              error_description="Something was missing",
                              error_uri="http://example.com/error_message.html")

        ue_str = err.to_urlencoded()
        del err["error_uri"]
        ueo_str = err.to_urlencoded()

        assert ue_str != ueo_str
        assert "error_message" not in ueo_str
        assert "error_message" in ue_str
        assert is_error_message(err)
Example #4
0
def do_endpoint(endpoint, **kwargs):
    try:
        authn = cherrypy.request.headers['Authorization']
    except KeyError:
        pr_args = {}
    else:
        pr_args = {'auth': authn}

    if endpoint.request_placement == 'body':
        if cherrypy.request.process_request_body is True:
            _request = cherrypy.request.body.read()
        else:
            raise cherrypy.HTTPError(400, 'Missing HTTP body')
        if not _request:
            _request = kwargs

        try:
            req_args = endpoint.parse_request(_request, **pr_args)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.exception(message)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            raise cherrypy.HTTPError(400, err_msg.to_json())
    else:
        try:
            req_args = endpoint.parse_request(kwargs, **pr_args)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.exception(message)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            raise cherrypy.HTTPError(400, err_msg.to_json())
    logger.info('request: {}'.format(req_args))

    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return as_bytes(req_args.to_json())

    try:
        if cherrypy.request.cookie:
            args = endpoint.process_request(req_args,
                                            cookie=cherrypy.request.cookie)
        else:
            args = endpoint.process_request(req_args)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        logger.exception(message)
        cherrypy.response.headers['Content-Type'] = 'text/html'
        err_msg = ResponseMessage(error='invalid_request',
                                  error_description=str(err))
        raise cherrypy.HTTPError(400, err_msg.to_json())

    if 'http_response' in args:
        return as_bytes(args['http_response'])

    return do_response(endpoint, req_args, **args)
Example #5
0
    def process_request(self, request=None, new_id=True, set_secret=True, **kwargs):
        try:
            reg_resp = self.client_registration_setup(request, new_id, set_secret)
        except Exception as err:
            return ResponseMessage(
                error="invalid_configuration_request", error_description="%s" % err
            )

        if "error" in reg_resp:
            return reg_resp
        else:
            _cookie = new_cookie(
                self.endpoint_context,
                cookie_name="oidc_op_rp",
                client_id=reg_resp["client_id"],
            )

            return {"response_args": reg_resp, "cookie": _cookie}
Example #6
0
    def process_request(self,
                        request=None,
                        new_id=True,
                        set_secret=True,
                        **kwargs):
        try:
            reg_resp = self.client_registration_setup(request, new_id,
                                                      set_secret)
        except Exception as err:
            logger.error("client_registration_setup: %s", request)
            return ResponseMessage(error="invalid_configuration_request",
                                   error_description="%s" % err)

        if "error" in reg_resp:
            return reg_resp
        else:
            _context = self.server_get("endpoint_context")
            _cookie = _context.new_cookie(
                name=_context.cookie_handler.name["register"],
                client_id=reg_resp["client_id"],
            )

            return {"response_args": reg_resp, "cookie": _cookie}
def test_error_description():
    msg = ResponseMessage(error="foobar", error_description="ÅÄÖ")
    with pytest.raises(ValueError):
        msg.verify()

    msg = ResponseMessage(error="foobar", error_description="abc\ndef")
    with pytest.raises(ValueError):
        msg.verify()

    msg = ResponseMessage(error="foobar", error_description="abc def")
    msg.verify()
Example #8
0
    def do_response(self,
                    response_args: Optional[dict] = None,
                    request: Optional[Union[Message, dict]] = None,
                    error: Optional[str] = "",
                    **kwargs) -> dict:
        """
        :param response_args: Information to use when constructing the response
        :param request: The original request
        :param error: Possible error encountered while processing the request
        """
        do_placement = True
        content_type = "text/html"
        _resp = {}
        _response_placement = None
        if response_args is None:
            response_args = {}

        LOGGER.debug("do_response kwargs: %s", kwargs)

        resp = None
        if error:
            _response = ResponseMessage(error=error)
            try:
                _response["error_description"] = kwargs["error_description"]
            except KeyError:
                pass
        elif "response_msg" in kwargs:
            resp = kwargs["response_msg"]
            _response_placement = kwargs.get("response_placement")
            do_placement = False
            _response = ""
            content_type = kwargs.get("content_type")
            if content_type is None:
                if self.response_format == "json":
                    content_type = "application/json"
                elif self.response_format in ["jws", "jwe", "jose"]:
                    content_type = "application/jose"
                else:
                    content_type = "application/x-www-form-urlencoded"
        else:
            _response = self.response_info(response_args, request, **kwargs)

        if do_placement:
            content_type = kwargs.get("content_type")
            if content_type is None:
                if self.response_placement == "body":
                    if self.response_format == "json":
                        content_type = "application/json; charset=utf-8"
                        resp = _response.to_json()
                    elif self.response_format in ["jws", "jwe", "jose"]:
                        content_type = "application/jose; charset=utf-8"
                        resp = _response
                    else:
                        content_type = "application/x-www-form-urlencoded"
                        resp = _response.to_urlencoded()
                elif self.response_placement == "url":
                    content_type = "application/x-www-form-urlencoded"
                    fragment_enc = kwargs.get("fragment_enc")
                    if not fragment_enc:
                        _ret_type = kwargs.get("return_type")
                        if _ret_type:
                            fragment_enc = fragment_encoding(_ret_type)
                        else:
                            fragment_enc = False

                    if fragment_enc:
                        resp = _response.request(kwargs["return_uri"], True)
                    else:
                        resp = _response.request(kwargs["return_uri"])
                else:
                    raise ValueError("Don't know where that is: '{}".format(
                        self.response_placement))

        if content_type:
            try:
                http_headers = set_content_type(kwargs["http_headers"],
                                                content_type)
            except KeyError:
                http_headers = [("Content-type", content_type)]
        else:
            try:
                http_headers = kwargs["http_headers"]
            except KeyError:
                http_headers = []

        if _response_placement:
            _resp["response_placement"] = _response_placement

        http_headers.extend(OAUTH2_NOCACHE_HEADERS)

        _resp.update({"response": resp, "http_headers": http_headers})

        try:
            _resp["cookie"] = kwargs["cookie"]
        except KeyError:
            pass

        return _resp
Example #9
0
    def do_response(self,
                    response_args=None,
                    request=None,
                    error='',
                    **kwargs):
        do_placement = True
        content_type = 'text/html'
        _resp = {}

        if response_args is None:
            response_args = {}

        if error:
            _response = ResponseMessage(error=error)
            try:
                _response['error_description'] = kwargs['error_description']
            except KeyError:
                pass
        elif 'response_msg' in kwargs:
            resp = kwargs['response_msg']
            do_placement = False
            _response = ''
            _resp['response_placement'] = 'body'
        else:
            _response = self.response_info(response_args, request, **kwargs)

        resp = None
        if do_placement:
            if self.response_placement == 'body':
                if self.response_format == 'json':
                    content_type = 'application/json'
                    resp = _response.to_json()
                elif self.request_format in ['jws', 'jwe', 'jose']:
                    content_type = 'application/jose'
                    resp = _response
                else:
                    content_type = 'application/x-www-form-urlencoded'
                    resp = _response.to_urlencoded()
            elif self.response_placement == 'url':
                # content_type = 'application/x-www-form-urlencoded'
                content_type = ''
                try:
                    fragment_enc = kwargs['fragment_enc']
                except KeyError:
                    fragment_enc = fragment_encoding(kwargs['return_type'])

                if fragment_enc:
                    resp = _response.request(kwargs['return_uri'], True)
                else:
                    resp = _response.request(kwargs['return_uri'])
            else:
                raise ValueError("Don't know where that is: '{}".format(
                    self.response_placement))

        if content_type:
            try:
                http_headers = set_content_type(kwargs['http_headers'],
                                                content_type)
            except KeyError:
                http_headers = [('Content-type', content_type)]
        else:
            try:
                http_headers = kwargs['http_headers']
            except KeyError:
                http_headers = []

        http_headers.extend(OAUTH2_NOCACHE_HEADERS)

        _resp.update({'response': resp, 'http_headers': http_headers})

        try:
            _resp['cookie'] = kwargs['cookie']
        except KeyError:
            pass

        return _resp
 def test_error_response_500(self):
     err = ResponseMessage(error='Illegal')
     http_resp = MockResponse(500, err.to_urlencoded())
     with pytest.raises(ParseError):
         self.client.parse_request_response(
             self.client.service['authorization'], http_resp)
Example #11
0
    def do_client_registration(self, request, client_id, ignore=None):
        if ignore is None:
            ignore = []

        _context = self.endpoint_context
        _cinfo = _context.cdb[client_id].copy()
        logger.debug("_cinfo: %s" % sanitize(_cinfo))

        for key, val in request.items():
            if key not in ignore:
                _cinfo[key] = val

        if "post_logout_redirect_uris" in request:
            plruri = []
            for uri in request["post_logout_redirect_uris"]:
                if urlparse(uri).fragment:
                    err = ClientRegistrationErrorResponse(
                        error="invalid_configuration_parameter",
                        error_description="post_logout_redirect_uris "
                        "contains "
                        "fragment")
                    return err
                base, query = splitquery(uri)
                if query:
                    plruri.append((base, parse_qs(query)))
                else:
                    plruri.append((base, query))
            _cinfo["post_logout_redirect_uris"] = plruri

        if "redirect_uris" in request:
            try:
                ruri = self.verify_redirect_uris(request)
                _cinfo["redirect_uris"] = ruri
            except InvalidRedirectURIError as e:
                return ClientRegistrationErrorResponse(
                    error="invalid_redirect_uri", error_description=str(e))

        if "sector_identifier_uri" in request:
            try:
                _cinfo["si_redirects"], _cinfo[
                    "sector_id"] = self._verify_sector_identifier(request)
            except InvalidSectorIdentifier as err:
                return ResponseMessage(error="invalid_configuration_parameter",
                                       error_description=err)
        elif "redirect_uris" in request:
            if len(request["redirect_uris"]) > 1:
                # check that the hostnames are the same
                host = ""
                for url in request["redirect_uris"]:
                    part = urlparse(url)
                    _host = part.netloc.split(":")[0]
                    if not host:
                        host = _host
                    else:
                        try:
                            assert host == _host
                        except AssertionError:
                            return ResponseMessage(
                                error="invalid_configuration_parameter",
                                error_description="'sector_identifier_uri' "
                                "must be registered")

        for item in ["policy_uri", "logo_uri", "tos_uri"]:
            if item in request:
                if verify_url(request[item], _cinfo["redirect_uris"]):
                    _cinfo[item] = request[item]
                else:
                    return ResponseMessage(
                        error="invalid_configuration_parameter",
                        error_description="%s pointed to illegal URL" % item)

        # Do I have the necessary keys
        for item in [
                "id_token_signed_response_alg", "userinfo_signed_response_alg"
        ]:
            if item in request:
                if request[item] in _context.provider_info[
                        PREFERENCE2PROVIDER[item]]:
                    ktyp = alg2keytype(request[item])
                    # do I have this ktyp and for EC type keys the curve
                    if ktyp not in ["none", "oct"]:
                        _k = []
                        for iss in ['', _context.issuer]:
                            _k.extend(
                                _context.keyjar.get_signing_key(
                                    ktyp, alg=request[item], owner=iss))
                        if not _k:
                            logger.warning('Lacking support for "{}"'.format(
                                request[item]))
                            del _cinfo[item]

        t = {'jwks_uri': '', 'jwks': None}

        for item in ['jwks_uri', 'jwks']:
            if item in request:
                t[item] = request[item]

        try:
            _context.keyjar.load_keys(client_id,
                                      jwks_uri=t['jwks_uri'],
                                      jwks=t['jwks'])
            try:
                n_keys = len(_context.keyjar[client_id])
                msg = "found {} keys for client_id={}"
                logger.debug(msg.format(n_keys, client_id))
            except KeyError:
                pass
        except Exception as err:
            logger.error("Failed to load client keys: %s" %
                         sanitize(request.to_dict()))
            logger.error("%s", err)
            logger.debug('Verify SSL: {}'.format(_context.keyjar.verify_ssl))
            return ClientRegistrationErrorResponse(
                error="invalid_configuration_parameter",
                error_description="%s" % err)

        return _cinfo
Example #12
0
    def client_registration_setup(self, request, new_id=True, set_secret=True):
        try:
            request.verify()
        except MessageException as err:
            if "type" not in request:
                return ResponseMessage(error="invalid_type",
                                       error_description="%s" % err)
            else:
                return ResponseMessage(error="invalid_configuration_parameter",
                                       error_description="%s" % err)

        request.rm_blanks()
        try:
            self.match_client_request(request)
        except CapabilitiesMisMatch as err:
            return ResponseMessage(
                error="invalid_request",
                error_description="Don't support proposed %s" % err)

        _context = self.endpoint_context
        if new_id:
            # create new id och secret
            client_id = rndstr(12)
            while client_id in _context.cdb:
                client_id = rndstr(12)
        else:
            try:
                client_id = request['client_id']
            except KeyError:
                raise ValueError('Missing client_id')

        _rat = rndstr(32)

        _cinfo = {
            "client_id":
            client_id,
            "registration_access_token":
            _rat,
            "registration_client_uri":
            "%s?client_id=%s" % (self.endpoint_path, client_id),
            "client_salt":
            rndstr(8)
        }

        if new_id:
            _cinfo["client_id_issued_at"] = utc_time_sans_frac()

        if set_secret:
            client_secret = secret(_context.seed, client_id)
            _cinfo.update({
                "client_secret":
                client_secret,
                "client_secret_expires_at":
                client_secret_expiration_time()
            })
        else:
            client_secret = ''

        _context.cdb[client_id] = _cinfo
        _context.cdb[_rat] = client_id

        _cinfo = self.do_client_registration(
            request,
            client_id,
            ignore=["redirect_uris", "policy_uri", "logo_uri", "tos_uri"])
        if isinstance(_cinfo, ResponseMessage):
            return _cinfo

        args = dict([(k, v) for k, v in _cinfo.items()
                     if k in RegistrationResponse.c_param])

        self.comb_uri(args)
        response = RegistrationResponse(**args)

        # Add the client_secret as a symmetric key to the key jar
        if client_secret:
            _context.keyjar.add_symmetric(client_id, str(client_secret))

        _context.cdb[client_id] = _cinfo

        try:
            _context.cdb.sync()
        except AttributeError:  # Not all databases can be sync'ed
            pass

        logger.info("registration_response: %s" % sanitize(response.to_dict()))

        return response
Example #13
0
    def client_registration_setup(self, request, new_id=True, set_secret=True):
        try:
            request.verify()
        except (MessageException, ValueError) as err:
            logger.error("request.verify() on %s", request)
            return ResponseMessage(error="invalid_configuration_request",
                                   error_description="%s" % err)

        request.rm_blanks()
        try:
            self.match_client_request(request)
        except CapabilitiesMisMatch as err:
            return ResponseMessage(
                error="invalid_request",
                error_description="Don't support proposed %s" % err,
            )

        _context = self.server_get("endpoint_context")
        if new_id:
            if self.kwargs.get("client_id_generator"):
                cid_generator = importer(
                    self.kwargs["client_id_generator"]["class"])
                cid_gen_kwargs = self.kwargs["client_id_generator"].get(
                    "kwargs", {})
            else:
                cid_generator = importer(
                    "oidcop.oidc.registration.random_client_id")
                cid_gen_kwargs = {}
            client_id = cid_generator(reserved=_context.cdb.keys(),
                                      **cid_gen_kwargs)
            if "client_id" in request:
                del request["client_id"]
        else:
            client_id = request.get("client_id")
            if not client_id:
                raise ValueError("Missing client_id")

        _cinfo = {"client_id": client_id, "client_salt": rndstr(8)}

        if self.server_get("endpoint", "registration_read"):
            self.add_registration_api(_cinfo, client_id, _context)

        if new_id:
            _cinfo["client_id_issued_at"] = utc_time_sans_frac()

        client_secret = ""
        if set_secret:
            client_secret = self.add_client_secret(_cinfo, client_id, _context)

        logger.debug(
            "Stored client info in CDB under cid={}".format(client_id))

        _context.cdb[client_id] = _cinfo
        _cinfo = self.do_client_registration(
            request,
            client_id,
            ignore=["redirect_uris", "policy_uri", "logo_uri", "tos_uri"],
        )
        if isinstance(_cinfo, ResponseMessage):
            return _cinfo

        args = dict([(k, v) for k, v in _cinfo.items()
                     if k in self.response_cls.c_param])

        comb_uri(args)
        response = self.response_cls(**args)

        # Add the client_secret as a symmetric key to the key jar
        if client_secret:
            _context.keyjar.add_symmetric(client_id, str(client_secret))

        logger.debug(
            "Stored updated client info in CDB under cid={}".format(client_id))
        logger.debug("ClientInfo: {}".format(_cinfo))
        _context.cdb[client_id] = _cinfo

        # Not all databases can be sync'ed
        if hasattr(_context.cdb, "sync") and callable(_context.cdb.sync):
            _context.cdb.sync()

        msg = "registration_response: {}"
        logger.info(msg.format(sanitize(response.to_dict())))

        return response
Example #14
0
def service_endpoint(endpoint):
    _log = current_app.logger
    _log.info('At the "{}" endpoint'.format(endpoint.name))

    if request.method == 'GET':
        if request.args:
            _req_args = request.args.to_dict()
        else:
            _req_args = {}
        try:
            req_args = endpoint.parse_request(_req_args)
        except (InvalidClient, UnknownClient) as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'unauthorized_client',
                    'error_description': str(err)
                }), 400)
        except Exception as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'invalid_request',
                    'error_description': str(err)
                }), 400)
    else:
        if request.data:
            if isinstance(request.data, str):
                req_args = request.data
            else:
                req_args = request.data.decode()
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        try:
            req_args = endpoint.parse_request(req_args)
        except Exception as err:
            _log.error(err)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            return make_response(err_msg.to_json(), 400)

    _log.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        args = endpoint.process_request(req_args)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        _log.error(message)
        err_msg = ResponseMessage(error='invalid_request',
                                  error_description=str(err))
        return make_response(err_msg.to_json(), 400)

    _log.info('Response args: {}'.format(args))

    if 'redirect_location' in args:
        return redirect(args['redirect_location'])
    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    response = do_response(endpoint, req_args, **args)
    return response
Example #15
0
    def client_registration_setup(self, request, new_id=True, set_secret=True):
        try:
            request.verify()
        except (MessageException, ValueError) as err:
            return ResponseMessage(
                error="invalid_configuration_request", error_description="%s" % err
            )

        request.rm_blanks()
        try:
            self.match_client_request(request)
        except CapabilitiesMisMatch as err:
            return ResponseMessage(
                error="invalid_request",
                error_description="Don't support proposed %s" % err,
            )

        _context = self.endpoint_context
        if new_id:
            # create new id och secret
            client_id = rndstr(12)
            while client_id in _context.cdb:
                client_id = rndstr(12)
        else:
            try:
                client_id = request["client_id"]
            except KeyError:
                raise ValueError("Missing client_id")

        _cinfo = {"client_id": client_id, "client_salt": rndstr(8)}

        if "registration_api" in self.endpoint_context.endpoint:
            self.add_registration_api(_cinfo, client_id, _context)

        if new_id:
            _cinfo["client_id_issued_at"] = utc_time_sans_frac()

        if set_secret:
            client_secret = self.add_client_secret(_cinfo, client_id, _context)
        else:
            client_secret = ""

        _context.cdb[client_id] = _cinfo

        _cinfo = self.do_client_registration(
            request,
            client_id,
            ignore=["redirect_uris", "policy_uri", "logo_uri", "tos_uri"],
        )
        if isinstance(_cinfo, ResponseMessage):
            return _cinfo

        args = dict(
            [(k, v) for k, v in _cinfo.items() if k in RegistrationResponse.c_param]
        )

        comb_uri(args)
        response = RegistrationResponse(**args)

        # Add the client_secret as a symmetric key to the key jar
        if client_secret:
            _context.keyjar.add_symmetric(client_id, str(client_secret))

        _context.cdb[client_id] = _cinfo

        try:
            _context.cdb.sync()
        except AttributeError:  # Not all databases can be sync'ed
            pass

        logger.info("registration_response: %s" % sanitize(response.to_dict()))

        return response
Example #16
0
    def do_client_registration(self, request, client_id, ignore=None):
        if ignore is None:
            ignore = []

        _context = self.endpoint_context
        _cinfo = _context.cdb[client_id].copy()
        logger.debug("_cinfo: %s" % sanitize(_cinfo))

        for key, val in request.items():
            if key not in ignore:
                _cinfo[key] = val

        if "post_logout_redirect_uris" in request:
            plruri = []
            for uri in request["post_logout_redirect_uris"]:
                if urlparse(uri).fragment:
                    err = ClientRegistrationErrorResponse(
                        error="invalid_configuration_parameter",
                        error_description="post_logout_redirect_uris "
                        "contains "
                        "fragment",
                    )
                    return err
                base, query = splitquery(uri)
                if query:
                    plruri.append((base, parse_qs(query)))
                else:
                    plruri.append((base, query))
            _cinfo["post_logout_redirect_uris"] = plruri

        if "redirect_uris" in request:
            try:
                ruri = self.verify_redirect_uris(request)
                _cinfo["redirect_uris"] = ruri
            except InvalidRedirectURIError as e:
                return ClientRegistrationErrorResponse(
                    error="invalid_redirect_uri", error_description=str(e)
                )

        if "sector_identifier_uri" in request:
            try:
                _cinfo["si_redirects"], _cinfo[
                    "sector_id"
                ] = self._verify_sector_identifier(request)
            except InvalidSectorIdentifier as err:
                return ResponseMessage(
                    error="invalid_configuration_parameter", error_description=str(err)
                )

        for item in ["policy_uri", "logo_uri", "tos_uri"]:
            if item in request:
                if verify_url(request[item], _cinfo["redirect_uris"]):
                    _cinfo[item] = request[item]
                else:
                    return ResponseMessage(
                        error="invalid_configuration_parameter",
                        error_description="%s pointed to illegal URL" % item,
                    )

        # Do I have the necessary keys
        for item in ["id_token_signed_response_alg", "userinfo_signed_response_alg"]:
            if item in request:
                if request[item] in _context.provider_info[PREFERENCE2PROVIDER[item]]:
                    ktyp = alg2keytype(request[item])
                    # do I have this ktyp and for EC type keys the curve
                    if ktyp not in ["none", "oct"]:
                        _k = []
                        for iss in ["", _context.issuer]:
                            _k.extend(
                                _context.keyjar.get_signing_key(
                                    ktyp, alg=request[item], owner=iss
                                )
                            )
                        if not _k:
                            logger.warning(
                                'Lacking support for "{}"'.format(request[item])
                            )
                            del _cinfo[item]

        t = {"jwks_uri": "", "jwks": None}

        for item in ["jwks_uri", "jwks"]:
            if item in request:
                t[item] = request[item]

        # if it can't load keys because the URL is false it will
        # just silently fail. Waiting for better times.
        _context.keyjar.load_keys(client_id, jwks_uri=t["jwks_uri"], jwks=t["jwks"])
        try:
            n_keys = 0
            for kb in _context.keyjar[client_id]:
                n_keys += len(kb.keys())
            msg = "found {} keys for client_id={}"
            logger.debug(msg.format(n_keys, client_id))
        except KeyError:
            pass

        return _cinfo
Example #17
0
def service_endpoint(endpoint):
    _log = current_app.srv_config.logger
    _log.info('At the "{}" endpoint'.format(endpoint.endpoint_name))

    try:
        authn = request.headers['Authorization']
    except KeyError:
        pr_args = {}
    else:
        pr_args = {'auth': authn}

    if request.method == 'GET':
        try:
            req_args = endpoint.parse_request(request.args.to_dict(),
                                              **pr_args)
        except (InvalidClient, UnknownClient) as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'unauthorized_client',
                    'error_description': str(err)
                }), 400)
        except Exception as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'invalid_request',
                    'error_description': str(err)
                }), 400)
    else:
        if request.data:
            if isinstance(request.data, str):
                req_args = request.data
            else:
                req_args = request.data.decode()
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        try:
            req_args = endpoint.parse_request(req_args, **pr_args)
        except Exception as err:
            _log.error(err)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            return make_response(err_msg.to_json(), 400)

    _log.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        if request.cookies:
            _log.debug(request.cookies)
            kwargs = {'cookie': request.cookies}
        else:
            kwargs = {}

        if isinstance(endpoint, AccessToken):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            **kwargs)
        else:
            args = endpoint.process_request(req_args, **kwargs)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        _log.error(message)
        err_msg = ResponseMessage(error='invalid_request',
                                  error_description=str(err))
        return make_response(err_msg.to_json(), 400)

    _log.info('Response args: {}'.format(args))

    if 'redirect_location' in args:
        return redirect(args['redirect_location'])
    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    return do_response(endpoint, req_args, **args)
Example #18
0
    def do_response(self,
                    response_args=None,
                    request=None,
                    error="",
                    **kwargs):
        """

        """
        do_placement = True
        content_type = "text/html"
        _resp = {}
        _response_placement = None
        if response_args is None:
            response_args = {}

        LOGGER.debug("do_response kwargs: %s", kwargs)

        resp = None
        if error:
            _response = ResponseMessage(error=error)
            try:
                _response["error_description"] = kwargs["error_description"]
            except KeyError:
                pass
        elif "response_msg" in kwargs:
            resp = kwargs["response_msg"]
            _response_placement = kwargs.get('response_placement')
            do_placement = False
            _response = ""
            content_type = kwargs.get('content_type')
            if content_type is None:
                if self.response_format == "json":
                    content_type = "application/json"
                elif self.request_format in ["jws", "jwe", "jose"]:
                    content_type = "application/jose"
                else:
                    content_type = "application/x-www-form-urlencoded"
        else:
            _response = self.response_info(response_args, request, **kwargs)

        if do_placement:
            content_type = kwargs.get('content_type')
            if content_type is None:
                if self.response_placement == "body":
                    if self.response_format == "json":
                        content_type = "application/json"
                        resp = _response.to_json()
                    elif self.request_format in ["jws", "jwe", "jose"]:
                        content_type = "application/jose"
                        resp = _response
                    else:
                        content_type = "application/x-www-form-urlencoded"
                        resp = _response.to_urlencoded()
                elif self.response_placement == "url":
                    # content_type = 'application/x-www-form-urlencoded'
                    content_type = ""
                    try:
                        fragment_enc = kwargs["fragment_enc"]
                    except KeyError:
                        _ret_type = kwargs.get("return_type")
                        if _ret_type:
                            fragment_enc = fragment_encoding(_ret_type)
                        else:
                            fragment_enc = False

                    if fragment_enc:
                        resp = _response.request(kwargs["return_uri"], True)
                    else:
                        resp = _response.request(kwargs["return_uri"])
                else:
                    raise ValueError("Don't know where that is: '{}".format(
                        self.response_placement))

        if content_type:
            try:
                http_headers = set_content_type(kwargs["http_headers"],
                                                content_type)
            except KeyError:
                http_headers = [("Content-type", content_type)]
        else:
            try:
                http_headers = kwargs["http_headers"]
            except KeyError:
                http_headers = []

        if _response_placement:
            _resp["response_placement"] = _response_placement

        http_headers.extend(OAUTH2_NOCACHE_HEADERS)

        _resp.update({"response": resp, "http_headers": http_headers})

        try:
            _resp["cookie"] = kwargs["cookie"]
        except KeyError:
            pass

        return _resp
Example #19
0
def service_endpoint(endpoint):
    _log = current_app.logger
    _log.info('At the "{}" endpoint'.format(endpoint.name))

    http_info = {
        "headers": {
            k: v
            for k, v in request.headers.items(lower=True) if k not in IGNORE
        },
        "method": request.method,
        "url": request.url,
        # name is not unique
        "cookie": [{
            "name": k,
            "value": v
        } for k, v in request.cookies.items()]
    }

    if request.method == 'GET':
        try:
            req_args = endpoint.parse_request(request.args.to_dict(),
                                              http_info=http_info)
        except (InvalidClient, UnknownClient) as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'unauthorized_client',
                    'error_description': str(err)
                }), 400)
        except Exception as err:
            _log.error(err)
            return make_response(
                json.dumps({
                    'error': 'invalid_request',
                    'error_description': str(err)
                }), 400)
    else:
        if request.data:
            if isinstance(request.data, str):
                req_args = request.data
            else:
                req_args = request.data.decode()
        else:
            req_args = dict([(k, v) for k, v in request.form.items()])
        try:
            req_args = endpoint.parse_request(req_args, http_info=http_info)
        except Exception as err:
            _log.error(err)
            err_msg = ResponseMessage(error='invalid_request',
                                      error_description=str(err))
            return make_response(err_msg.to_json(), 400)

    _log.info('request: {}'.format(req_args))
    if isinstance(req_args, ResponseMessage) and 'error' in req_args:
        return make_response(req_args.to_json(), 400)

    try:
        if isinstance(endpoint, Token):
            args = endpoint.process_request(AccessTokenRequest(**req_args),
                                            http_info=http_info)
        else:
            args = endpoint.process_request(req_args, http_info=http_info)
    except Exception as err:
        message = traceback.format_exception(*sys.exc_info())
        _log.error(message)
        err_msg = ResponseMessage(error='invalid_request',
                                  error_description=str(err))
        return make_response(err_msg.to_json(), 400)

    _log.info('Response args: {}'.format(args))

    if 'redirect_location' in args:
        return redirect(args['redirect_location'])
    if 'http_response' in args:
        return make_response(args['http_response'], 200)

    response = do_response(endpoint, req_args, **args)
    return response