sig-rnd-io-testuser opened a new issue, #43257:
URL: https://github.com/apache/superset/issues/43257

   ### Bug description
   
   Superset 6.1.0 added `@has_access_api` decorator to the `post()` and `put()` 
methods of `DashboardFilterStateRestApi` (in 
`superset/dashboards/filter_state/api.py`). This causes **401 "Access is 
Denied"** for all users, **including admin**, when calling `POST 
/api/v1/dashboard/{id}/filter_state` or `PUT 
/api/v1/dashboard/{id}/filter_state/{key}`.
   
   GET and DELETE on the same endpoint work fine because they do not have 
`@has_access_api`.
   
   ### Root cause
   
   The decorator ordering on POST/PUT is:
   
   ```python
   @api
   @has_access_api          # runs BEFORE @protect()
   @expose("/<int:pk>/filter_state", methods=("POST",))
   @protect()               # never reached
   @safe
   @event_logger.log_this_with_context(...)
   def post(self, pk: int) -> Response:
   ```
   
   `@has_access_api` checks `current_user` via Flask-Login. However, 
`@protect()` (which validates JWT Bearer tokens and sets `current_user`) runs 
**after** `@has_access_api` in the decorator chain. The session cookie from the 
CSRF token endpoint only contains `{"csrf_token": "..."}` — no user identity. 
So `current_user` is anonymous when `@has_access_api` evaluates, and it returns 
`response_401()`.
   
   This was not an issue in Superset 4.1.1 because `@has_access_api` was not 
present on these methods — only `@protect()` was used.
   
   ### Comparison: 4.1.1 vs 6.1.0
   
   | Version | POST/PUT decorators | Result |
   |---------|-------------------|--------|
   | 4.1.1 | `@expose`, `@protect()`, `@safe`, `@event_logger` | Works |
   | 6.1.0 | `@api`, `@has_access_api`, `@expose`, `@protect()`, `@safe`, 
`@event_logger` | 401 |
   
   ### How to reproduce
   
   1. Deploy Superset 6.1.0
   2. Login via API:
      ```bash
      curl -s -X POST http://localhost:8088/api/v1/security/login \
        -H "Content-Type: application/json" \
        -d 
'{"username":"admin","password":"admin","provider":"db","refresh":"true"}'
      ```
   3. Get CSRF token:
      ```bash
      curl -sv http://localhost:8088/api/v1/security/csrf_token/ \
        -H "Authorization: Bearer <access_token>"
      ```
   4. POST to filter_state:
      ```bash
      curl -X POST "http://localhost:8088/api/v1/dashboard/1/filter_state"; \
        -H "Authorization: Bearer <access_token>" \
        -H "X-CSRFToken: <csrf_token>" \
        -H "Cookie: <session_cookie>" \
        -H "Content-Type: application/json" \
        -d '{"value":"{\"test\":\"test\"}"}'
      ```
   5. Response: `{"message":"Access is Denied","severity":"danger"}` with HTTP 
401
   
   6. Compare with GET (which does NOT have `@has_access_api`):
      ```bash
      curl "http://localhost:8088/api/v1/dashboard/1/filter_state/any_key"; \
        -H "Authorization: Bearer <access_token>" \
        -H "Cookie: <session_cookie>"
      ```
      Response: `{"message":"Not found"}` with HTTP 404 — auth passes, key just 
doesn't exist.
   
   ### Expected results
   
   POST and PUT to `/api/v1/dashboard/{id}/filter_state` should succeed with 
valid JWT + CSRF tokens (as they did in 4.1.1).
   
   ### Actual results
   
   401 "Access is Denied" for all users including admin.
   
   ### Suggested fix
   
   Either:
   1. **Remove `@has_access_api`** from `post()` and `put()` in 
`DashboardFilterStateRestApi`, reverting to the 4.1.1 decorator chain where 
`@protect()` handles authentication.
   2. **Or reorder** so `@protect()` runs before `@has_access_api`, ensuring 
`current_user` is set from the JWT token before the permission check.
   
   ### Superset version
   
   6.1.0
   
   ### Python version
   
   3.12
   
   ### Node version
   
   22.x
   
   ### Browser
   
   Not applicable (API-only issue)
   
   ### Additional context
   
   This also likely affects `ExploreFormDataRestApi` and 
`ExplorePermalinkRestApi` which have the same decorator pattern in 6.1.0.
   
   Workaround: patch the Docker image to comment out `@has_access_api` via sed.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to