This is an automated email from the ASF dual-hosted git repository.

vatsrahul1001 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 6e749f72c2e Document that plugin FastAPI apps are not authenticated by 
Airflow (#72655)
6e749f72c2e is described below

commit 6e749f72c2e2689d4f5dfe4ce8a293fa131ef37b
Author: Jarek Potiuk <[email protected]>
AuthorDate: Fri Sep 11 11:30:50 2026 +0200

    Document that plugin FastAPI apps are not authenticated by Airflow (#72655)
    
    * Document that plugin FastAPI apps are not authenticated by Airflow
    
    Airflow authenticates the core API with a router-level dependency. A plugin 
app is
    attached with app.mount(), and a Starlette mount has its own route table 
and inherits
    none of the parent's dependencies, so that dependency never reaches a 
plugin's routes;
    no middleware in the API server authenticates them either.
    
    The consequence is that every route a plugin exposes is reachable by 
anonymous callers
    unless the plugin authenticates it itself -- and the documented example is 
exactly that
    shape: a plain route, with no authentication and no note saying one is 
needed. A
    deployment that follows the docs ships plugin endpoints pre-auth without 
being told.
    
    Enforcing authentication in core was the alternative and was rejected: it 
breaks plugins
    that legitimately serve anonymous callers, and access control for a 
plugin's own routes
    belongs to the plugin author rather than to core.
    
    So document the gap where it is read. The plugins page now states plainly 
that Airflow
    does not authenticate plugin apps, shows GetUserDep on a route, shows the
    application-level form that keeps a later-added route from silently shipping
    unauthenticated, and separates authentication from authorization -- 
including team
    scoping, which a plugin must check for itself.
    
    Documentation only; no behaviour change.
    
    * Add Starlette to the docs spelling wordlist
    
    The plugin authentication warning names Starlette when explaining why a
    mounted app inherits none of the parent's dependencies, and the docs
    spellcheck has no entry for it.
    
    Generated-by: Claude Code (Opus 5)
    Claude-Session: https://claude.ai/code/session_01XS3bodTDYYGrPmorhtLsjP
---
 .../docs/administration-and-deployment/plugins.rst | 47 ++++++++++++++++++++++
 docs/spelling_wordlist.txt                         |  1 +
 2 files changed, 48 insertions(+)

diff --git a/airflow-core/docs/administration-and-deployment/plugins.rst 
b/airflow-core/docs/administration-and-deployment/plugins.rst
index a4b699fb163..7784df244a6 100644
--- a/airflow-core/docs/administration-and-deployment/plugins.rst
+++ b/airflow-core/docs/administration-and-deployment/plugins.rst
@@ -229,6 +229,53 @@ definitions in Airflow.
     app_with_metadata = {"app": app, "url_prefix": "/some_prefix", "name": 
"Name of the App"}
 
 
+.. warning::
+
+    **Airflow does not authenticate plugin FastAPI apps. Authenticating them 
is the
+    plugin author's responsibility.**
+
+    Airflow authenticates the core API with a router-level dependency. A 
plugin app is
+    attached with ``app.mount()``, and a Starlette mount has its own route 
table and
+    inherits none of the parent's dependencies, so that dependency never 
reaches a
+    plugin's routes. No middleware in the API server authenticates them either.
+
+    Every route a plugin exposes is therefore reachable by **anonymous 
callers** unless
+    the plugin authenticates it itself. The minimal ``app`` above is a 
structural
+    illustration, not a template to deploy as-is.
+
+    Depend on ``GetUserDep`` to require a caller Airflow has authenticated:
+
+    .. code-block:: python
+
+        from fastapi import FastAPI
+
+        from airflow.api_fastapi.core_api.security import GetUserDep
+
+        app = FastAPI()
+
+
+        @app.get("/dashboard")
+        def dashboard(user: GetUserDep):
+            return {"user": user.get_name()}
+
+    Prefer attaching the dependency once, at the application or router level, 
so that a
+    route added later does not silently ship unauthenticated:
+
+    .. code-block:: python
+
+        from fastapi import Depends, FastAPI
+
+        from airflow.api_fastapi.core_api.security import get_user
+
+        app = FastAPI(dependencies=[Depends(get_user)])
+
+    Authentication is not authorization. ``GetUserDep`` establishes *who* is 
calling;
+    whether that user may perform a given action remains the plugin's own 
decision. This
+    applies to team scoping too — in a multi-team deployment, a plugin that 
does not check
+    the caller's team serves every team's users the same data.
+
+.. code-block:: python
+
     # Creating a FastAPI middleware that will operates on all the server api 
requests.
     middleware_with_metadata = {
         "middleware": TrustedHostMiddleware,
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 140ca2e93aa..74bdc1864ed 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1632,6 +1632,7 @@ Stackdriver
 stackdriver
 stacklevel
 stacktrace
+Starlette
 starttls
 stateful
 StatefulSet

Reply via email to