
    K.hY                        d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
mZ ddlmZmZ ddlmZ ddlmZmZmZ ddlZddlZddlmZmZmZ ddlmZ dd	lmZmZm Z m!Z!m"Z" dd
l#m$Z$m%Z% ddl&m'Z'  ej(        e)          Z* G d de+          Z, G d de,          Z- G d de,          Z. G d de          Z/ G d de          Z0e G d d                      Z1 G d dej2                  Z3dS )z|
OAuth2 Authentication implementation for HTTPX.

Implements authorization code flow with PKCE and automatic token refresh.
    N)AsyncGenerator	AwaitableCallable)	dataclassfield)Protocol)	urlencodeurljoinurlparse)	BaseModelFieldValidationError)MCP_PROTOCOL_VERSION)OAuthClientInformationFullOAuthClientMetadataOAuthMetadata
OAuthTokenProtectedResourceMetadata)check_resource_allowedresource_url_from_server_url)LATEST_PROTOCOL_VERSIONc                       e Zd ZdZdS )OAuthFlowErrorz%Base exception for OAuth flow errors.N__name__
__module____qualname____doc__     a/Users/user/workspace/sujinbaek/cqa-test-app/venv/lib/python3.11/site-packages/mcp/client/auth.pyr   r   %   s        ////r    r   c                       e Zd ZdZdS )OAuthTokenErrorz"Raised when token operations fail.Nr   r   r    r!   r#   r#   )   s        ,,,,r    r#   c                       e Zd ZdZdS )OAuthRegistrationErrorz&Raised when client registration fails.Nr   r   r    r!   r%   r%   -   s        0000r    r%   c                   x    e Zd ZU dZ eddd          Zeed<    eddd          Zeed<   e	dd	            Z
d
S )PKCEParametersz.PKCE (Proof Key for Code Exchange) parameters..+      )
min_length
max_lengthcode_verifiercode_challengereturnc                 V   d                     d t          d          D                       }t          j        |                                                                          }t          j        |                                          	                    d          } | ||          S )zGenerate new PKCE parameters. c              3   r   K   | ]2}t          j        t          j        t          j        z   d z             V  3dS )z-._~N)secretschoicestringascii_lettersdigits).0_s     r!   	<genexpr>z*PKCEParameters.generate.<locals>.<genexpr>:   s=      rrbcv/Cfm/SV\/\ ] ]rrrrrrr    r)   =)r,   r-   )
joinrangehashlibsha256encodedigestbase64urlsafe_b64encodedecoderstrip)clsr,   r@   r-   s       r!   generatezPKCEParameters.generate7   s     rrglmpgqgqrrrrr 4 4 6 677>>@@1&99@@BBII#NNs~NNNNr    N)r.   r'   )r   r   r   r   r   r,   str__annotations__r-   classmethodrF   r   r    r!   r'   r'   1   s         88srcBBBM3BBB%sCCCNCCCCO O O [O O Or    r'   c                   V    e Zd ZdZdedz  fdZdeddfdZdedz  fdZdeddfd	Z	dS )
TokenStoragez+Protocol for token storage implementations.r.   Nc                 
   K   dS )zGet stored tokens.Nr   selfs    r!   
get_tokenszTokenStorage.get_tokensC         r    tokensc                 
   K   dS )zStore tokens.Nr   )rN   rQ   s     r!   
set_tokenszTokenStorage.set_tokensG   rP   r    c                 
   K   dS )zGet stored client information.Nr   rM   s    r!   get_client_infozTokenStorage.get_client_infoK   rP   r    client_infoc                 
   K   dS )zStore client information.Nr   )rN   rV   s     r!   set_client_infozTokenStorage.set_client_infoO   rP   r    )
