This is an automated email from the ASF dual-hosted git repository.
potiuk 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 11f348694fc Fix SimpleAuthManager redirect to next URL after login
(#67483)
11f348694fc is described below
commit 11f348694fc3024b81888e29618c25091fa41f66
Author: Aditya Patel <[email protected]>
AuthorDate: Mon May 25 17:10:25 2026 -0400
Fix SimpleAuthManager redirect to next URL after login (#67483)
* Fix simple auth redirect to next URL
* Format simple auth redirect test
---
.../auth/managers/simple/routes/login.py | 6 +++++-
.../auth/managers/simple/routes/test_login.py | 22 ++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/routes/login.py
b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/routes/login.py
index fc5938a14cc..c659edb0e19 100644
--- a/airflow-core/src/airflow/api_fastapi/auth/managers/simple/routes/login.py
+++ b/airflow-core/src/airflow/api_fastapi/auth/managers/simple/routes/login.py
@@ -28,6 +28,7 @@ from airflow.api_fastapi.auth.managers.simple.utils import
parse_login_body
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.common.types import Mimetype
from airflow.api_fastapi.core_api.openapi.exceptions import
create_openapi_http_exception_doc
+from airflow.api_fastapi.core_api.security import is_safe_url
from airflow.configuration import conf
login_router = AirflowRouter(tags=["SimpleAuthManagerLogin"])
@@ -85,7 +86,10 @@ def create_token_all_admins() -> LoginResponse:
)
def login_all_admins(request: Request) -> RedirectResponse:
"""Login the user with no credentials."""
- response = RedirectResponse(url=conf.get("api", "base_url", fallback="/"))
+ fallback_url = conf.get("api", "base_url", fallback="/")
+ next_url = request.query_params.get("next")
+ redirect_url = next_url if next_url and is_safe_url(next_url,
request=request) else fallback_url
+ response = RedirectResponse(url=redirect_url)
# The default config has this as an empty string, so we can't use
`has_option`.
# And look at the request info (needs `--proxy-headers` flag to api-server)
diff --git
a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/routes/test_login.py
b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/routes/test_login.py
index 85c24cf8ac8..4460f3e5fd4 100644
---
a/airflow-core/tests/unit/api_fastapi/auth/managers/simple/routes/test_login.py
+++
b/airflow-core/tests/unit/api_fastapi/auth/managers/simple/routes/test_login.py
@@ -87,6 +87,28 @@ class TestLogin:
assert response.cookies.get("_token") is not None
assert "samesite=lax" in response.headers["set-cookie"].lower()
+ def test_login_all_admins_redirects_to_next_url(self, test_client):
+ with conf_vars({("core", "simple_auth_manager_all_admins"): "true",
("api", "ssl_cert"): "false"}):
+ response = test_client.get(
+
"/auth/token/login?next=/dags/example_dag/runs/manual__2026-05-20/tasks/example_task",
+ follow_redirects=False,
+ )
+ assert response.status_code == 307
+ assert (
+ response.headers["location"] ==
"/dags/example_dag/runs/manual__2026-05-20/tasks/example_task"
+ )
+ assert response.cookies.get("_token") is not None
+
+ def test_login_all_admins_ignores_unsafe_next_url(self, test_client):
+ with conf_vars({("core", "simple_auth_manager_all_admins"): "true",
("api", "ssl_cert"): "false"}):
+ response = test_client.get(
+ "/auth/token/login?next=https://example.com/malicious",
+ follow_redirects=False,
+ )
+ assert response.status_code == 307
+ assert response.headers["location"] == "/"
+ assert response.cookies.get("_token") is not None
+
def test_login_all_admins_config_disabled(self, test_client):
response = test_client.get("/auth/token/login", follow_redirects=False)
assert response.status_code == 403