1919
2020from mcp .server .auth .errors import InvalidTokenError
2121from mcp .server .auth .provider import (
22+ AuthorizationCodeMeta ,
2223 AuthorizationParams ,
2324 OAuthRegisteredClientsStore ,
2425 OAuthServerProvider ,
26+ OAuthTokenRevocationRequest ,
2527)
2628from mcp .server .auth .router import (
2729 ClientRegistrationOptions ,
3234from mcp .server .fastmcp import FastMCP
3335from mcp .shared .auth import (
3436 OAuthClientInformationFull ,
35- OAuthTokenRevocationRequest ,
3637 OAuthTokens ,
3738)
3839from mcp .types import JSONRPCRequest
@@ -74,32 +75,19 @@ async def create_authorization_code(
7475 code = f"code_{ int (time .time ())} "
7576
7677 # Store the code for later verification
77- self .auth_codes [code ] = {
78- " client_id" : client .client_id ,
79- " code_challenge" : params .code_challenge ,
80- " redirect_uri" : params .redirect_uri ,
81- "expires_at" : int ( time .time ()) + 600 , # 10 minutes
82- }
78+ self .auth_codes [code ] = AuthorizationCodeMeta (
79+ client_id = client .client_id ,
80+ code_challenge = params .code_challenge ,
81+ redirect_uri = params .redirect_uri ,
82+ issued_at = time .time (),
83+ )
8384
8485 return code
8586
86- async def challenge_for_authorization_code (
87+ async def load_authorization_code_metadata (
8788 self , client : OAuthClientInformationFull , authorization_code : str
88- ) -> str :
89- # Get the stored code info
90- code_info = self .auth_codes .get (authorization_code )
91- if not code_info :
92- raise InvalidTokenError ("Invalid authorization code" )
93-
94- # Check if code is expired
95- if code_info ["expires_at" ] < int (time .time ()):
96- raise InvalidTokenError ("Authorization code has expired" )
97-
98- # Check if the code was issued to this client
99- if code_info ["client_id" ] != client .client_id :
100- raise InvalidTokenError ("Authorization code was not issued to this client" )
101-
102- return code_info ["code_challenge" ]
89+ ) -> AuthorizationCodeMeta | None :
90+ return self .auth_codes .get (authorization_code )
10391
10492 async def exchange_authorization_code (
10593 self , client : OAuthClientInformationFull , authorization_code : str
@@ -109,14 +97,6 @@ async def exchange_authorization_code(
10997 if not code_info :
11098 raise InvalidTokenError ("Invalid authorization code" )
11199
112- # Check if code is expired
113- if code_info ["expires_at" ] < int (time .time ()):
114- raise InvalidTokenError ("Authorization code has expired" )
115-
116- # Check if the code was issued to this client
117- if code_info ["client_id" ] != client .client_id :
118- raise InvalidTokenError ("Authorization code was not issued to this client" )
119-
120100 # Generate an access token and refresh token
121101 access_token = f"access_{ secrets .token_hex (32 )} "
122102 refresh_token = f"refresh_{ secrets .token_hex (32 )} "
@@ -436,6 +416,7 @@ async def test_authorization_flow(
436416 "client_secret" : client_info ["client_secret" ],
437417 "code" : auth_code ,
438418 "code_verifier" : code_verifier ,
419+ "redirect_uri" : "https://client.example.com/callback" ,
439420 },
440421 )
441422 assert response .status_code == 200
@@ -465,6 +446,7 @@ async def test_authorization_flow(
465446 "client_id" : client_info ["client_id" ],
466447 "client_secret" : client_info ["client_secret" ],
467448 "refresh_token" : refresh_token ,
449+ "redirect_uri" : "https://client.example.com/callback" ,
468450 },
469451 )
470452 assert response .status_code == 200
@@ -585,6 +567,7 @@ def test_tool(x: int) -> str:
585567 "client_secret" : client_info ["client_secret" ],
586568 "code" : auth_code ,
587569 "code_verifier" : code_verifier ,
570+ "redirect_uri" : "https://client.example.com/callback" ,
588571 },
589572 )
590573 assert response .status_code == 200
0 commit comments