Flask-AppBuilder icon indicating copy to clipboard operation
Flask-AppBuilder copied to clipboard

When creating an API endpoint, and trying to access it with a user issued token in the request Header, it's saying access denied for the newly created permission on the api class denied.

Open shenglong opened this issue 2 years ago • 1 comments

If you'd like to report a bug in Flask-Appbuilder, fill out the template below. Provide any extra information that may be useful

Responsible disclosure: We want to keep Flask-AppBuilder safe for everyone. If you've discovered a security vulnerability please report to [email protected].

Environment

Flask-Appbuilder version: 4.1.4

pip freeze output: aiocache==0.11.1 aiofiles==0.8.0 aiohttp==3.8.1 aiohttp-swagger==1.0.16 aiosignal==1.2.0 ansible==3.0.0 ansible-base==2.10.6 ansible-compat==2.2.1 ansible-core==2.13.4 ansible-lint==6.8.0 ansible-runner==2.3.1 apispec==3.3.2 appdirs==1.4.4 astroid==2.5 async-lru==1.0.3 async-timeout==4.0.2 attrs==22.1.0 Babel==2.10.3 bcrypt==3.2.0 black==23.1.0 bmc-helix-inventory==0.10.0 bracex==2.3.post1 cached-property==1.5.2 certifi==2020.12.5 cffi==1.14.5 chardet==4.0.0 charset-normalizer==2.1.0 cisco-gnmi==1.0.15 ciscoconfparse==1.6.40 click==8.1.3 colorama==0.4.5 commonmark==0.9.1 cryptography==3.4.6 defusedxml==0.7.1 dill==0.3.5.1 distlib==0.3.1 distro==1.7.0 dnspython==2.2.1 docker==4.4.4 docutils==0.19 email-validator==1.3.0 exceptiongroup==1.1.0 f5-icontrol-rest==1.3.13 f5-sdk==3.0.21 fastapi==0.68.2 filelock==3.0.12 Flask==2.2.2 Flask-AppBuilder==4.1.4 Flask-Babel==2.0.0 Flask-JWT-Extended==4.4.4 Flask-Login==0.6.2 flask-mongoengine==1.0.0 Flask-SQLAlchemy==2.5.1 Flask-WTF==1.0.1 frozenlist==1.3.0 future==0.18.2 genie==22.7 genie.libs.clean==22.7 genie.libs.conf==22.7 genie.libs.filetransferutils==22.7 genie.libs.health==22.7 genie.libs.ops==22.7 genie.libs.parser==22.7 genie.libs.sdk==22.7 gitdb==4.0.9 GitPython==3.1.18 greenlet==1.1.3.post0 grpcio==1.47.0 idna==2.10 importlib-metadata==5.0.0 importlib-resources==5.10.0 iniconfig==1.1.1 invoke==1.5.0 IPy==1.1 isodate==0.6.0 isort==5.7.0 itsdangerous==2.1.2 Jinja2==3.1.2 jsonify==0.5 jsonpickle==2.2.0 jsonschema==4.16.0 junit-xml==1.9 junos-eznc==2.6.4 lazy-object-proxy==1.5.2 lockfile==0.12.2 loguru==0.6.0 lxml==4.6.3 Markdown==3.4.1 MarkupSafe==2.1.1 marshmallow==3.18.0 marshmallow-enum==1.5.1 marshmallow-sqlalchemy==0.26.1 mccabe==0.6.1 mongo==0.2.0 mongoengine==0.24.2 multidict==6.0.2 mypy-extensions==0.4.3 ncclient==0.6.13 netaddr==0.8.0 netmiko==3.4.0 ntc-templates==3.0.0 numpy==1.21.3 packaging==23.0 pandas==1.3.4 paramiko==2.7.2 passlib==1.7.4 pathspec==0.10.1 pexpect==4.8.0 pii==0.0.1 pkgutil_resolve_name==1.3.10 platformdirs==2.5.2 pluggy==0.13.1 prettytable==3.3.0 prison==0.2.1 protobuf==3.20.1 psutil==5.9.1 ptyprocess==0.7.0 py==1.10.0 pyasn1==0.4.8 pyasn1-modules==0.2.8 pyats==22.7.1 pyats.aereport==22.7 pyats.aetest==22.7 pyats.async==22.7 pyats.connections==22.7 pyats.datastructures==22.7 pyats.easypy==22.7 pyats.kleenex==22.7 pyats.log==22.7 pyats.reporter==22.7 pyats.results==22.7 pyats.tcl==22.7 pyats.topology==22.7 pyats.utils==22.7 pycparser==2.20 pydantic==1.9.2 pyeapi==0.8.4 pyftpdlib==1.5.6 Pygments==2.13.0 PyJWT==2.5.0 pylint==2.7.0 pymongo==4.2.0 PyNaCl==1.4.0 pyntc==0.20.1 pynxos==0.0.5 pyparsing==3.0.9 pyrsistent==0.18.1 pyserial==3.5 pytest==7.2.1 python-daemon==2.3.2 python-dateutil==2.8.2 python-dotenv==0.10.5 python-engineio==3.14.2 python-ldap==3.4.3 python-socketio==4.6.1 pytz==2022.5 PyYAML==5.4.1 regex==2020.11.13 requests==2.25.1 requests-file==1.5.1 requests-toolbelt==0.9.1 resolvelib==0.8.1 rich==12.6.0 ruamel.yaml==0.17.21 ruamel.yaml.clib==0.2.6 scp==0.13.6 six==1.16.0 smmap==5.0.0 SQLAlchemy==1.4.42 SQLAlchemy-Utils==0.38.3 starlette==0.14.2 style==1.1.0 subprocess-tee==0.3.5 tenacity==8.0.1 textfsm==1.1.3 tftpy==0.8.0 toml==0.10.2 tomli==2.0.1 tox==3.22.0 tqdm==4.64.0 transitions==0.8.11 typed-ast==1.4.2 typing-extensions==3.10.0.2 unicon==22.7 unicon.plugins==22.7 update==0.0.1 urllib3==1.26.3 virtualenv==20.4.2 wcmatch==8.4.1 wcwidth==0.2.5 websocket-client==0.57.0 Werkzeug==2.2.2 wrapt==1.12.1 WTForms==3.0.1 xmltodict==0.13.0 yamllint==1.27.1 yamlordereddictloader==0.4.0 yang.connector==22.7 yarl==1.7.2 zeep==4.0.0 zipp==3.9.0

Describe the expected results

Tell us what should happen.

Sending a request like this:

curl 'http://localhost:8080/secured/security' -H "Authorization: Bearer $TOKEN"

TOKEN Has the issued token returned from an user in the mongodb database using create_access_token from flask_jwt_extended.

With the api endpoint written like this:

from flask_appbuilder.security.decorators import protect, has_access_api
from flask_appbuilder.api import BaseApi, expose
from flask import request


class SecuredApi(BaseApi):
    """Greeting API Test."""

    route_base = "/secured"
    @has_access_api
    @expose("/security")
    @protect()
    def security_test(self):
        return self.response(200, message="This is private")

It should return a response with the message "This is private".

Describe the actual results

Tell us what happens instead.

But instead returns this message:

{
    "message": "Access is Denied",
    "severity": "danger"
}

In the flask app output log will say this:

2023-03-07 14:59:29,400:WARNING:flask_appbuilder.security.decorators:Access is Denied for: can_security_test on: SecuredApi
2023-03-07 14:59:29,403:INFO:werkzeug:127.0.0.1 - - [07/Mar/2023 14:59:29] "GET /secured/security HTTP/1.1" 401 -

Steps to reproduce

Write and expose the same api endpoint code, run the flask app, and send the get method from the curl line.

When checking the permissions on the view from SecuredApi, it does have can_security_test permissions, assigned to the role of the user.

shenglong avatar Mar 07 '23 14:03 shenglong

Hi,

Use the @protect() decorator instead, https://flask-appbuilder.readthedocs.io/en/latest/rest_api.html#security

dpgaspar avatar Mar 11 '23 13:03 dpgaspar