r   r   r   r   r   rO   rS   r   rU   rX   r   r    r!   rK   rK   @   s        55*t"3    z d    'AD'H    1K PT      r    rK   c                      e Zd ZU dZeed<   eed<   eed<   eege	d         f         ed<   eg e	e
eedz  f                  f         ed<   dZeed	<   dZedz  ed
<   dZedz  ed<   dZedz  ed<   dZedz  ed<   dZedz  ed<   dZedz  ed<   dZedz  ed<    eej                  Zej        ed<   dZedz  ed<   dZedz  ed<   dedefdZdeddfdZde fdZ!de fdZ"ddZ#defdZ$ddedz  de fdZ%dS ) OAuthContextzOAuth flow context.
server_urlclient_metadatastorageNredirect_handlercallback_handler     r@timeoutprotected_resource_metadataoauth_metadataauth_server_urlprotocol_versionrV   current_tokenstoken_expiry_time)default_factorylockdiscovery_base_urldiscovery_pathnamer.   c                 B    t          |          }|j         d|j         S )z,Extract base URL by removing path component.://)r   schemenetloc)rN   r[   parseds      r!   get_authorization_base_urlz'OAuthContext.get_authorization_base_urls   s'    *%%-33FM333r    tokenc                 f    |j         r"t          j                    |j         z   | _        dS d| _        dS )zUpdate token expiry time.N)
expires_intimerg   )rN   rr   s     r!   update_token_expiryz OAuthContext.update_token_expiryx   s7     	*%)Y[[53C%CD"""%)D"""r    c                     t          | j        o/| j        j        o#| j         pt	          j                    | j        k              S )z Check if current token is valid.)boolrf   access_tokenrg   ru   rM   s    r!   is_token_validzOAuthContext.is_token_valid   sK     V#0V++Tty{{d>T/T
 
 	
r    c                 P    t          | j        o| j        j        o| j                  S )z Check if token can be refreshed.)rx   rf   refresh_tokenrV   rM   s    r!   can_refresh_tokenzOAuthContext.can_refresh_token   s'    D'bD,?,MbRVRbcccr    c                 "    d| _         d| _        dS )zClear current tokens.N)rf   rg   rM   s    r!   clear_tokenszOAuthContext.clear_tokens   s    "!%r    c                     t          | j                  }| j        r8| j        j        r,t	          | j        j                  }t          ||          r|}|S )zGet resource URL for RFC 8707.

        Uses PRM resource if it's a valid parent, otherwise uses canonical server URL.
        )requested_resourceconfigured_resource)r   r[   rb   resourcerG   r   )rN   r   prm_resources      r!   get_resource_urlzOAuthContext.get_resource_url   s`    
 0@@ + 	(0P0Y 	(t?HIIL%Wcddd ('r    c                 (    | j         dS |sdS |dk    S )zDetermine if the resource parameter should be included in OAuth requests.

        Returns True if:
        - Protected resource metadata is available, OR
        - MCP-Protocol-Version header is 2025-06-18 or later
        NTFz
2025-06-18)rb   )rN   re   s     r!   should_include_resource_paramz*OAuthContext.should_include_resource_param   s.     +74   	5  <//r    r.   N)N)&r   r   r   r   rG   rH   r   rK   r   r   tuplera   floatrb   r   rc   r   rd   re   rV   r   rf   r   rg   r   anyioLockri   rj   rk   rq   rv   rx   rz   r}   r   r   r   r   r    r!   rZ   rZ   T   sW        OOO((((uio56666r9U3d
?-C#DDEEEEGU EI!:T!AHHH+/NMD(///"&OS4Z&&&#'cDj''' 6:K+d2999 )-NJ%,,,&*ut|*** uUZ888D%*888 &*d
)))%)d
)))4S 4S 4 4 4 4
* * * * * *
 
 
 
 
d4 d d d d& & & &
#    0 0cDj 0TX 0 0 0 0 0 0r    rZ   c                   N   e Zd ZdZdZ	 d#dedededeege	d         f         d	eg e	e
eedz  f                  f         d
efdZdej        dedz  fdZdej        dej        fdZdej        ddfdZdee         fdZdej        dz  fdZdej        ddfdZde
eef         fdZdededej        fdZdej        ddfdZdej        fdZdej        defdZd$dZdej        ddfdZdedej        fd Zdej        ddfd!Z dej        de!ej        ej        f         fd"Z"dS )%OAuthClientProviderzw
    OAuth2 authentication for httpx.
    Handles OAuth flow with automatic client registration and token storage.
    Tr`   r[   r\   r]   r^   Nr_   ra   c                 H    t          ||||||          | _        d| _        dS )z!Initialize OAuth2 authentication.)r[   r\   r]   r^   r_   ra   FN)rZ   context_initialized)rN   r[   r\   r]   r^   r_   ra   s          r!   __init__zOAuthClientProvider.__init__   s<     $!+--
 
 
 "r    init_responser.   c                     |r|j         dk    rdS |j                            d          }|sdS d}t          j        ||          }|r*|                    d          p|                    d          S dS )z
        Extract protected resource metadata URL from WWW-Authenticate header as per RFC9728.

        Returns:
            Resource metadata URL if found in WWW-Authenticate header, None otherwise
          NzWWW-Authenticatez)resource_metadata=(?:"([^"]+)"|([^\s,]+))      )status_codeheadersgetresearchgroup)rN   r   www_auth_headerpatternmatchs        r!   (_extract_resource_metadata_from_www_authz<OAuthClientProvider._extract_resource_metadata_from_www_auth   s      	 9S @ @4'/334FGG 	4 ?	'?33 	4;;q>>3U[[^^3tr    c                    K   |                      |          }|s4| j                            | j        j                  }t	          |d          }t          j        d|t          t          i          S )Nz%/.well-known/oauth-protected-resourceGETr   )	r   r   rq   r[   r
   httpxRequestr   r   )rN   r   urlauth_base_urls       r!   _discover_protected_resourcez0OAuthClientProvider._discover_protected_resource   sj      ;;MJJ 	R LCCDLD[\\M-)PQQC}UC2FH_1`aaaar    responsec                   K   |j         dk    r{	 |                                 d{V }t          j        |          }|| j        _        |j        r&t          |j        d                   | j        _        dS dS # t          $ r Y dS w xY wdS )zHandle discovery response.   Nr   )
r   areadr   model_validate_jsonr   rb   authorization_serversrG   rd   r   rN   r   contentmetadatas       r!   #_handle_protected_resource_responsez7OAuthClientProvider._handle_protected_resource_response   s      3&& ( 0 00000004HQQ;C81 Z36x7UVW7X3Y3YDL000Z Z"    '&s   A%A8 8
BBc                 b   g }| j         j        p| j         j        }t          |          }|j         d|j         }|j        rK|j        dk    r@d|j                            d           }|                    t          ||                     |                    t          |d                     |j        rK|j        dk    r@d|j                            d           }|                    t          ||                     |                    d           d}|                    |           |S )zCGenerate ordered list of (url, type) tuples for discovery attempts.rm   /z'/.well-known/oauth-authorization-serverz!/.well-known/openid-configuration)
r   rd   r[   r   rn   ro   pathrD   appendr
   )rN   urlsrd   rp   base_url
oauth_path	oidc_pathoidc_fallbacks           r!   _get_discovery_urlsz'OAuthClientProvider._get_discovery_urls   s6   ,6Q$,:Q/**m7777 ; 	76;#--\6;CUCUVYCZCZ\\JKK*55666 	GH&OPPQQQ ; 	66;#--UFK<N<Ns<S<SUUIKK)44555 +11#66YYYM"""r    c                 z  K   | j         j        rdS | j         j        r0| j         j        j        rt	          | j         j        j                  }n4| j                             | j         j                  }t          |d          }| j         j        	                    ddd          }t          j        d||ddi	          S )
z9Build registration request or skip if already registered.Nz	/registerTjson)by_aliasmodeexclude_nonePOSTContent-Typezapplication/json)r   r   )r   rV   rc   registration_endpointrG   rq   r[   r
   r\   
model_dumpr   r   )rN   registration_urlr   registration_datas       r!   _register_clientz$OAuthClientProvider._register_client  s      <# 	4<& 	C4<+F+\ 	C"4<#>#TUU LCCDLD[\\M&}kBB L8CCTX^mqCrr}$+<~WiFj
 
 
 	
r    c                   K   |j         dvr9|                                 d{V  t          d|j          d|j                   	 |                                 d{V }t	          j        |          }|| j        _        | j        j        	                    |           d{V  dS # t          $ r}t          d|           d}~ww xY w)zHandle registration response.)r      NzRegistration failed:  zInvalid registration response: )r   r   r%   textr   r   r   rV   r]   rX   r   )rN   r   r   rV   es        r!   _handle_registration_responsez1OAuthClientProvider._handle_registration_response*  s     z11.."""""""""()gAU)g)gX`Xe)g)ghhh	P$NN,,,,,,,,G4HQQK'2DL$,&66{CCCCCCCCCCC 	P 	P 	P()N1)N)NOOO	Ps   AB' '
C1CCc                   K   | j         j        r0| j         j        j        rt          | j         j        j                  }n4| j                             | j         j                  }t          |d          }| j         j        st          d          t          
                                }t          j        d          }d| j         j        j        t          | j         j        j        d                   ||j        dd}| j                             | j         j                  r| j                                         |d<   | j         j        j        r| j         j        j        |d	<   | d
