fix: use FastMCP get_access_token() for OAuth claims extraction

The previous implementation tried to access OAuth token claims via
context.request_context.access_token.claims, which doesn't exist in
FastMCP's context structure.

FastMCP stores access tokens in Python's ContextVars, accessible via
the get_access_token() dependency function. This fix updates both
extract_user_from_context() and RBACMiddleware._extract_user_from_context()
to use this correct approach.

Before: Users appeared as "anonymous" with no groups (RBAC denied all)
After: User identity and groups correctly extracted from OAuth claims
This commit is contained in:
Ryan Malloy 2025-12-28 11:15:28 -07:00
parent ab83c70c31
commit 79d2caef45

View File

@ -92,24 +92,26 @@ def with_permission_check(tool_name: str) -> Callable:
def extract_user_from_context(ctx) -> dict[str, Any] | None:
"""Extract user information from FastMCP context.
Uses FastMCP's dependency injection to get the access token from
the current request's context variable.
Args:
ctx: FastMCP Context object.
ctx: FastMCP Context object (unused, kept for API compatibility).
Returns:
User info dict from OAuth token claims, or None if not authenticated.
"""
if ctx is None:
return None
# Try to get access token from context
try:
# FastMCP stores the access token in request_context
if hasattr(ctx, "request_context") and ctx.request_context:
token = getattr(ctx.request_context, "access_token", None)
if token and hasattr(token, "claims"):
return token.claims
except Exception:
pass
# FastMCP stores access token in a context variable, accessed via dependency
from fastmcp.server.dependencies import get_access_token
access_token = get_access_token()
if access_token and hasattr(access_token, "claims"):
return access_token.claims
except (RuntimeError, ImportError) as e:
# RuntimeError: No active HTTP request context
# ImportError: FastMCP auth dependencies not available
logger.debug("Could not get access token: %s", e)
return None
@ -208,23 +210,26 @@ class RBACMiddleware(Middleware):
) -> dict[str, Any] | None:
"""Extract user claims from FastMCP context.
Uses FastMCP's dependency injection to retrieve the access token
from the current request's context variable.
Args:
fastmcp_ctx: FastMCP Context object from middleware context.
fastmcp_ctx: FastMCP Context object (unused, kept for API compatibility).
Returns:
User claims dict from OAuth token, or None if not authenticated.
"""
if fastmcp_ctx is None:
return None
try:
# FastMCP stores access token in request_context
if hasattr(fastmcp_ctx, "request_context") and fastmcp_ctx.request_context:
token = getattr(fastmcp_ctx.request_context, "access_token", None)
if token and hasattr(token, "claims"):
return token.claims
except Exception as e:
logger.debug("Failed to extract user from context: %s", e)
# FastMCP stores access token in a context variable, accessed via dependency
from fastmcp.server.dependencies import get_access_token
access_token = get_access_token()
if access_token and hasattr(access_token, "claims"):
return access_token.claims
except (RuntimeError, ImportError) as e:
# RuntimeError: No active HTTP request context
# ImportError: FastMCP auth dependencies not available
logger.debug("Could not get access token: %s", e)
return None