mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-20 20:44:17 +02:00
Merge pull request #892 from jlowin/claude-wt-20250620-113451
This commit is contained in:
commit
a0242e1c68
2 changed files with 63 additions and 2 deletions
|
|
@ -17,7 +17,7 @@ from mcp.shared.auth import (
|
|||
OAuthClientInformationFull,
|
||||
OAuthToken,
|
||||
)
|
||||
from pydantic import SecretStr
|
||||
from pydantic import AnyHttpUrl, SecretStr, ValidationError
|
||||
|
||||
from fastmcp.server.auth.auth import (
|
||||
ClientRegistrationOptions,
|
||||
|
|
@ -179,8 +179,16 @@ class BearerAuthProvider(OAuthProvider):
|
|||
if public_key and jwks_uri:
|
||||
raise ValueError("Provide either public_key or jwks_uri, not both")
|
||||
|
||||
# Only pass issuer to parent if it's a valid URL, otherwise use default
|
||||
# This allows the issuer claim validation to work with string issuers per RFC 7519
|
||||
try:
|
||||
issuer_url = AnyHttpUrl(issuer) if issuer else "https://fastmcp.example.com"
|
||||
except ValidationError:
|
||||
# Issuer is not a valid URL, use default for parent class
|
||||
issuer_url = "https://fastmcp.example.com"
|
||||
|
||||
super().__init__(
|
||||
issuer_url=issuer or "https://fastmcp.example.com",
|
||||
issuer_url=issuer_url,
|
||||
client_registration_options=ClientRegistrationOptions(enabled=False),
|
||||
revocation_options=RevocationOptions(enabled=False),
|
||||
required_scopes=required_scopes,
|
||||
|
|
|
|||
|
|
@ -539,6 +539,59 @@ class TestBearerToken:
|
|||
assert access_token is not None
|
||||
assert access_token.client_id == "app456" # Should prefer client_id over sub
|
||||
|
||||
async def test_string_issuer_validation(self, rsa_key_pair: RSAKeyPair):
|
||||
"""Test that string (non-URL) issuers are supported per RFC 7519."""
|
||||
# Create provider with string issuer
|
||||
provider = BearerAuthProvider(
|
||||
public_key=rsa_key_pair.public_key,
|
||||
issuer="my-service", # String issuer, not a URL
|
||||
)
|
||||
|
||||
# Create token with matching string issuer
|
||||
token = rsa_key_pair.create_token(
|
||||
subject="test-user",
|
||||
issuer="my-service", # Same string issuer
|
||||
)
|
||||
|
||||
access_token = await provider.load_access_token(token)
|
||||
assert access_token is not None
|
||||
assert access_token.client_id == "test-user"
|
||||
|
||||
async def test_string_issuer_mismatch_rejection(self, rsa_key_pair: RSAKeyPair):
|
||||
"""Test that mismatched string issuers are rejected."""
|
||||
# Create provider with one string issuer
|
||||
provider = BearerAuthProvider(
|
||||
public_key=rsa_key_pair.public_key,
|
||||
issuer="my-service",
|
||||
)
|
||||
|
||||
# Create token with different string issuer
|
||||
token = rsa_key_pair.create_token(
|
||||
subject="test-user",
|
||||
issuer="other-service", # Different string issuer
|
||||
)
|
||||
|
||||
access_token = await provider.load_access_token(token)
|
||||
assert access_token is None
|
||||
|
||||
async def test_url_issuer_still_works(self, rsa_key_pair: RSAKeyPair):
|
||||
"""Test that URL issuers still work after the fix."""
|
||||
# Create provider with URL issuer
|
||||
provider = BearerAuthProvider(
|
||||
public_key=rsa_key_pair.public_key,
|
||||
issuer="https://my-auth-server.com", # URL issuer
|
||||
)
|
||||
|
||||
# Create token with matching URL issuer
|
||||
token = rsa_key_pair.create_token(
|
||||
subject="test-user",
|
||||
issuer="https://my-auth-server.com", # Same URL issuer
|
||||
)
|
||||
|
||||
access_token = await provider.load_access_token(token)
|
||||
assert access_token is not None
|
||||
assert access_token.client_id == "test-user"
|
||||
|
||||
|
||||
class TestFastMCPBearerAuth:
|
||||
def test_bearer_auth(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue