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

vincbeck 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 d596f4d4a98 Add documentation about Airflow API authentication (#48417)
d596f4d4a98 is described below

commit d596f4d4a982eb5ce9fb8d6bd5c007162c945f99
Author: Vincent <[email protected]>
AuthorDate: Thu Mar 27 13:46:09 2025 -0400

    Add documentation about Airflow API authentication (#48417)
---
 .../docs/core-concepts/auth-manager/index.rst      | 43 +++++++++--------
 airflow-core/docs/index.rst                        |  2 +-
 airflow-core/docs/security/api.rst                 | 56 +++++++++++++++++-----
 airflow-core/docs/stable-rest-api-ref.rst          |  4 +-
 .../api_fastapi/core_api/openapi/v1-generated.yaml | 10 +++-
 .../src/airflow/api_fastapi/core_api/security.py   | 12 ++++-
 .../auth/managers/test_base_auth_manager.py        | 20 ++++++++
 docs/conf.py                                       |  1 -
 8 files changed, 112 insertions(+), 36 deletions(-)

diff --git a/airflow-core/docs/core-concepts/auth-manager/index.rst 
b/airflow-core/docs/core-concepts/auth-manager/index.rst
index bd13d89ace8..98bd9360281 100644
--- a/airflow-core/docs/core-concepts/auth-manager/index.rst
+++ b/airflow-core/docs/core-concepts/auth-manager/index.rst
@@ -98,24 +98,6 @@ Authentication related BaseAuthManager methods
 * ``get_user``: Return the signed-in user.
 * ``get_url_login``: Return the URL the user is redirected to for signing in.
 
-JWT token management by auth managers
--------------------------------------
-The auth manager is responsible of creating the JWT token and pass it to 
Airflow UI. The protocol to exchange the JWT
-token between the auth manager and Airflow UI is using cookies. The auth 
manager needs to save the JWT token in a
-cookie named ``_token`` before redirecting to the Airflow UI. The Airflow UI 
will then read the cookie, save it and
-delete the cookie.
-
-.. code-block:: python
-
-    from airflow.api_fastapi.auth.managers.base_auth_manager import 
COOKIE_NAME_JWT_TOKEN
-
-    response = RedirectResponse(url="/")
-    response.set_cookie(COOKIE_NAME_JWT_TOKEN, token, secure=True)
-    return response
-
-.. note::
-    Do not set the cookie parameter ``httponly`` to ``True``. Airflow UI needs 
to access the JWT token from the cookie.
-
 Authorization related BaseAuthManager methods
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -147,6 +129,29 @@ These authorization methods are:
 * ``is_authorized_view``: Return whether the user is authorized to access a 
specific view in Airflow. The view is specified through ``access_view`` (e.g. 
``AccessView.CLUSTER_ACTIVITY``).
 * ``is_authorized_custom_view``: Return whether the user is authorized to 
access a specific view not defined in Airflow. This view can be provided by the 
auth manager itself or a plugin defined by the user.
 
+JWT token management by auth managers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The auth manager is responsible for creating the JWT token needed to interact 
with Airflow public API.
+To achieve this, the auth manager **must** provide an endpoint to create this 
JWT token. This endpoint must be
+available at ``POST /auth/token``
+
+The auth manager is also responsible of passing the JWT token to Airflow UI. 
The protocol to exchange the JWT
+token between the auth manager and Airflow UI is using cookies. The auth 
manager needs to save the JWT token in a
+cookie named ``_token`` before redirecting to the Airflow UI. The Airflow UI 
will then read the cookie, save it and
+delete the cookie.
+
+.. code-block:: python
+
+    from airflow.api_fastapi.auth.managers.base_auth_manager import 
COOKIE_NAME_JWT_TOKEN
+
+    response = RedirectResponse(url="/")
+    response.set_cookie(COOKIE_NAME_JWT_TOKEN, token, secure=True)
+    return response
+
+.. note::
+    Do not set the cookie parameter ``httponly`` to ``True``. Airflow UI needs 
to access the JWT token from the cookie.
+
+
 Optional methods recommended to override for optimization
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -199,7 +204,7 @@ Such additional endpoints can be used to manage resources 
such as users, groups,
 Endpoints defined by ``get_fastapi_app`` are mounted in ``/auth``.
 
 Next Steps
-^^^^^^^^^^
+----------
 
 Once you have created a new auth manager class implementing the 
:class:`~airflow.api_fastapi.auth.managers.base_auth_manager.BaseAuthManager` 
interface, you can configure Airflow to use it by setting the 
``core.auth_manager`` configuration value to the module path of your auth 
manager:
 
diff --git a/airflow-core/docs/index.rst b/airflow-core/docs/index.rst
index 78c33348d3f..c25a724792b 100644
--- a/airflow-core/docs/index.rst
+++ b/airflow-core/docs/index.rst
@@ -176,7 +176,7 @@ so coding will always be required.
     Operators and hooks <operators-and-hooks-ref>
     CLI <cli-and-env-variables-ref>
     Templates <templates-ref>
-    Stable REST API <stable-rest-api-ref>
+    Airflow public API <stable-rest-api-ref>
     Configurations <configurations-ref>
     Extra packages <extra-packages-ref>
 
diff --git a/airflow-core/docs/security/api.rst 
b/airflow-core/docs/security/api.rst
index 0bae61d7363..1ed568f69b3 100644
--- a/airflow-core/docs/security/api.rst
+++ b/airflow-core/docs/security/api.rst
@@ -15,20 +15,54 @@
     specific language governing permissions and limitations
     under the License.
 
-API
-===
+Public API
+==========
 
-API Authentication
-------------------
+Airflow public API authentication
+---------------------------------
 
-The API authentication is handled by the auth manager.
-For more information about API authentication, please refer to the auth 
manager documentation used by your environment.
-By default Airflow uses the ``Simple Auth Manager``, if you did not specify 
any other auth manager.
-``Simple Auth Manager`` is a basic auth manager that persisted under Airflow 
core.
-It is not recommended to use it in production and currently aiming for 
development purposes.
+The Airflow public API uses JWT (JSON Web Token) for authenticating API 
requests.
+Each request made to the Airflow API must include a valid JWT token in the 
``Authorization`` header to verify the
+identity and permissions of the client.
 
-Please install ``apache-airflow-providers-fab`` to use the auth manager that 
is aimed for production.
-For that, please look at 
:doc:`apache-airflow-providers-fab:auth-manager/api-authentication`.
+Generate a JWT token
+^^^^^^^^^^^^^^^^^^^^
+
+To interact with the Airflow API, clients must first authenticate and obtain a 
JWT token.
+The token can be generated by making a ``POST`` request to the ``/auth/token`` 
endpoint, passing the necessary
+credentials (e.g., username and password). The ``/auth/token`` endpoint is 
provided by the auth manager, therefore,
+please read the documentation of the auth manager configured in your 
environment for more details.
+
+Example
+*******
+
+Request
+
+.. code-block:: bash
+
+    ENDPOINT_URL="http://localhost:8080/";
+    curl -X POST ${ENDPOINT_URL}/auth/token \
+      -H "Content-Type: application/json" \
+      -d '{
+        "username": "your-username",
+        "password": "your-password"
+      }'
+
+Response
+
+.. code-block:: json
+
+  {
+    "jwt_token": "<JWT-TOKEN>"
+  }
+
+Use the JWT token to call Airflow public API
+
+.. code-block:: bash
+
+    ENDPOINT_URL="http://localhost:8080/";
+    curl -X GET ${ENDPOINT_URL}/api/v2/dags \
+      -H "Authorization: Bearer <JWT-TOKEN>"
 
 Enabling CORS
 -------------
diff --git a/airflow-core/docs/stable-rest-api-ref.rst 
b/airflow-core/docs/stable-rest-api-ref.rst
index 673b88cc35b..0996dd69dc9 100644
--- a/airflow-core/docs/stable-rest-api-ref.rst
+++ b/airflow-core/docs/stable-rest-api-ref.rst
@@ -16,8 +16,8 @@
     specific language governing permissions and limitations
     under the License.
 
-REST API Reference
-==================
+Airflow public API reference
+============================
 
 It's a stub file. It will be converted automatically during the build process
 to the valid documentation by the Sphinx plugin. See: /docs/conf.py
diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-generated.yaml 
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
index 97f43ee8d9a..cb0b38960de 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
+++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
@@ -11782,7 +11782,15 @@ components:
   securitySchemes:
     OAuth2PasswordBearer:
       type: oauth2
+      description: To authenticate Airflow API requests, clients must include 
a JWT
+        (JSON Web Token) in the Authorization header of each request. This 
token is
+        used to verify the identity of the client and ensure that they have 
the appropriate
+        permissions to access the requested resources. You can use the 
endpoint ``POST
+        /auth/token`` in order to generate a JWT token. Upon successful 
authentication,
+        the server will issue a JWT token that contains the necessary 
information
+        (such as user identity and scope) to authenticate subsequent requests. 
To
+        learn more about Airflow public API authentication, please read 
https://airflow.apache.org/docs/apache-airflow/stable/security/api.html.
       flows:
         password:
           scopes: {}
-          tokenUrl: token
+          tokenUrl: /auth/token
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/security.py 
b/airflow-core/src/airflow/api_fastapi/core_api/security.py
index b10f7ac8549..0b5f51d2c81 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/security.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/security.py
@@ -50,7 +50,17 @@ if TYPE_CHECKING:
 
     from airflow.api_fastapi.auth.managers.base_auth_manager import 
BaseAuthManager, ResourceMethod
 
-oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+auth_description = (
+    "To authenticate Airflow API requests, clients must include a JWT (JSON 
Web Token) in "
+    "the Authorization header of each request. This token is used to verify 
the identity of "
+    "the client and ensure that they have the appropriate permissions to 
access the "
+    "requested resources. "
+    "You can use the endpoint ``POST /auth/token`` in order to generate a JWT 
token. "
+    "Upon successful authentication, the server will issue a JWT token that 
contains the necessary "
+    "information (such as user identity and scope) to authenticate subsequent 
requests. "
+    "To learn more about Airflow public API authentication, please read 
https://airflow.apache.org/docs/apache-airflow/stable/security/api.html.";
+)
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token", 
description=auth_description)
 
 
 async def get_user(token_str: Annotated[str, Depends(oauth2_scheme)]) -> 