t+          |           }| j                             |           d{V  | j                                          d{V \  }}|t          j        ||          st          d| d|           |st          d          ||j        fS )z5Perform the authorization redirect and get auth code.z
/authorizez*No client info available for authorization    coder   S256)response_type	client_idredirect_uristater-   code_challenge_methodr   scope?NzState parameter mismatch: z != zNo authorization code received)r   rc   authorization_endpointrG   rq   r[   r
   rV   r   r'   rF   r2   token_urlsafer   r\   redirect_urisr-   r   re   r   r   r	   r^   r_   compare_digestr,   )	rN   auth_endpointr   pkce_paramsr   auth_paramsauthorization_url	auth_codereturned_states	            r!   _perform_authorizationz*OAuthClientProvider._perform_authorization8  s     <& 	A4<+F+] 	A ; RSSMM LCCDLD[\\M#M<@@M|' 	O !MNNN %--//%b)) $1; < J1 MNN)8%+
 
 <55dl6STT 	F&*l&C&C&E&EK
#<'- 	F#'<#?#EK ,GGy/E/EGGl++,=>>>>>>>>> +/,*G*G*I*I$I$I$I$I$I$I!	>!)?PU)V)V! !Yn!Y!YRW!Y!YZZZ 	C !ABBB +333r    r   r,   c                   K   | j         j        st          d          | j         j        r0| j         j        j        rt          | j         j        j                  }n4| j                             | j         j                  }t          |d          }d|t          | j         j	        j
        d                   | j         j        j        |d}| j                             | j         j                  r| j                                         |d<   | j         j        j        r| j         j        j        |d<   t!          j        d||d	d
i          S )zBuild token exchange request.zMissing client info/tokenauthorization_coder   )
grant_typer   r   r   r,   r   client_secretr   r   !application/x-www-form-urlencodeddatar   )r   rV   r   rc   token_endpointrG   rq   r[   r
   r\   r   r   r   re   r   r   r   r   )rN   r   r,   	token_urlr   
token_datas         r!   _exchange_tokenz#OAuthClientProvider._exchange_tokenf  s;     |' 	8 !6777<& 	94<+F+U 	9DL7FGGII LCCDLD[\\Mx88I / < J1 MNN1;*
 

 <55dl6STT 	E%)\%B%B%D%DJz"<#1 	Q*.,*B*PJ'}IJIl8m
 
 
 	
r    c                   K   |j         dk    rt          d|j                    	 |                                 d{V }t          j        |          }|j        r| j        j        j        rot          | j        j        j        	                                          }t          |j        	                                          }||z
  }|rt          d|           || j        _
        | j                            |           | j        j                            |           d{V  dS # t          $ r}t          d|           d}~ww xY w)zHandle token exchange response.r   zToken exchange failed: Nz$Server granted unauthorized scopes: zInvalid token response: )r   r#   r   r   r   r   r   r\   setsplitrf   rv   r]   rS   r   )rN   r   r   token_responserequested_scopesreturned_scopesunauthorized_scopesr   s           r!   _handle_token_responsez*OAuthClientProvider._handle_token_response  sy     3&&!"RH<P"R"RSSS	B$NN,,,,,,,,G';GDDN # h(D(J h#&t|'C'I'O'O'Q'Q#R#R "%n&:&@&@&B&B"C"C&58H&H#& h)*fQd*f*fggg*8DL'L,,^<<<,&11.AAAAAAAAAAA 	B 	B 	B!"@Q"@"@AAA	Bs   D D( (
E	2EE	c                   K   | j         j        r| j         j        j        st          d          | j         j        st          d          | j         j        r0| j         j        j        rt          | j         j        j                  }n4| j                             | j         j	                  }t          |d          }d| j         j        j        | j         j        j        d}| j                             | j         j                  r| j                                         |d<   | j         j        j        r| j         j        j        |d<   t!          j        d||d	d
i          S )zBuild token refresh request.zNo refresh token availablezNo client info availabler   r|   )r   r|   r   r   r   r   r   r   r   )r   rf   r|   r#   rV   rc   r   rG   rq   r[   r
   r   r   re   r   r   r   r   )rN   r   r   refresh_datas       r!   _refresh_tokenz"OAuthClientProvider._refresh_token  sU     |* 	@$,2M2[ 	@!">???|' 	>!"<===<& 	94<+F+U 	9DL7FGGII LCCDLD[\\Mx88I *!\8F1;
 
 <55dl6STT 	G'+|'D'D'F'FL$<#1 	S,0L,D,RL)}IL>Kn:o
 
 
 	
