Skip to content

DatabaseRestApi.get_list and DatasetRestApi.get_list return count:0 for JWT-authenticated Admin users in 6.0.1 #39834

@gkhnelbstn

Description

@gkhnelbstn

Bug description

DatabaseRestApi.get_list and DatasetRestApi.get_list return count:0 for JWT-authenticated Admin users in 6.0.1

Labels: bug, needs-triage


Bug description

When authenticating via the REST API using a JWT Bearer token (POST /api/v1/security/login), the /api/v1/database/ and /api/v1/dataset/ list endpoints always return count: 0 and an empty result array — even for users with the Admin role who have all_database_access and all_datasource_access permissions, and even when the objects exist in the metadata database.

The same user can see all objects correctly in the Superset UI (browser session). The issue is specific to JWT Bearer token authentication used by programmatic clients (MCP servers, provisioning scripts, FastAPI backends, etc.).

Steps to reproduce

  1. Start Superset 6.0.1 with default config (WTF_CSRF_ENABLED = True)
  2. Create at least one database connection and one dataset via the UI
  3. Authenticate via the REST API:
import requests

resp = requests.post(
    "http://localhost:8088/api/v1/security/login",
    json={"username": "admin", "password": "admin", "provider": "db", "refresh": True}
)
token = resp.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
  1. Call the database list endpoint:
r = requests.get("http://localhost:8088/api/v1/database/", headers=headers)
print(r.status_code, r.json()["count"])
# Output: 200  0
  1. Call the dataset list endpoint:
r = requests.get("http://localhost:8088/api/v1/dataset/", headers=headers)
print(r.status_code, r.json()["count"])
# Output: 200  0

Both return 200 OK with count: 0 and result: [], despite objects existing in the DB.

Root cause (identified)

DatabaseFilter.apply() in superset/databases/filters.py calls security_manager.can_access_all_databases(), which internally calls self.can_access("all_database_access", "all_database_access"), which reads g.user.

In Superset 6.0.1, when a request is authenticated via JWT Bearer token, flask-jwt-extended's user_lookup_loader sets g.user correctly — but only after the FAB before_request hook runs, which resets g.user to current_user (the Flask-Login anonymous proxy). As a result, g.user.is_anonymous returns True inside DatabaseFilter.apply(), causing can_access_all_databases() to return False.

When can_access_all_databases() returns False, the filter falls through to:

return query.filter(
    or_(
        self.model.perm.in_(database_perms),
        self.model.database_name.in_(database_names),
    )
)

However, the perm column was removed from the dbs table in Superset 6.x. This causes a silent failure that results in an empty result set rather than raising an exception.

Superset logs showing the silent failure:

ERROR:superset.views.error_handling:'encrypted_extra'
KeyError: 'encrypted_extra'

This secondary error occurs on GET /api/v1/database/_info because the extra JSON field in older dbs rows is missing the encrypted_extra key expected by 6.0.1.

Workaround

Add a before_request hook in superset_config.py that explicitly sets g.user from the JWT token before FAB's hook can reset it:

def FLASK_APP_MUTATOR(app):
    from flask import g, request

    @app.before_request
    def _set_user_from_jwt():
        auth_header = request.headers.get("Authorization", "")
        if auth_header.startswith("Bearer "):
            token = auth_header.split(" ", 1)[1]
            try:
                from flask_jwt_extended import decode_token
                decoded = decode_token(token)
                identity = decoded.get("sub")
                if identity:
                    from superset import security_manager
                    user = security_manager.load_user(identity)
                    if user and user.is_active:
                        g.user = user
            except Exception:
                pass

After applying this workaround, both endpoints return the correct count and result.

Expected behavior

GET /api/v1/database/ and GET /api/v1/dataset/ should return all objects visible to the authenticated user when using JWT Bearer token authentication, consistent with browser session behavior.

Actual behavior

Both endpoints return count: 0 and result: [] for JWT-authenticated requests, regardless of the user's role or permissions.

Superset version

6.0.1

Python version

3.10

Browser

N/A (API client)

Additional context

  • The dbs table perm column referenced in DatabaseFilter was removed in 6.x. The filter's fallback branch silently fails when this column is missing.
  • A secondary issue: dbs rows created before 6.0.1 may be missing the encrypted_extra key in the extra JSON field, causing KeyError: 'encrypted_extra' on GET /api/v1/database/_info. Fix:
    UPDATE dbs
    SET extra = (extra::jsonb || '{"encrypted_extra": ""}')::text
    WHERE extra NOT LIKE '%encrypted_extra%';
  • Both issues compound to make the REST API completely non-functional for programmatic clients (MCP servers, provisioning scripts, FastAPI backends) that use JWT auth.

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Screenshots/recordings

No response

Superset version

master / latest-dev

Python version

3.10

Node version

I don't know

Browser

Not applicable

Additional context

No response

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Metadata

Metadata

Assignees

No one assigned

    Labels

    #bug:regressionBugs that are identified as regessionsapiRelated to the REST APIauthentication:fabRelated to authentication with FAB

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions