
    k7i7                         S SK r S SKrS SKJrJrJrJrJrJrJ	r	  S SK
JrJr  S SKJr  S SKJrJrJr  SrSrSr " S S	\5      rg)
    N)AccessTokenAuthorizationCodeAuthorizationParamsAuthorizeErrorRefreshToken
TokenErrorconstruct_redirect_uri)OAuthClientInformationFull
OAuthToken)
AnyHttpUrl)ClientRegistrationOptionsOAuthProviderRevocationOptionsi,  i  c                     ^  \ rS rSrSr     S!S\\-  S-  S\\-  S-  S\S-  S\S-  S\	\   S-  4
U 4S	 jjjr
S
\S\S-  4S jrS\SS4S jrS\S\S\4S jrS\S\S\S-  4S jrS\S\S\4S jrS\S\S\S-  4S jrS\S\S\	\   S\4S jrS\S\S-  4S jrS\S\S-  4S jr S"S\S-  S\S-  4S jjrS\\-  SS4S jrS rU =r$ )#InMemoryOAuthProvider   zs
An in-memory OAuth provider for testing purposes.
It simulates the OAuth 2.1 flow locally without external calls.
Nbase_urlservice_documentation_urlclient_registration_optionsrevocation_optionsrequired_scopesc                    > [         TU ]  U=(       d    SUUUUS9  0 U l        0 U l        0 U l        0 U l        0 U l        0 U l        g )Nzhttp://fastmcp.example.com)r   r   r   r   r   )super__init__clients
auth_codesaccess_tokensrefresh_tokens_access_to_refresh_map_refresh_to_access_map)selfr   r   r   r   r   	__class__s         a/home/james-whalen/.local/lib/python3.13/site-packages/fastmcp/server/auth/providers/in_memory.pyr   InMemoryOAuthProvider.__init__%   sg     	=!=&?(C1+ 	 	
 ?A8:5779
  	#
  	#    	client_idreturnc                 @   #    U R                   R                  U5      $ 7fN)r   get)r!   r&   s     r#   
get_client InMemoryOAuthProvider.get_clientA   s     ||	**s   client_infoc                 r   #    UR                   U R                  ;   a   XR                  UR                   '   g 7fr)   )r&   r   )r!   r-   s     r#   register_client%InMemoryOAuthProvider.register_clientD   s.       DLL0 .9[**+s   57clientparamsc           
        #    UR                   U R                  ;  a  [        SSUR                    S3S9e UR                  UR                  ;  a   S[        R                  " S	5       3n[        R                  " 5       [        -   nUR                  b  UR                  O/ nUR                  (       a<  [        UR                  R                  5       5      nU Vs/ s H  oU;   d  M
  UPM     nn[        UUR                   UR                  UR                  UUUR                   S
9n	XR"                  U'   [%        ['        UR                  5      XBR(                  S9$ ! [
         a  n[        SSS9UeSnAff = fs  snf 7f)zs
Simulates user authorization and generates an authorization code.
Returns a redirect URI with the code and state.
unauthorized_clientzClient 'z' not registered.)errorerror_descriptioninvalid_requestzInvalid redirect_uri.Ntest_auth_code_   )coder&   redirect_uri redirect_uri_provided_explicitlyscopes
expires_atcode_challenge)r:   state)r&   r   r   r;   redirect_uris	Exceptionsecrets	token_hextime DEFAULT_AUTH_CODE_EXPIRY_SECONDSr=   scopesetsplitr   r<   r?   r   r	   strr@   )
r!   r1   r2   eauth_code_valuer>   scopes_listclient_allowed_scopess	auth_codes
             r#   	authorizeInMemoryOAuthProvider.authorizeL   sj     4<</ +$,V-=-=,>>O"P 	 ""&*>*>>  ,G,=,=b,A+BCYY[#CC
 (.}}'@fmmb<<$'(:(:(<$=!&1Pk:O5O1kKP% &&,,-3-T-T!!00	
	 ,5(%##$?,,
 	
5  	 ';R	 Qs<   3E<E BE<	E7&E7,A.E<
E4$E//E44E<authorization_codec                    #    U R                   R                  U5      nU(       aN  UR                  UR                  :w  a  g UR                  [        R                  " 5       :  a  U R                   U	 g U$ g 7fr)   )r   r*   r&   r>   rE   )r!   r1   rS   auth_code_objs       r#   load_authorization_code-InMemoryOAuthProvider.load_authorization_code   sc      ++,>?&&&*:*::''$))+5OO$67  s   A2A4c           	        #    UR                   U R                  ;  a  [        SS5      eU R                  UR                   	 S[        R                  " S5       3nS[        R                  " S5       3n[        [        R                  " 5       [        -   5      nS n[        b%  [        [        R                  " 5       [        -   5      n[        UUR                  UR                  US9U R                  U'   [        UUR                  UR                  US9U R                  U'   X@R                  U'   X0R                   U'   [#        US[        USR%                  UR                  5      S	9$ 7f)
Ninvalid_grantz-Authorization code not found or already used.test_access_token_    test_refresh_token_tokenr&   r=   r>   Bearer access_token
token_type
expires_inrefresh_tokenrG   )r:   r   r   rC   rD   intrE   #DEFAULT_ACCESS_TOKEN_EXPIRY_SECONDS$DEFAULT_REFRESH_TOKEN_EXPIRY_SECONDSr   r&   r=   r   r   r   r   r    r   join)r!   r1   rS   access_token_valuerefresh_token_valueaccess_token_expires_atrefresh_token_expires_ats          r#   exchange_authorization_code1InMemoryOAuthProvider.exchange_authorization_code   s`     ""$//9!P 
 OO.3341'2C2CB2G1HI 3G4E4Eb4I3JK"%diik4W&W"X $( /;'*		BB($ 2=$&&%,,.	2
-. 4@%&&%,,/	4
/0 ;N##$67;M##$78+:-((-445
 	
   E#E%re   c                   #    U R                   R                  U5      nU(       ag  UR                  UR                  :w  a  g UR                  b=  UR                  [        R                  " 5       :  a  U R                  UR                  S9  g U$ g 7f)Nrefresh_token_str)r   r*   r&   r>   rE   _revoke_internalr^   )r!   r1   re   	token_objs       r#   load_refresh_token(InMemoryOAuthProvider.load_refresh_token   s~      ''++M:	""f&6&66##/I4H4H499;4V%%&/oo &  s   BBr=   c           	        #    [        UR                  5      n[        U5      nUR                  U5      (       d  [        SS5      eU R	                  UR
                  S9  S[        R                  " S5       3nS[        R                  " S5       3n[        [        R                  " 5       [        -   5      nS n	[        b%  [        [        R                  " 5       [        -   5      n	[        UUR                  UUS9U R                  U'   [        UUR                  UU	S9U R                   U'   XpR"                  U'   X`R$                  U'   ['        US[        US	R)                  U5      S
9$ 7f)Ninvalid_scopez>Requested scopes exceed those authorized by the refresh token.rr   rZ   r[   r\   r]   r_   r`   ra   )rH   r=   issubsetr   rt   r^   rC   rD   rf   rE   rg   rh   r   r&   r   r   r   r   r    r   ri   )
r!   r1   re   r=   original_scopesrequested_scopesnew_access_token_valuenew_refresh_token_valuerl   rm   s
             r#   exchange_refresh_token,InMemoryOAuthProvider.exchange_refresh_token   sm     m223v;((99P  	0C0CD $6g6G6G6K5L!M$78I8I"8M7N"O"%diik4W&W"X $( /;'*		BB($ 6A(&&.	6
12 8D)&&/	8
34 ?V##$:;?U##$;</:1((6"
 	
rp   r^   c                    #    U R                   R                  U5      nU(       aL  UR                  b=  UR                  [        R                  " 5       :  a  U R	                  UR
                  S9  g U$ g 7f)Naccess_token_str)r   r*   r>   rE   rt   r^   )r!   r^   ru   s      r#   load_access_token'InMemoryOAuthProvider.load_access_token  se     &&**51	##/I4H4H499;4V%%%.__ &  s   A0A2c                 @   #    U R                  U5      I Sh  vN $  N7f)a  
Verify a bearer token and return access info if valid.

This method implements the TokenVerifier protocol by delegating
to our existing load_access_token method.

Args:
    token: The token string to validate

Returns:
    AccessToken object if valid, None if invalid or expired
N)r   r!   r^   s     r#   verify_token"InMemoryOAuthProvider.verify_token  s      ++E2222s   r   rs   c                    SnSnU(       a{  XR                   ;   a  U R                   U	 UnU R                  R                  US5      nU(       a:  XPR                  ;   a  U R                  U	 UnU R                  R                  US5        U(       a{  X R                  ;   a  U R                  U	 UnU R                  R                  US5      nU(       a:  X`R                   ;   a  U R                   U	 UnU R                  R                  US5        U(       a  X0R                  ;   a  U R                  U	 U(       a  X@R                  ;   a  U R                  U	 ggg)z8Internal helper to remove tokens and their associations.N)r   r   popr   r    )r!   r   rs   removed_access_tokenremoved_refresh_tokenassociated_refreshassociated_accesss          r#   rt   &InMemoryOAuthProvider._revoke_internal!  sQ     $ $#5#55&&'78'7$ "&!<!<!@!@AQSW!X!%)<)<<++,>?,>)++//0BDI $7$77''(9:(9% !% ; ; ? ?@QSW X $(:(::**+<=+<(++//0A4H  $8<W<W$W++,@A!%)D)DD++,AB E "r%   c                    #    [        U[        5      (       a  U R                  UR                  S9  g[        U[        5      (       a  U R                  UR                  S9  gg7f)z7Revokes an access or refresh token and its counterpart.r   rr   N)
isinstancer   rt   r^   r   r   s     r#   revoke_token"InMemoryOAuthProvider.revoke_tokenK  sP     
 e[))!!5;;!?|,,!!EKK!@ -s   A A")r   r    r   r   r   r   )NNNNN)NN)__name__
__module____qualname____firstlineno____doc__r   rJ   r   r   listr   r
   r+   r/   r   rQ   r   rV   r   rn   r   rv   r   r   r   r   rt   r   __static_attributes____classcell__)r"   s   @r#   r   r      s    -1=AHL7;,0s"T) $.#3d#: &?%E	
 .4 cT) 8+# +2Lt2S +:1K :PT :3
03
:M3
	3
j0FI	T	!1
01
FW1
	1
f0AD		5
*5
 $5
 S		5

 
5
n	S 	[45G 	3 3d0B 3  TX(C #d
(CFIDj(CTA\)A 
A Ar%   r   )rC   rE   mcp.server.auth.providerr   r   r   r   r   r   r	   mcp.shared.authr
   r   pydanticr   fastmcp.server.auth.authr   r   r   rF   rg   rh   r    r%   r#   <module>r      sR           $*  &- #'+ $tAM tAr%   