r    c                   K   |j         dk    r=t                              d|j                     | j                                         dS 	 |                                 d{V }t          j        |          }|| j        _        | j        	                    |           | j        j
                            |           d{V  dS # t          $ r7 t                              d           | j                                         Y dS w xY w)z:Handle token refresh response. Returns True if successful.r   zToken refresh failed: FNTzInvalid refresh response)r   loggerwarningr   r   r   r   r   rf   rv   r]   rS   r   	exception)rN   r   r   r   s       r!   _handle_refresh_responsez,OAuthClientProvider._handle_refresh_response  s     3&&NNJH4HJJKKKL%%'''5	$NN,,,,,,,,G';GDDN*8DL'L,,^<<<,&11.AAAAAAAAA4 	 	 	7888L%%'''55	s   A9C =DDc                    K   | j         j                                         d{V | j         _        | j         j                                         d{V | j         _        d| _        dS )z#Load stored tokens and client info.NT)r   r]   rO   rf   rU   rV   r   rM   s    r!   _initializezOAuthClientProvider._initialize  sn      ,0L,@,K,K,M,M&M&M&M&M&M&M#)-)=)M)M)O)O#O#O#O#O#O#O  r    requestc                     | j         j        r/| j         j        j        r d| j         j        j         |j        d<   dS dS dS )z<Add authorization header to request if we have valid tokens.zBearer AuthorizationN)r   rf   ry   r   )rN   r  s     r!   _add_auth_headerz$OAuthClientProvider._add_auth_header  sZ    <& 	d4<+F+S 	d/c9T9a/c/cGOO,,,	d 	d 	d 	dr    r   c                 H    t          j        d|t          t          i          S )Nr   r   )r   r   r   r   )rN   r   s     r!   _create_oauth_metadata_requestz2OAuthClientProvider._create_oauth_metadata_request  s     }UC2FH_1`aaaar    c                   K   |                                  d {V }t          j        |          }|| j        _        | j        j        j        2|j        -d                    |j                  | j        j        _        d S d S d S )Nr   )	r   r   r   r   rc   r\   r   scopes_supportedr;   r   s       r!   _handle_oauth_metadata_responsez3OAuthClientProvider._handle_oauth_metadata_response  s       (((((((( 4W==&.#<'-5(:S:_14(:S1T1TDL(... 65:_:_r    c                  K   | j         j        4 d{V  | j        s|                                  d{V  |j                            t                    | j         _        | j                                         sZ| j         	                                rA| 
                                 d{V }|W V }|                     |           d{V sd| _        | j                                         r|                     |           |W V }|j        dk    r	 |                     |           d{V }|W V }|                     |           d{V  |                                 }|D ]m}|                     |          }	|	W V }
|
j        dk    r.	 |                     |
           d{V   n)# t&          $ r Y Qw xY w|
j        dk     s|
j        dk    r nn|                                  d{V }|r |W V }|                     |           d{V  |                                  d{V \  }}|                     ||           d{V }|W V }|                     |           d{V  n)# t2          $ r t4                              d            w xY w|                     |           |W V  ddd          d{V  dS # 1 d{V swxY w Y   dS )zHTTPX auth flow integration.NFr   r   i  i  zOAuth flow error)r   ri   r   r  r   r   r   re   rz   r}   r   r  r  r   r   r   r   r	  r  r   r   r   r   r   r   	Exceptionr   r   )rN   r  refresh_requestrefresh_responser   discovery_requestdiscovery_responsediscovery_urlsr   oauth_metadata_requestoauth_metadata_responseregistration_requestregistration_responser   r,   token_requestr   s                    r!   async_auth_flowz#OAuthClientProvider.async_auth_flow  s     <$ @	 @	 @	 @	 @	 @	 @	 @	$ )&&((((((((( -4O,?,?@T,U,UDL)<..00 .T\5S5S5U5U .(,(;(;(=(="="="="="="=)8#8#8#8 !::;KLLLLLLLL .(-D%|**,, /%%g...$}}}H#s**% /3.O.OPX.Y.Y(Y(Y(Y(Y(Y(Y%/@)@)@)@&BBCUVVVVVVVVV &*%=%=%?%?N- " "151T1TUX1Y1Y.8N2N2N2N/2>#EE)&*&J&JKb&c&c c c c c c c c %#2 ) ) ) ()4@3FFJaJmqtJtJt!E Ku 261F1F1H1H+H+H+H+H+H+H(+ X6J0J0J0J-"@@AVWWWWWWWWW 6:5P5P5R5R/R/R/R/R/R/R,I} +/*>*>y-*X*X$X$X$X$X$X$XM+8%8%8%8N55nEEEEEEEEEE    $$%7888
 %%g...A@	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	 @	sP   C=J>A8I(F)'I()
F63I(5F66B1I('J>(&JJ>>
KK)r`   r   )#r   r   r   r   requires_response_bodyrG   r   rK   r   r   r   r   r   r   Responser   r   r   r   listr   r   r   r   r   r   r   rx   r  r  r  r	  r  r   r  r   r    r!   r   r      s        
 " " "" -" 	"
 #C5)D/#9:" #2ysC$J1G'H#HI" " " " "(en Y\_cYc    0	b 	bSXS` 	b 	b 	b 	b
%. 
UY 
 
 
 
T#Y    6
(< 
 
 
 
"PEN Pt P P P P,4eCHo ,4 ,4 ,4 ,4\
s 
3 
5= 
 
 
 
<BU^ B B B B B.
em 
 
 
 
>u~ $    *! ! ! !d d$ d d d d
b# b%- b b b bUen UQU U U U UBU] B~em]b]kNk?l B B B B B Br    r   )4r   rA   r=   loggingr   r2   r4   ru   collections.abcr   r   r   dataclassesr   r   typingr   urllib.parser	   r
   r   r   r   pydanticr   r   r   mcp.client.streamable_httpr   mcp.shared.authr   r   r   r   r   mcp.shared.auth_utilsr   r   	mcp.typesr   	getLoggerr   r   r  r   r#   r%   r'   rK   rZ   Authr   r   r    r!   <module>r)     s       				    ? ? ? ? ? ? ? ? ? ? ( ( ( ( ( ( ( (       5 5 5 5 5 5 5 5 5 5   6 6 6 6 6 6 6 6 6 6 ; ; ; ; ; ;              W V V V V V V V - - - - - -		8	$	$0 0 0 0 0Y 0 0 0- - - - -n - - -1 1 1 1 1^ 1 1 1O O O O OY O O O    8   ( [0 [0 [0 [0 [0 [0 [0 [0|t t t t t%* t t t t tr    