1
+ """
2
+ An FastMCP server that provides a "WhoAmI" tool to return the current user's information.
3
+
4
+ This server is compatible with OpenID Connect (OIDC) providers and uses the `mcpauth` library
5
+ to handle authorization. Please check https://mcp-auth.dev/docs/tutorials/whoami for more
6
+ information on how to use this server.
7
+ """
8
+
1
9
import os
2
10
from typing import Any
3
11
from mcp .server .fastmcp import FastMCP
@@ -41,6 +49,11 @@ def whoami() -> dict[str, Any]:
41
49
42
50
43
51
def verify_access_token (token : str ) -> AuthInfo :
52
+ """
53
+ Verifies the provided Bearer token by fetching user information from the authorization server.
54
+ If the token is valid, it returns an `AuthInfo` object containing the user's information.
55
+ """
56
+
44
57
endpoint = auth_server_config .metadata .userinfo_endpoint
45
58
if not endpoint :
46
59
raise ValueError (
@@ -50,37 +63,41 @@ def verify_access_token(token: str) -> AuthInfo:
50
63
try :
51
64
response = requests .get (
52
65
endpoint ,
53
- headers = {"Authorization" : f"Bearer { token } " },
66
+ headers = {
67
+ "Authorization" : f"Bearer { token } "
68
+ }, # Standard Bearer token header
54
69
)
55
- response .raise_for_status ()
56
- json = response .json ()
70
+ response .raise_for_status () # Ensure we raise an error for HTTP errors
71
+ json = response .json () # Parse the JSON response
57
72
return AuthInfo (
58
73
token = token ,
59
- subject = json .get ("sub" ),
60
- issuer = auth_issuer ,
61
- claims = json ,
74
+ subject = json .get (
75
+ "sub"
76
+ ), # 'sub' is a standard claim for the subject (user's ID)
77
+ issuer = auth_issuer , # Use the configured issuer
78
+ claims = json , # Include all claims (JSON fields) returned by the userinfo endpoint
62
79
)
80
+ # `AuthInfo` is a Pydantic model, so validation errors usually mean the response didn't match
81
+ # the expected structure
63
82
except pydantic .ValidationError as e :
64
83
raise MCPAuthTokenVerificationException (
65
84
MCPAuthTokenVerificationExceptionCode .INVALID_TOKEN ,
66
85
cause = e ,
67
86
)
87
+ # Handle other exceptions that may occur during the request
68
88
except Exception as e :
69
89
raise MCPAuthTokenVerificationException (
70
90
MCPAuthTokenVerificationExceptionCode .TOKEN_VERIFICATION_FAILED ,
71
91
cause = e ,
72
92
)
73
93
74
94
95
+ bearer_auth = Middleware (mcp_auth .bearer_auth_middleware (verify_access_token ))
75
96
app = Starlette (
76
97
routes = [
98
+ # Add the metadata route (`/.well-known/oauth-authorization-server`)
77
99
mcp_auth .metadata_route (),
78
- Mount (
79
- "/" ,
80
- app = mcp .sse_app (),
81
- middleware = [
82
- Middleware (mcp_auth .bearer_auth_middleware (verify_access_token ))
83
- ],
84
- ),
85
- ]
100
+ # Protect the MCP server with the Bearer auth middleware
101
+ Mount ("/" , app = mcp .sse_app (), middleware = [bearer_auth ]),
102
+ ],
86
103
)
0 commit comments