BaseUser:
diff --git 
a/airflow-core/tests/unit/api_fastapi/auth/managers/test_base_auth_manager.py 
b/airflow-core/tests/unit/api_fastapi/auth/managers/test_base_auth_manager.py
index 741c4962f34..bd37351fd63 100644
--- 
a/airflow-core/tests/unit/api_fastapi/auth/managers/test_base_auth_manager.py
+++ 
b/airflow-core/tests/unit/api_fastapi/auth/managers/test_base_auth_manager.py
@@ -33,6 +33,8 @@ from 
airflow.api_fastapi.auth.managers.models.resource_details import (
 )
 from airflow.api_fastapi.auth.tokens import JWTGenerator, JWTValidator
 from airflow.api_fastapi.common.types import MenuItem
+from airflow.providers_manager import ProvidersManager
+from airflow.utils.module_loading import import_string
 
 if TYPE_CHECKING:
     from airflow.api_fastapi.auth.managers.base_auth_manager import 
ResourceMethod
@@ -366,3 +368,21 @@ class TestBaseAuthManager:
         session.execute.return_value = dags
         result = auth_manager.get_authorized_dag_ids(user=user, 
session=session)
         assert result == expected
+
+
+def test_auth_managers_have_create_token_endpoint(test_client):
+    auth_managers = ProvidersManager().auth_managers
+    
auth_managers.append("airflow.api_fastapi.auth.managers.simple.simple_auth_manager.SimpleAuthManager")
+
+    for auth_manager_module in auth_managers:
+        auth_manager_cls = import_string(auth_manager_module)
+        am = auth_manager_cls()
+        am.init()
+
+        response = test_client.post(
+            "/auth/token",
+            json={"username": "", "password": ""},
+        )
+        assert (
+            response.status_code not in [404, 405]
+        ), f"The auth manager {auth_manager_module} does not provide an 
endpoint to create a JWT token. This endpoint should be POST /auth/token"
diff --git a/docs/conf.py b/docs/conf.py
index 823b8027a9b..6b3fc7d54d6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -920,7 +920,6 @@ if PACKAGE_NAME == "apache-airflow":
             "spec": OPENAPI_FILE.as_posix(),
             "opts": {
                 "hide-hostname": True,
-                "no-auto-auth": True,
             },
         },
     ]

Reply via email to