Skip to content

Commit 674dbd0

Browse files
committed
more cleaning up
1 parent 09fdc6d commit 674dbd0

6 files changed

Lines changed: 31 additions & 37 deletions

File tree

examples/example-fastmcp-mcp/.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
AUTH0_DOMAIN=your-tenant.auth0.com
33
AUTH0_AUDIENCE=https://api.example.com
44
MCP_SERVER_URL=http://localhost:3001
5-
PORT=3001
5+
PORT=3001
6+
DEBUG=false

examples/example-fastmcp-mcp/src/auth0/__init__.py

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,29 @@
55
including token verification, middleware, and scoped tool decorators.
66
"""
77

8-
import os
9-
10-
from dotenv import load_dotenv
118
from mcp.server.auth.routes import create_protected_resource_routes
12-
from pydantic import AnyHttpUrl
139
from starlette.middleware import Middleware
1410
from starlette.routing import Route, Router
1511

16-
from .middeware import Auth0Middleware
12+
from .middleware import Auth0Middleware
1713

18-
# Load environment variables
19-
load_dotenv()
2014

2115
class Auth0Mcp:
22-
def __init__(self, name: str):
16+
def __init__(self, name: str, audience: str, domain: str):
2317
self.name = name
24-
self.audience = os.getenv("AUTH0_AUDIENCE", "https://api.example.com")
25-
self.domain = os.getenv("AUTH0_DOMAIN", "your-tenant.auth0.com")
18+
self.audience = audience
19+
self.domain = domain
20+
if not self.audience or not self.domain:
21+
raise RuntimeError("audience and domain must be provided")
2622

2723
def auth_metadata_router(self) -> Router:
2824
"""
2925
Returns a router that serves the OAuth Protected Resource Metadata
3026
at the standard endpoint: /.well-known/oauth-protected-resource
3127
"""
32-
routes: list[Route] = []
33-
34-
routes = create_protected_resource_routes(
35-
resource_url=AnyHttpUrl(self.audience),
36-
authorization_servers=[AnyHttpUrl(f"https://{self.domain}")],
28+
routes: list[Route] = create_protected_resource_routes(
29+
resource_url=self.audience,
30+
authorization_servers=[f"https://{self.domain}"],
3731
scopes_supported=[
3832
"openid",
3933
"profile",
@@ -45,12 +39,4 @@ def auth_metadata_router(self) -> Router:
4539
return Router(routes=routes)
4640

4741
def auth_middleware(self) -> list[Middleware]:
48-
middleware: list[Middleware] = []
49-
50-
middleware.append(
51-
Middleware(
52-
Auth0Middleware
53-
)
54-
)
55-
56-
return middleware
42+
return [Middleware(Auth0Middleware, domain=self.domain, audience=self.audience)]

examples/example-fastmcp-mcp/src/auth0/middeware.py renamed to examples/example-fastmcp-mcp/src/auth0/middleware.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@
1313
class Auth0Middleware(BaseHTTPMiddleware):
1414
"""
1515
Middleware that requires a valid Bearer token in the Authorization header.
16-
This will validate the token using Auth0 SDK Client and add the auth info to request.scope["auth"].
16+
Validates the token using Auth0 SDK Client and stores auth info in request.state.auth.
1717
"""
1818

19-
def __init__(self, app: ASGIApp):
19+
def __init__(self, app: ASGIApp, domain: str, audience: str):
2020
super().__init__(app)
21+
if not domain or not audience:
22+
raise RuntimeError("domain and audience must be provided")
2123
self.client = ApiClient(ApiClientOptions(
22-
domain=os.getenv("AUTH0_DOMAIN", "your-tenant.auth0.com"),
23-
audience=os.getenv("AUTH0_AUDIENCE", "https://api.example.com")
24+
domain=domain,
25+
audience=audience
2426
))
2527

2628
async def dispatch(self, request: Request, call_next):
@@ -50,7 +52,6 @@ async def dispatch(self, request: Request, call_next):
5052

5153
# Set up authentication context
5254
auth_data = {
53-
"token": token,
5455
"client_id": clientId,
5556
"scopes": decoded_and_verified_token.get("scope", "").split()
5657
if decoded_and_verified_token.get("scope") else []
@@ -66,7 +67,7 @@ async def dispatch(self, request: Request, call_next):
6667
extra[field] = decoded_and_verified_token.get(field)
6768

6869
auth_data["extra"] = extra
69-
request.scope["auth"] = auth_data
70+
request.state.auth = auth_data
7071

7172
return await call_next(request)
7273
except VerifyAccessTokenError as e:

examples/example-fastmcp-mcp/src/auth0/tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,5 @@ async def scope_checked_wrapper(*args, **kwargs):
8888

8989

9090
def get_auth_info(request) -> dict:
91-
"""Get authentication info from request."""
92-
return request.scope.get("auth", {})
91+
"""Get authentication info from request state."""
92+
return getattr(request.state, 'auth', {})

examples/example-fastmcp-mcp/src/server.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@
33
import os
44
from collections.abc import AsyncIterator
55

6+
from dotenv import load_dotenv
67
from starlette.applications import Starlette
78
from starlette.middleware.cors import CORSMiddleware
89
from starlette.routing import Mount
910

1011
from .auth0 import Auth0Mcp
1112
from .mcp import mcp
1213

14+
load_dotenv()
15+
1316
# Configure logging
1417
logging.basicConfig(level=logging.INFO)
1518
logger = logging.getLogger(__name__)
1619

17-
auth0_mcp = Auth0Mcp(name="Example FastMCP Server")
20+
auth0_mcp = Auth0Mcp(
21+
name="Example FastMCP Server",
22+
audience=os.getenv("AUTH0_AUDIENCE"),
23+
domain=os.getenv("AUTH0_DOMAIN")
24+
)
1825

1926
@contextlib.asynccontextmanager
2027
async def lifespan(app: Starlette) -> AsyncIterator[None]:
@@ -26,7 +33,7 @@ async def lifespan(app: Starlette) -> AsyncIterator[None]:
2633
yield
2734

2835
starlette_app = Starlette(
29-
debug=True,
36+
debug=os.getenv("DEBUG", "true").lower() == "true",
3037
routes=[
3138
# Add discovery metadata route
3239
*auth0_mcp.auth_metadata_router().routes,

examples/example-fastmcp-mcp/src/tools.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ def echo(text: str) -> str:
2323
annotations={"readOnlyHint": True}
2424
)
2525
def greet(name: str, ctx: Context) -> str:
26-
if not name or name.strip() == "":
27-
name = "world"
26+
name = (name or "").strip() or "world"
2827
request = ctx.request_context.request
2928
auth_info = get_auth_info(request)
3029
user_id = auth_info.get("extra", {}).get("sub")

0 commit comments

Comments
 (0)