Ejemplo n.º 1
0
    def __init__(self, configuration=None, baseurl=""):

        self.conf_info = configuration or {}
        self.resource_set = MemResourceSetDB()
        self.rpt = {}
        self.baseurl = baseurl
        if not self.baseurl.endswith("/"):
            self.baseurl += "/"
        self.session = Session()
        self.permit = Permission()
        self.permission_requests = PermissionRequests()
        self.map_rsid_id = {}
        self.map_id_rsid = {}
        self.map_user_id = {}
        self.eid2rpt = {}
        self.get_requester = get_requester
Ejemplo n.º 2
0
    def __init__(self, configuration=None, baseurl=""):

        self.conf_info = configuration or {}
        self.resource_set = MemResourceSetDB()
        self.rpt = {}
        self.baseurl = baseurl
        if not self.baseurl.endswith("/"):
            self.baseurl += "/"
        self.session = Session()
        self.permit = Permission()
        self.permission_requests = PermissionRequests()
        self.map_rsid_id = {}
        self.map_id_rsid = {}
        self.map_user_id = {}
        self.eid2rpt = {}
        self.get_requester = get_requester
Ejemplo n.º 3
0
class UmaAS(object):
    endp = [
        AuthorizationEndpoint,
        DynamicClientEndpoint,
        IntrospectionEndpoint,
        PermissionRegistrationEndpoint,
        RequestingPartyClaimsEndpoint,
        ResourceSetRegistrationEndpoint,
        RPTEndpoint,
        TokenEndpoint,
        ClientInfoEndpoint,
    ]

    def __init__(self, configuration=None, baseurl=""):

        self.conf_info = configuration or {}
        self.resource_set = MemResourceSetDB()
        self.rpt = {}
        self.baseurl = baseurl
        if not self.baseurl.endswith("/"):
            self.baseurl += "/"
        self.session = Session()
        self.permit = Permission()
        self.permission_requests = PermissionRequests()
        self.map_rsid_id = {}
        self.map_id_rsid = {}
        self.map_user_id = {}
        self.eid2rpt = {}
        self.get_requester = get_requester

    def endpoints(self):
        for endp in self.endp:
            yield endp(None).name

    def services(self):
        for endp in self.endp:
            yield endp.etype

    # def rpt_endpoint_(self, requestor, client_id, **kwargs):
    # """
    # The endpoint URI at which the client asks the authorization server for
    # a RPT.
    #     """
    #     #res = self.client_authentication(authn)
    #     #if isinstance(res, Response):
    #     #    return res
    #
    #     # create RPT, just overwrites whatever was there before
    #     rpt = rndstr(32)
    #     self.rpt[rpt] = {"requestor": requestor, "client_id": client_id}
    #     self.session.set(rpt)
    #
    #     msg = RPTResponse(rpt=rpt)
    #     return Response(msg.to_json(), content="application/json")

    def resource_set_registration_endpoint_(self, entity, path, method, client_id, body="", if_match="", **kwargs):
        """
        The endpoint at which the resource server handles resource sets
        descriptions.

        :param entity: The entity that controls the resource set
        :param path:
        :param method: HTTP method
        :param body: The resource set registration message
        :paran client_id: Which client I'm talking to
        :param if_match: The HTTP If-Match header if any
        :param kwargs: possible other arguments
        :returns: A Response instance
        """

        # path should be /resource_set/{rsid} or /resource_set
        # Path may or may not start with '/'
        if path.startswith("/"):
            assert path[1:].startswith(RSR_PATH)
            rsid = path[PLEN + 1 :]
        else:
            assert path.startswith(RSR_PATH)
            rsid = path[PLEN:]

        if rsid.startswith("/"):
            rsid = rsid[1:]

        _user = safe_name(entity, client_id)
        logger.debug("handling resource set belonging to '%s'" % _user)
        #  self.resource_set.set_collection(_user)
        if method == "POST":  # create
            args = {"oid": _user, "data": body}
            func = self.resource_set.create
        elif method == "PUT":  # update
            args = {
                "oid": _user,
                "data": body,
                "rsid": rsid,
                # "if_match": if_match
            }
            func = self.resource_set.update
        elif method == "GET":
            args = {"oid": _user}
            if not rsid:  # List
                func = self.resource_set.list
            else:  # Read
                func = self.resource_set.read
                args["rsid"] = rsid
        elif method == "DELETE":
            args = {"rsid": rsid, "oid": _user}
            func = self.resource_set.delete
        else:
            return BadRequest("Message error")

        logger.debug("operation: %s" % func)
        logger.debug("operation args: %s" % (args,))
        try:
            body = func(**args)
        except MessageException as err:
            _err = ErrorResponse(error="invalid_request", error_description=str(err))
            response = BadRequest(_err.to_json(), content="application/json")
        except UnknownObject:
            _err = ErrorResponse(error="not_found")
            response = NotFound(_err.to_json(), content="application/json")
        else:
            response = None
            if isinstance(body, ErrorResponse):
                pass
            else:
                if func == self.resource_set.delete:
                    # As a side effect all permissions assigned that references
                    # this resource set should be deleted
                    self.permit.delete_permit_by_resource_id(entity, rsid)
                    response = NoContent()
                elif func == self.resource_set.create:
                    _etag = self.resource_set.etag[body["_id"]]
                    response = Created(
                        body.to_json(),
                        content="application/json",
                        headers=[("ETag", _etag), ("Location", "/{}/{}".format(RSR_PATH, body["_id"]))],
                    )
                elif func == self.resource_set.update:
                    _etag = self.resource_set.etag[body["_id"]]
                    response = NoContent(content="application/json", headers=[("ETag", _etag)])
                elif func == self.resource_set.list:
                    response = Response(json.dumps(body))

            if not response:
                response = Response(body.to_json(), content="application/json")

        return response

    def _collapse(self, items):
        referenced = {}
        ibrsid = {}
        for item in items:
            try:
                for rsid in item["subsets"]:
                    if rsid not in referenced:
                        referenced[rsid] = 1
                    else:
                        referenced[rsid] += 1
            except KeyError:
                pass

            _rsid = self.map_id_rsid[item["_id"]]
            if _rsid not in referenced:
                referenced[_rsid] = 0
            ibrsid[_rsid] = item

        res = []
        for key, val in list(referenced.items()):
            if val == 0:
                res.append(ibrsid[key])

        return res

    def resource_sets_by_user(self, entity, client_id, collapse=False):
        """
        :param entity: The entity for which resource set descriptions has been
            registered.
        :return: A list of ResourceSetDescriptions
        """
        res = []
        _user = safe_name(entity, client_id)
        try:
            rss = self.resource_set.list(_user)
        except KeyError:
            return []

        for _id in rss:
            try:
                res.append(self.resource_set.read(_user, _id))
            except Exception:
                raise

        if collapse:
            res = self._collapse(res)

        return res

    # def resource_set_tree_by_rsid(self, owner, rsid):
    #     rs = self.resource_set.read(owner, rsid)
    #     _name = rs["name"].split("/")[-1]
    #     try:
    #         _rsids = rs["subsets"]
    #     except KeyError:
    #         return rsid, _name
    #     else:
    #         res = {}
    #         for _rsid in _rsids:
    #             _rs = self.resource_set_tree_by_rsid(owner, _rsid)
    #             try:
    #                 res.update(_rs)
    #             except ValueError:
    #                 try:
    #                     res.append(_rs)
    #                 except AttributeError:
    #                     res = [_rs]
    #
    #         return {(rsid, _name): res}
    #
    # def resource_set_name(self, rsid):
    #     rs = self.resource_set.read(self.map_rsid_id[rsid])
    #     return rs["name"]

    def permits_by_user(self, owner):
        """
        :param owner: The owner of the resource
        :return: A dictionary with requestors as keys and permissions as values
        """
        return self.permit.get_permits(owner)

    def authz_session_info(self, token):
        pass

    def introspection_endpoint_(self, entity, **kwargs):
        """
        The endpoint URI at which the resource server introspects an RPT
        presented to it by a client.
        """

        request = kwargs["request"]
        logger.debug("requestor: %s, request: %s" % (entity, request))
        ir = IntrospectionRequest().from_json(request)
        owner = safe_name(entity, kwargs["client_id"])
        try:
            try:
                # requestor = self.rpt[ir["token"]]["requestor"]
                perms = self.permit.get_accepted(owner, ir["token"])
            except KeyError:
                response = BadRequest()
            else:
                if perms:
                    irep = IntrospectionResponse(active=True, exp=perms[0]["exp"], permissions=perms)
                    logger.debug("response: %s" % irep.to_json())
                    response = Response(irep.to_json(), content="application/json")
                else:
                    logger.info("No permissions bound to this RPT")
                    response = BadRequest()
        except ToOld:
            logger.info("RPT expired")
            irep = IntrospectionResponse(valid=False)
            response = Response(irep.to_json(), content="application/json")
        except KeyError:
            response = BadRequest()

        return response

    def permission_registration_endpoint_(self, entity, **kwargs):
        """
        The endpoint URI at which the resource server registers a
        client-requested permission with the authorization server.
        This is a proposed permission waiting for the user to accept it.
        """
        request = kwargs["request"]
        _ticket = rndstr(24)
        logging.debug("Registering permission request: %s" % request)
        resp = PermissionRegistrationResponse(ticket=_ticket)
        self.permission_requests.add_request(_ticket, request)

        return Created(resp.to_json(), content="application/json")

    def requesting_party_claims_endpoint(self, request="", **kwargs):
        """
        The endpoint at which the resource server gathers the consent of
        the end-user resource owner or the client gathers the consent of the
        end-user requesting party, if the "authorization_code" grant type is
        used.
        """
        pass

    def dynamic_client_endpoint(self, request="", **kwargs):
        pass

    def token_endpoint(self, request="", **kwargs):
        pass

    def authorization_endpoint(self, request="", **kwargs):
        pass

    @staticmethod
    def token_scope_check(areq, info):
        """
        verifies that the scope that is demanded for the access token is
        one that I'm comfortable with.

        :param areq: AccessTokenRequest
        :param info: What's in the session db
        :return: None if OK otherwise and error response.
        """
        try:
            assert areq["scope"] in info["scope"]
        except AssertionError:
            logger.error("Not the same scope as for the AuthzRequest")
            err = TokenErrorResponse(error="invalid_scope")
            return Response(err.to_json(), content="application/json")

        try:
            assert areq["scope"] in list(UMA_SCOPE.values())
        except AssertionError:
            logger.error("Asked for scope which I don't deal with")
            err = TokenErrorResponse(error="invalid_scope")
            return Response(err.to_json(), content="application/json")

        return None

    def create_uma_providerinfo(self, pcr_class=ProviderConfiguration):
        kwargs = dict([(k, v) for k, v in list(self.conf_info.items()) if k in pcr_class.c_param])
        _response = pcr_class(**kwargs)

        for endp in UmaAS.endp:
            _response.update(endpoint_ava(endp, self.baseurl))

        logger.debug("provider_info_response: %s" % (_response.to_dict(),))
        return _response

    # noinspection PyUnusedLocal
    def providerinfo_endpoint_(self, handle="", **kwargs):
        logger.debug("@providerinfo_endpoint")
        try:
            _response = self.create_uma_providerinfo()

            headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")]
            # if handle:
            #     (key, timestamp) = handle
            #     if key.startswith(STR) and key.endswith(STR):
            #         cookie = self.cookie_func(key, self.cookie_name, "pinfo",
            #                                   self.sso_ttl)
            #         headers.append(cookie)

            resp = Response(_response.to_json(), content="application/json", headers=headers)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.error(message)
            resp = Response(message, content="html/text")

        return resp

    def get_subsets(self, owner, requestor, scopes):
        res = {}
        try:
            permits = self.permit.get_permit_by_requestor(owner, requestor)
        except KeyError:
            return res

        for permit, (_scopes, time_stamp) in list(permits.items()):
            _scs = []
            for scope in scopes:
                try:
                    assert scope in _scopes
                except AssertionError:
                    pass
                else:
                    _scs.append(scope)
            if _scs:
                res[permit] = _scs
        return res

    def register_permission(self, owner, rpt, rsid, scopes):
        now = utc_time_sans_frac()
        perm = AuthzDescription(resource_set_id=rsid, scopes=scopes, exp=now + self.session.lifetime, iat=now)

        self.permit.set_accepted(owner, rpt, perm)

    def rpt_endpoint_(self, entity, client_id, **kwargs):
        """
        Registers an Authorization Description

        :param entity: Who's on the other side
        :param client_id: The UMA client
        :return: A Response instance
        """

        adr = AuthorizationDataRequest().from_json(kwargs["request"])

        # Get request permission that the resource server has registered
        try:
            prr_list = self.permission_requests.get_request(adr["ticket"])
        except KeyError:
            errmsg = ErrorResponse(error="invalid_ticket")
            return BadRequest(errmsg.to_json(), content="application/json")

        self.permission_requests.del_request(adr["ticket"])
        try:
            _rpt = adr["rpt"]
        except KeyError:
            _rpt = rndstr(32)

        for prr in prr_list:
            _rsid = prr["resource_set_id"]

            # Verify that the scopes are defined for the resource set
            owner = self.resource_set.rsid2oid[_rsid]
            rsd = self.resource_set.read(owner, _rsid)
            for scope in prr["scopes"]:
                try:
                    assert scope in rsd["scopes"]
                except AssertionError:
                    errmsg = ErrorResponse(error="not_authorized", error_description="Undefined scopes")
                    return BadRequest(errmsg.to_json(), content="application/json")

            # Is there any permissions registered by the owner, if so verify
            # that it allows what is requested. Return what is allowed !

            try:
                allow_scopes, timestamp = self.permit.get_permit(owner, entity, _rsid)
            except KeyError:  #
                errmsg = ErrorResponse(error="not_authorized", error_description="No permission given")
                return BadRequest(errmsg.to_json(), content="application/json")
            else:
                _scopes = []
                for scope in prr["scopes"]:
                    try:
                        assert scope in allow_scopes
                    except AssertionError:
                        pass
                    else:
                        _scopes.append(scope)

                # bind _requester to specific RPT for this user
                try:
                    self.eid2rpt[owner][entity] = _rpt
                except KeyError:
                    self.eid2rpt[owner] = {entity: _rpt}

                self.register_permission(owner, _rpt, _rsid, _scopes)

        rsp = AuthorizationDataResponse(rpt=_rpt)

        return Response(rsp.to_json())

    def name2id(self, owner, requestor, rsid):
        _user = safe_name(owner, requestor)
        obj = self.resource_set.read(_user, rsid)
        return obj["_id"]

    def remove_permission(self, owner, requestor, resource_name):
        """
        :param owner: The resource owner
        :param requestor: The SP entity ID
        :param resource_name: The name of the resource set
        """
        _id = self.name2id(owner, requestor, resource_name)

        try:
            self.permit.delete_permit(owner, requestor, _id)
        except KeyError:
            pass

        try:
            _user = "******" % (owner, requestor)
            rm_rpt = self.permit.rm_accepted(_user, _id)
        except KeyError:
            pass
        else:
            for _rpt in rm_rpt:
                # immediate expiration
                self.session.update(_rpt, expires_at=0)

    def store_permission(self, user, requestor, rsids):
        """
        :param user: The resource owner
        :param requestor: The requestor ID
        :param rsids: dictionary with Resource set IDs as keys and scopes
            as values
        """

        logger.info("store: (%s, %s, %s)" % (user, requestor, rsids))

        present = self.permit.get_rsid_permits(user, requestor)
        _new = [k for k in list(rsids.keys()) if k not in present]
        _user = safe_name(user, requestor)
        for rsid in _new:
            scopes = rsids[rsid]
            if scopes is None:
                rs = self.resource_set.read(_user, rsid)
                scopes = rs["scopes"]
            self.permit.set_permit(user, requestor, rsid, scopes)

        _rem = [k for k in present if k not in rsids]
        for rsid in _rem:
            self.permit.delete_permit(user, requestor, rsid)

    def read_permission(self, user, requestor, rsid):
        return self.permit.get_permit(user, requestor, rsid)

    def rec_rm_permission(self, user, requestor, rsid):
        """
        If the resource set is a complex set, remove all subset permissions
        :param user: The owner of the resource
        :param requestor: Who the permission is applying to
        :param rsid: The resource set name
        """
        _user = safe_name(user, requestor)
        rs = self.resource_set.read(_user, rsid)
        if "subsets" in rs:
            for ss in rs["subsets"]:
                self.rec_rm_permission(user, requestor, ss)
        try:
            self.permit.delete_permit(user, requestor, rsid)
        except KeyError:
            pass

    def rm_permission(self, user, requestor, rsid):
        """
        If the resource set is a complex set, remove all subset permissions
        :param user: The owner of the resource
        :param requestor: Who the permission is applying to
        :param rsid: The resource set name
        """
        logger.info("remove: (%s, %s, %s)" % (user, requestor, rsid))
        self.rec_rm_permission(user, requestor, rsid)
        return True

    def rsid_permits(self, user, requestor):
        return self.permit.get_rsid_permits(user, requestor)
