mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Fix Azure scope fallback (#4469)
This commit is contained in:
parent
9f251bad00
commit
1d932cc778
2 changed files with 34 additions and 7 deletions
|
|
@ -501,8 +501,12 @@ class AzureProvider(OAuthProxy):
|
|||
Returns:
|
||||
List of scopes for Azure token endpoint
|
||||
"""
|
||||
# Prefix scopes for this API
|
||||
prefixed_scopes = self._prefix_scopes_for_azure(scopes or [])
|
||||
# Prefix scopes for this API. Some clients omit the scope parameter on
|
||||
# the MCP authorization request; use the provider's configured scopes
|
||||
# just like the authorize URL path does.
|
||||
prefixed_scopes = self._prefix_scopes_for_azure(
|
||||
scopes or self.required_scopes or []
|
||||
)
|
||||
|
||||
# Add OIDC scopes only (not other API scopes) to avoid AADSTS28000
|
||||
if self.additional_authorize_scopes:
|
||||
|
|
@ -528,9 +532,13 @@ class AzureProvider(OAuthProxy):
|
|||
"""
|
||||
logger.debug("Base scopes from storage: %s", scopes)
|
||||
|
||||
# Some clients omit the scope parameter on the MCP authorization request;
|
||||
# use the provider's configured scopes just like the authorize URL path does.
|
||||
requested_scopes = scopes or self.required_scopes or []
|
||||
|
||||
# Filter out any additional_authorize_scopes that may have been stored
|
||||
additional_scopes_set = set(self.additional_authorize_scopes or [])
|
||||
base_scopes = [s for s in scopes if s not in additional_scopes_set]
|
||||
base_scopes = [s for s in requested_scopes if s not in additional_scopes_set]
|
||||
|
||||
# Prefix base scopes with identifier_uri for Azure
|
||||
prefixed_scopes = self._prefix_scopes_for_azure(base_scopes)
|
||||
|
|
|
|||
|
|
@ -445,6 +445,25 @@ class TestAzureProvider:
|
|||
assert "Mail.Read" in upstream_url
|
||||
assert "User.Read" in upstream_url
|
||||
|
||||
def test_prepare_scopes_for_token_exchange_falls_back_to_required_scopes(
|
||||
self, memory_storage: MemoryStore
|
||||
):
|
||||
"""Clients may omit scope; Azure still needs an API scope with offline_access."""
|
||||
provider = AzureProvider(
|
||||
client_id="test_client",
|
||||
client_secret="test_secret",
|
||||
tenant_id="test-tenant",
|
||||
base_url="https://myserver.com",
|
||||
identifier_uri="api://my-api",
|
||||
required_scopes=["read"],
|
||||
jwt_signing_key="test-secret",
|
||||
client_storage=memory_storage,
|
||||
)
|
||||
|
||||
result = provider._prepare_scopes_for_token_exchange([])
|
||||
|
||||
assert result == ["api://my-api/read", "offline_access"]
|
||||
|
||||
def test_base_authority_defaults_to_public_cloud(self, memory_storage: MemoryStore):
|
||||
"""Test that base_authority defaults to login.microsoftonline.com."""
|
||||
provider = AzureProvider(
|
||||
|
|
@ -724,10 +743,10 @@ class TestAzureProvider:
|
|||
"https://graph.microsoft.com/.default" in result
|
||||
) # Not prefixed (contains ://)
|
||||
|
||||
def test_prepare_scopes_for_upstream_refresh_empty_scopes(
|
||||
def test_prepare_scopes_for_upstream_refresh_empty_scopes_falls_back_to_required(
|
||||
self, memory_storage: MemoryStore
|
||||
):
|
||||
"""Test behavior with empty scopes list."""
|
||||
"""Clients may omit scope; refresh should still request the configured API scope."""
|
||||
provider = AzureProvider(
|
||||
client_id="test_client",
|
||||
client_secret="test_secret",
|
||||
|
|
@ -740,13 +759,13 @@ class TestAzureProvider:
|
|||
client_storage=memory_storage,
|
||||
)
|
||||
|
||||
# Empty scopes should still add OIDC scopes (not User.Read)
|
||||
result = provider._prepare_scopes_for_upstream_refresh([])
|
||||
|
||||
assert "api://my-api/read" in result
|
||||
assert "User.Read" not in result # Not OIDC
|
||||
assert "openid" in result
|
||||
assert "offline_access" in result # Auto-included
|
||||
assert len(result) == 2 # Only OIDC scopes: openid + offline_access
|
||||
assert len(result) == 3
|
||||
|
||||
def test_prepare_scopes_for_upstream_refresh_no_additional_scopes(
|
||||
self, memory_storage: MemoryStore
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue