Skip to content

Commit d7f8055

Browse files
edoakessampan-s-nayaksampan
authored
[core] Cherry pick fallback authorization header (#58826)
Cherry pick: #58819 Signed-off-by: sampan <[email protected]> Signed-off-by: Edward Oakes <[email protected]> Co-authored-by: Sampan S Nayak <[email protected]> Co-authored-by: sampan <[email protected]>
1 parent 1cd18e2 commit d7f8055

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

python/ray/_private/authentication/authentication_constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
AUTHORIZATION_HEADER_NAME = "authorization"
2626
AUTHORIZATION_BEARER_PREFIX = "Bearer "
27+
RAY_AUTHORIZATION_HEADER_NAME = "x-ray-authorization"
2728

2829
AUTHENTICATION_TOKEN_COOKIE_NAME = "ray-authentication-token"
2930
AUTHENTICATION_TOKEN_COOKIE_MAX_AGE = 30 * 24 * 60 * 60 # 30 days

python/ray/_private/authentication/http_token_authentication.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,20 @@ async def token_auth_middleware(request, handler):
4343
):
4444
return await handler(request)
4545

46-
# Check Authorization header first (for API clients)
46+
# Try to get authentication token from multiple sources (in priority order):
47+
# 1. Standard "Authorization" header (for API clients, SDKs)
48+
# 2. Fallback "X-Ray-Authorization" header (for proxies and KubeRay)
49+
# 3. Cookie (for web dashboard sessions)
50+
4751
auth_header = request.headers.get(
4852
authentication_constants.AUTHORIZATION_HEADER_NAME, ""
4953
)
5054

51-
# If no Authorization header, check cookie (for web dashboard)
55+
if not auth_header:
56+
auth_header = request.headers.get(
57+
authentication_constants.RAY_AUTHORIZATION_HEADER_NAME, ""
58+
)
59+
5260
if not auth_header:
5361
token = request.cookies.get(
5462
authentication_constants.AUTHENTICATION_TOKEN_COOKIE_NAME

python/ray/dashboard/tests/test_dashboard_auth.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,54 @@ def test_dashboard_request_requires_auth_invalid_token(setup_cluster_with_token_
5050
assert response.status_code == 403
5151

5252

53+
def test_dashboard_request_with_ray_auth_header(setup_cluster_with_token_auth):
54+
"""Test that requests succeed with valid token in X-Ray-Authorization header."""
55+
56+
cluster_info = setup_cluster_with_token_auth
57+
headers = {"X-Ray-Authorization": f"Bearer {cluster_info['token']}"}
58+
59+
response = requests.get(
60+
f"{cluster_info['dashboard_url']}/api/component_activities",
61+
headers=headers,
62+
)
63+
64+
assert response.status_code == 200
65+
66+
67+
def test_authorization_header_takes_precedence(setup_cluster_with_token_auth):
68+
"""Test that standard Authorization header takes precedence over X-Ray-Authorization."""
69+
70+
cluster_info = setup_cluster_with_token_auth
71+
72+
# Provide both headers: valid token in Authorization, invalid in X-Ray-Authorization
73+
headers = {
74+
"Authorization": f"Bearer {cluster_info['token']}",
75+
"X-Ray-Authorization": "Bearer invalid_token_000000000000000000000000",
76+
}
77+
78+
# Should succeed because Authorization header takes precedence
79+
response = requests.get(
80+
f"{cluster_info['dashboard_url']}/api/component_activities",
81+
headers=headers,
82+
)
83+
84+
assert response.status_code == 200
85+
86+
# Now test with invalid Authorization but valid X-Ray-Authorization
87+
headers = {
88+
"Authorization": "Bearer invalid_token_000000000000000000000000",
89+
"X-Ray-Authorization": f"Bearer {cluster_info['token']}",
90+
}
91+
92+
# Should fail because Authorization header takes precedence (even though it's invalid)
93+
response = requests.get(
94+
f"{cluster_info['dashboard_url']}/api/component_activities",
95+
headers=headers,
96+
)
97+
98+
assert response.status_code == 403
99+
100+
53101
def test_dashboard_auth_disabled(setup_cluster_without_token_auth):
54102
"""Test that auth is not enforced when AUTH_MODE is disabled."""
55103

0 commit comments

Comments
 (0)