Ejemplo n.º 4
0
class UmaAS(object):
    endp = [
        AuthorizationEndpoint, DynamicClientEndpoint, IntrospectionEndpoint,
        PermissionRegistrationEndpoint, RequestingPartyClaimsEndpoint,
        ResourceSetRegistrationEndpoint, RPTEndpoint, TokenEndpoint,
        ClientInfoEndpoint
    ]

    def __init__(self, configuration=None, baseurl=""):

        self.conf_info = configuration or {}
        self.resource_set = MemResourceSetDB()
        self.rpt = {}
        self.baseurl = baseurl
        if not self.baseurl.endswith("/"):
            self.baseurl += "/"
        self.session = Session()
        self.permit = Permission()
        self.permission_requests = PermissionRequests()
        self.map_rsid_id = {}
        self.map_id_rsid = {}
        self.map_user_id = {}
        self.eid2rpt = {}
        self.get_requester = get_requester

    def endpoints(self):
        for endp in self.endp:
            yield endp(None).name

    def services(self):
        for endp in self.endp:
            yield endp.etype

    # def rpt_endpoint_(self, requestor, client_id, **kwargs):
    # """
    # The endpoint URI at which the client asks the authorization server for
    # a RPT.
    #     """
    #     #res = self.client_authentication(authn)
    #     #if isinstance(res, Response):
    #     #    return res
    #
    #     # create RPT, just overwrites whatever was there before
    #     rpt = rndstr(32)
    #     self.rpt[rpt] = {"requestor": requestor, "client_id": client_id}
    #     self.session.set(rpt)
    #
    #     msg = RPTResponse(rpt=rpt)
    #     return Response(msg.to_json(), content="application/json")

    def resource_set_registration_endpoint_(self,
                                            entity,
                                            path,
                                            method,
                                            client_id,
                                            body="",
                                            if_match="",
                                            **kwargs):
        """
        The endpoint at which the resource server handles resource sets
        descriptions.

        :param entity: The entity that controls the resource set
        :param path:
        :param method: HTTP method
        :param body: The resource set registration message
        :paran client_id: Which client I'm talking to
        :param if_match: The HTTP If-Match header if any
        :param kwargs: possible other arguments
        :returns: A Response instance
        """

        # path should be /resource_set/{rsid} or /resource_set
        # Path may or may not start with '/'
        if path.startswith("/"):
            assert path[1:].startswith(RSR_PATH)
            rsid = path[PLEN + 1:]
        else:
            assert path.startswith(RSR_PATH)
            rsid = path[PLEN:]

        if rsid.startswith("/"):
            rsid = rsid[1:]

        _user = safe_name(entity, client_id)
        logger.debug("handling resource set belonging to '%s'" % _user)
        #  self.resource_set.set_collection(_user)
        if method == "POST":  # create
            args = {"oid": _user, "data": body}
            func = self.resource_set.create
        elif method == "PUT":  # update
            args = {
                "oid": _user,
                "data": body,
                "rsid": rsid,
                # "if_match": if_match
            }
            func = self.resource_set.update
        elif method == "GET":
            args = {"oid": _user}
            if not rsid:  # List
                func = self.resource_set.list
            else:  # Read
                func = self.resource_set.read
                args["rsid"] = rsid
        elif method == "DELETE":
            args = {"rsid": rsid, "oid": _user}
            func = self.resource_set.delete
        else:
            return BadRequest("Message error")

        logger.debug("operation: %s" % func)
        logger.debug("operation args: %s" % (args, ))
        try:
            body = func(**args)
        except MessageException as err:
            _err = ErrorResponse(error="invalid_request",
                                 error_description=str(err))
            response = BadRequest(_err.to_json(), content="application/json")
        except UnknownObject:
            _err = ErrorResponse(error="not_found")
            response = NotFound(_err.to_json(), content="application/json")
        else:
            response = None
            if isinstance(body, ErrorResponse):
                pass
            else:
                if func == self.resource_set.delete:
                    # As a side effect all permissions assigned that references
                    # this resource set should be deleted
                    self.permit.delete_permit_by_resource_id(entity, rsid)
                    response = NoContent()
                elif func == self.resource_set.create:
                    _etag = self.resource_set.etag[body["_id"]]
                    response = Created(body.to_json(),
                                       content="application/json",
                                       headers=[("ETag", _etag),
                                                ("Location", "/{}/{}".format(
                                                    RSR_PATH, body["_id"]))])
                elif func == self.resource_set.update:
                    _etag = self.resource_set.etag[body["_id"]]
                    response = NoContent(content="application/json",
                                         headers=[("ETag", _etag)])
                elif func == self.resource_set.list:
                    response = Response(json.dumps(body))

            if not response:
                response = Response(body.to_json(), content="application/json")

        return response

    def _collapse(self, items):
        referenced = {}
        ibrsid = {}
        for item in items:
            try:
                for rsid in item["subsets"]:
                    if rsid not in referenced:
                        referenced[rsid] = 1
                    else:
                        referenced[rsid] += 1
            except KeyError:
                pass

            _rsid = self.map_id_rsid[item["_id"]]
            if _rsid not in referenced:
                referenced[_rsid] = 0
            ibrsid[_rsid] = item

        res = []
        for key, val in list(referenced.items()):
            if val == 0:
                res.append(ibrsid[key])

        return res

    def resource_sets_by_user(self, entity, client_id, collapse=False):
        """
        :param entity: The entity for which resource set descriptions has been
            registered.
        :return: A list of ResourceSetDescriptions
        """
        res = []
        _user = safe_name(entity, client_id)
        try:
            rss = self.resource_set.list(_user)
        except KeyError:
            return []

        for _id in rss:
            try:
                res.append(self.resource_set.read(_user, _id))
            except Exception:
                raise

        if collapse:
            res = self._collapse(res)

        return res

    # def resource_set_tree_by_rsid(self, owner, rsid):
    #     rs = self.resource_set.read(owner, rsid)
    #     _name = rs["name"].split("/")[-1]
    #     try:
    #         _rsids = rs["subsets"]
    #     except KeyError:
    #         return rsid, _name
    #     else:
    #         res = {}
    #         for _rsid in _rsids:
    #             _rs = self.resource_set_tree_by_rsid(owner, _rsid)
    #             try:
    #                 res.update(_rs)
    #             except ValueError:
    #                 try:
    #                     res.append(_rs)
    #                 except AttributeError:
    #                     res = [_rs]
    #
    #         return {(rsid, _name): res}
    #
    # def resource_set_name(self, rsid):
    #     rs = self.resource_set.read(self.map_rsid_id[rsid])
    #     return rs["name"]

    def permits_by_user(self, owner):
        """
        :param owner: The owner of the resource
        :return: A dictionary with requestors as keys and permissions as values
        """
        return self.permit.get_permits(owner)

    def authz_session_info(self, token):
        pass

    def introspection_endpoint_(self, entity, **kwargs):
        """
        The endpoint URI at which the resource server introspects an RPT
        presented to it by a client.
        """

        request = kwargs["request"]
        logger.debug("requestor: %s, request: %s" % (entity, request))
        ir = IntrospectionRequest().from_json(request)
        owner = safe_name(entity, kwargs["client_id"])
        try:
            try:
                # requestor = self.rpt[ir["token"]]["requestor"]
                perms = self.permit.get_accepted(owner, ir["token"])
            except KeyError:
                response = BadRequest()
            else:
                if perms:
                    irep = IntrospectionResponse(active=True,
                                                 exp=perms[0]["exp"],
                                                 permissions=perms)
                    logger.debug("response: %s" % irep.to_json())
                    response = Response(irep.to_json(),
                                        content="application/json")
                else:
                    logger.info("No permissions bound to this RPT")
                    response = BadRequest()
        except ToOld:
            logger.info("RPT expired")
            irep = IntrospectionResponse(valid=False)
            response = Response(irep.to_json(), content="application/json")
        except KeyError:
            response = BadRequest()

        return response

    def permission_registration_endpoint_(self, entity, **kwargs):
        """
        The endpoint URI at which the resource server registers a
        client-requested permission with the authorization server.
        This is a proposed permission waiting for the user to accept it.
        """
        request = kwargs["request"]
        _ticket = rndstr(24)
        logging.debug("Registering permission request: %s" % request)
        resp = PermissionRegistrationResponse(ticket=_ticket)
        self.permission_requests.add_request(_ticket, request)

        return Created(resp.to_json(), content="application/json")

    def requesting_party_claims_endpoint(self, request="", **kwargs):
        """
        The endpoint at which the resource server gathers the consent of
        the end-user resource owner or the client gathers the consent of the
        end-user requesting party, if the "authorization_code" grant type is
        used.
        """
        pass

    def dynamic_client_endpoint(self, request="", **kwargs):
        pass

    def token_endpoint(self, request="", **kwargs):
        pass

    def authorization_endpoint(self, request="", **kwargs):
        pass

    @staticmethod
    def token_scope_check(areq, info):
        """
        verifies that the scope that is demanded for the access token is
        one that I'm comfortable with.

        :param areq: AccessTokenRequest
        :param info: What's in the session db
        :return: None if OK otherwise and error response.
        """
        try:
            assert areq["scope"] in info["scope"]
        except AssertionError:
            logger.error("Not the same scope as for the AuthzRequest")
            err = TokenErrorResponse(error="invalid_scope")
            return Response(err.to_json(), content="application/json")

        try:
            assert areq["scope"] in list(UMA_SCOPE.values())
        except AssertionError:
            logger.error("Asked for scope which I don't deal with")
            err = TokenErrorResponse(error="invalid_scope")
            return Response(err.to_json(), content="application/json")

        return None

    def create_uma_providerinfo(self, pcr_class=ProviderConfiguration):
        kwargs = dict([(k, v) for k, v in list(self.conf_info.items())
                       if k in pcr_class.c_param])
        _response = pcr_class(**kwargs)

        for endp in UmaAS.endp:
            _response.update(endpoint_ava(endp, self.baseurl))

        logger.debug("provider_info_response: %s" % (_response.to_dict(), ))
        return _response

    # noinspection PyUnusedLocal
    def providerinfo_endpoint_(self, handle="", **kwargs):
        logger.debug("@providerinfo_endpoint")
        try:
            _response = self.create_uma_providerinfo()

            headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")]
            # if handle:
            #     (key, timestamp) = handle
            #     if key.startswith(STR) and key.endswith(STR):
            #         cookie = self.cookie_func(key, self.cookie_name, "pinfo",
            #                                   self.sso_ttl)
            #         headers.append(cookie)

            resp = Response(_response.to_json(),
                            content="application/json",
                            headers=headers)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.error(message)
            resp = Response(message, content="html/text")

        return resp

    def get_subsets(self, owner, requestor, scopes):
        res = {}
        try:
            permits = self.permit.get_permit_by_requestor(owner, requestor)
        except KeyError:
            return res

        for permit, (_scopes, time_stamp) in list(permits.items()):
            _scs = []
            for scope in scopes:
                try:
                    assert scope in _scopes
                except AssertionError:
                    pass
                else:
                    _scs.append(scope)
            if _scs:
                res[permit] = _scs
        return res

    def register_permission(self, owner, rpt, rsid, scopes):
        now = utc_time_sans_frac()
        perm = AuthzDescription(resource_set_id=rsid,
                                scopes=scopes,
                                exp=now + self.session.lifetime,
                                iat=now)

        self.permit.set_accepted(owner, rpt, perm)

    def rpt_endpoint_(self, entity, client_id, **kwargs):
        """
        Registers an Authorization Description

        :param entity: Who's on the other side
        :param client_id: The UMA client
        :return: A Response instance
        """

        adr = AuthorizationDataRequest().from_json(kwargs["request"])

        # Get request permission that the resource server has registered
        try:
            prr_list = self.permission_requests.get_request(adr["ticket"])
        except KeyError:
            errmsg = ErrorResponse(error="invalid_ticket")
            return BadRequest(errmsg.to_json(), content="application/json")

        self.permission_requests.del_request(adr["ticket"])
        try:
            _rpt = adr["rpt"]
        except KeyError:
            _rpt = rndstr(32)

        for prr in prr_list:
            _rsid = prr["resource_set_id"]

            # Verify that the scopes are defined for the resource set
            owner = self.resource_set.rsid2oid[_rsid]
            rsd = self.resource_set.read(owner, _rsid)
            for scope in prr["scopes"]:
                try:
                    assert scope in rsd["scopes"]
                except AssertionError:
                    errmsg = ErrorResponse(
                        error="not_authorized",
                        error_description="Undefined scopes")
                    return BadRequest(errmsg.to_json(),
                                      content="application/json")

            # Is there any permissions registered by the owner, if so verify
            # that it allows what is requested. Return what is allowed !

            try:
                allow_scopes, timestamp = self.permit.get_permit(
                    owner, entity, _rsid)
            except KeyError:  #
                errmsg = ErrorResponse(error="not_authorized",
                                       error_description="No permission given")
                return BadRequest(errmsg.to_json(), content="application/json")
            else:
                _scopes = []
                for scope in prr["scopes"]:
                    try:
                        assert scope in allow_scopes
                    except AssertionError:
                        pass
                    else:
                        _scopes.append(scope)

                # bind _requester to specific RPT for this user
                try:
                    self.eid2rpt[owner][entity] = _rpt
                except KeyError:
                    self.eid2rpt[owner] = {entity: _rpt}

                self.register_permission(owner, _rpt, _rsid, _scopes)

        rsp = AuthorizationDataResponse(rpt=_rpt)

        return Response(rsp.to_json())

    def name2id(self, owner, requestor, rsid):
        _user = safe_name(owner, requestor)
        obj = self.resource_set.read(_user, rsid)
        return obj["_id"]

    def remove_permission(self, owner, requestor, resource_name):
        """
        :param owner: The resource owner
        :param requestor: The SP entity ID
        :param resource_name: The name of the resource set
        """
        _id = self.name2id(owner, requestor, resource_name)

        try:
            self.permit.delete_permit(owner, requestor, _id)
        except KeyError:
            pass

        try:
            _user = "******" % (owner, requestor)
            rm_rpt = self.permit.rm_accepted(_user, _id)
        except KeyError:
            pass
        else:
            for _rpt in rm_rpt:
                # immediate expiration
                self.session.update(_rpt, expires_at=0)

    def store_permission(self, user, requestor, rsids):
        """
        :param user: The resource owner
        :param requestor: The requestor ID
        :param rsids: dictionary with Resource set IDs as keys and scopes
            as values
        """

        logger.info("store: (%s, %s, %s)" % (user, requestor, rsids))

        present = self.permit.get_rsid_permits(user, requestor)
        _new = [k for k in list(rsids.keys()) if k not in present]
        _user = safe_name(user, requestor)
        for rsid in _new:
            scopes = rsids[rsid]
            if scopes is None:
                rs = self.resource_set.read(_user, rsid)
                scopes = rs["scopes"]
            self.permit.set_permit(user, requestor, rsid, scopes)

        _rem = [k for k in present if k not in rsids]
        for rsid in _rem:
            self.permit.delete_permit(user, requestor, rsid)

    def read_permission(self, user, requestor, rsid):
        return self.permit.get_permit(user, requestor, rsid)

    def rec_rm_permission(self, user, requestor, rsid):
        """
        If the resource set is a complex set, remove all subset permissions
        :param user: The owner of the resource
        :param requestor: Who the permission is applying to
        :param rsid: The resource set name
        """
        _user = safe_name(user, requestor)
        rs = self.resource_set.read(_user, rsid)
        if "subsets" in rs:
            for ss in rs["subsets"]:
                self.rec_rm_permission(user, requestor, ss)
        try:
            self.permit.delete_permit(user, requestor, rsid)
        except KeyError:
            pass

    def rm_permission(self, user, requestor, rsid):
        """
        If the resource set is a complex set, remove all subset permissions
        :param user: The owner of the resource
        :param requestor: Who the permission is applying to
        :param rsid: The resource set name
        """
        logger.info("remove: (%s, %s, %s)" % (user, requestor, rsid))
        self.rec_rm_permission(user, requestor, rsid)
        return True

    def rsid_permits(self, user, requestor):
        return self.permit.get_rsid_permits(user, requestor)