
    )`ik                        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mZm	Z	m
Z
 ddlmZmZ ddlmZmZ ddlmZ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mZ dd	lm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. dd
l/m0Z0 ddl1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8m9Z9m:Z:  ej;        e<          Z= G d de          Z> G d de          Z?e G d d                      Z@ G d dejA                  ZBdS )z|
OAuth2 Authentication implementation for HTTPX.

Implements authorization code flow with PKCE and automatic token refresh.
    N)AsyncGenerator	AwaitableCallable)	dataclassfield)AnyProtocol)quote	urlencodeurljoinurlparse)	BaseModelFieldValidationError)OAuthFlowErrorOAuthTokenError)8build_oauth_authorization_server_metadata_discovery_urls0build_protected_resource_metadata_discovery_urls$create_client_info_from_metadata_url"create_client_registration_requestcreate_oauth_metadata_requestextract_field_from_www_auth'extract_resource_metadata_from_www_authextract_scope_from_www_authget_client_metadata_scopeshandle_auth_metadata_response"handle_protected_resource_responsehandle_registration_responsehandle_token_response_scopesis_valid_client_metadata_urlshould_use_client_metadata_url)MCP_PROTOCOL_VERSION)OAuthClientInformationFullOAuthClientMetadataOAuthMetadata
OAuthTokenProtectedResourceMetadata)calculate_token_expirycheck_resource_allowedresource_url_from_server_urlc                   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     j/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/mcp/client/auth/oauth2.py	<genexpr>z*PKCEParameters.generate.<locals>.<genexpr>B   s=      rrbcv/Cfm/SV\/\ ] ]rrrrrr    r.   =)r1   r2   )
joinrangehashlibsha256encodedigestbase64urlsafe_b64encodedecoderstrip)clsr1   rG   r2   s       r>   generatezPKCEParameters.generate?   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)r3   r,   )__name__
__module____qualname____doc__r   r1   str__annotations__r2   classmethodrM    r@   r>   r,   r,   9   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.r3   Nc                 
   K   dS )zGet stored tokens.NrU   selfs    r>   
get_tokenszTokenStorage.get_tokensK         r@   tokensc                 
   K   dS )zStore tokens.NrU   )rZ   r]   s     r>   
set_tokenszTokenStorage.set_tokensO   r\   r@   c                 
   K   dS )zGet stored client information.NrU   rY   s    r>   get_client_infozTokenStorage.get_client_infoS   r\   r@   client_infoc                 
   K   dS )zStore client information.NrU   )rZ   rb   s     r>   set_client_infozTokenStorage.set_client_infoW   r\   r@   )
rN   rO   rP   rQ   r&   r[   r_   r#   ra   rd   rU   r@   r>   rW   rW   H   s        55*t"3    z d    'AD'H    1K PT      r@   rW   c                   X   e Zd ZU dZeed<   eed<   eed<   eege	d         f         dz  ed<   eg e	e
eedz  f                  f         dz  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<   dZedz  ed<    eej                  Zej        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!de%eef         de%eef         dz  de
e%eef         e%eef         f         fdZ&dS )"OAuthContextzOAuth flow context.
server_urlclient_metadatastorageNredirect_handlercallback_handler     r@timeoutclient_metadata_urlprotected_resource_metadataoauth_metadataauth_server_urlprotocol_versionrb   current_tokenstoken_expiry_time)default_factorylockr3   c                 B    t          |          }|j         d|j         S )z,Extract base URL by removing path component.z://)r   schemenetloc)rZ   rg   parseds      r>   get_authorization_base_urlz'OAuthContext.get_authorization_base_urlx   s'    *%%-33FM333r@   tokenc                 8    t          |j                  | _        dS )z4Update token expiry time using shared util function.N)r(   
expires_inrt   )rZ   r|   s     r>   update_token_expiryz OAuthContext.update_token_expiry}   s    !78H!I!Ir@   c                     t          | j        o/| j        j        o#| j         pt	          j                    | j        k              S )z Check if current token is valid.)boolrs   access_tokenrt   timerY   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.)r   rs   refresh_tokenrb   rY   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)rs   rt   rY   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*   rg   ro   resourcerR   r)   )rZ   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)ro   )rZ   rr   s     r>   should_include_resource_paramz*OAuthContext.should_include_resource_param   s.     +74   	5  <//r@   dataheadersc                    |i }| j         s||fS | j         j        }|dk    r| j         j        r| j         j        rt	          | j         j        d          }t	          | j         j        d          }| d| }t          j        |                                                                          }d| |d<   d |	                                D             }n!|d	k    r| j         j        r| j         j        |d
<   ||fS )zPrepare authentication for token requests.

        Args:
            data: The form data to send
            headers: Optional headers dict to update

        Returns:
            Tuple of (updated_data, updated_headers)
        Nclient_secret_basicr5   )safe:zBasic Authorizationc                 &    i | ]\  }}|d k    ||S )client_secretrU   )r<   kvs      r>   
<dictcomp>z3OAuthContext.prepare_token_auth.<locals>.<dictcomp>   s(    JJJTQQ/5I5IAq5I5I5Ir@   client_secret_postr   )
rb   token_endpoint_auth_method	client_idr   r
   rH   	b64encoderF   rJ   items)rZ   r   r   auth_method
encoded_idencoded_secretcredentialsencoded_credentialss           r>   prepare_token_authzOAuthContext.prepare_token_auth   s     ?G 	!= &A///D4D4N/SWScSq/t/9CCCJ"4#3#AKKKN'::.::K"("2;3E3E3G3G"H"H"O"O"Q"Q'E0C'E'EGO$JJTZZ\\JJJDD000T5E5S0$($4$BD! W}r@   r3   NN)'rN   rO   rP   rQ   rR   rS   r$   rW   r   r   tuplerm   floatrn   ro   r'   rp   r%   rq   rr   rb   r#   rs   r&   rt   r   anyioLockrv   r{   r   r   r   r   r   r   r   dictr   rU   r@   r>   rf   rf   \   s        OOO((((uio56====r9U3d
?-C#DDELLLLGU&*t*** 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4S 4S 4 4 4 4
J J J J J J
 
 
 
 
d4 d d d d& & & &
#    0 0cDj 0TX 0 0 0 0( FJ" "cN"-1#s(^d-B"	tCH~tCH~-	." " " " " "r@   rf   c                       e Zd ZdZdZ	 	 	 	 d dedededeege	d         f         dz  d	eg e	e
eedz  f                  f         dz  d
ededz  fdZdej        defdZdej        fdZde
eef         fdZdefdZi ddededeeef         dz  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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.
    TNrl   rg   rh   ri   rj   rk   rm   rn   c           	          |!t          |          st          d|           t          |||||||          | _        d| _        dS )al  Initialize OAuth2 authentication.

        Args:
            server_url: The MCP server URL.
            client_metadata: OAuth client metadata for registration.
            storage: Token storage implementation.
            redirect_handler: Handler for authorization redirects.
            callback_handler: Handler for authorization callbacks.
            timeout: Timeout for the OAuth flow.
            client_metadata_url: URL-based client ID. When provided and the server
                advertises client_id_metadata_document_supported=true, this URL will be
                used as the client_id instead of performing dynamic client registration.
                Must be a valid HTTPS URL with a non-root pathname.

        Raises:
            ValueError: If client_metadata_url is provided but not a valid HTTPS URL
                with a non-root pathname.
        NzMclient_metadata_url must be a valid HTTPS URL with a non-root pathname, got: )rg   rh   ri   rj   rk   rm   rn   F)r    
ValueErrorrf   context_initialized)rZ   rg   rh   ri   rj   rk   rm   rn   s           r>   __init__zOAuthClientProvider.__init__   st    : *3OPc3d3d*u`suu   $!+-- 3
 
 
 "r@   responser3   c                   K   |j         dk    r	 |                                 d{V }t          j        |          }|| j        _        |j        r$t          |j        d                   | j        _        dS # t          $ r+ t                              d|j        j                    Y dS w xY w|j         dk    r*t                              d|j        j         d	           dS t          d
|j                    )z
        Handle protected resource metadata discovery response.

        Per SEP-985, supports fallback when discovery fails at one URL.

        Returns:
            True if metadata was successfully discovered, False if we should try next URL
           Nr   Tz'Invalid protected resource metadata at Fi  z)Protected resource metadata not found at z, trying next URLz,Protected Resource Metadata request failed: )status_codeareadr'   model_validate_jsonr   ro   authorization_serversrR   rq   r   loggerwarningrequesturldebugr   rZ   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t"   _IYI]__```uu !S((LLlXEUEYlllmmm5 !Ux?SUU  s   A%A6 61B+*B+c                 |   K   |                                   d{V \  }}|                     ||           d{V }|S )zPerform the authorization flow.N)!_perform_authorization_code_grant"_exchange_token_authorization_code)rZ   	auth_coder1   token_requests       r>   _perform_authorizationz*OAuthClientProvider._perform_authorization.  s\      )-)O)O)Q)Q#Q#Q#Q#Q#Q#Q 	="EEiQ^________r@   c                   K   | j         j        j        t          d          | 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          }| 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.N6No redirect URIs provided for authorization code grantz9No redirect handler provided for authorization code grantz9No callback handler provided for authorization code grantz
/authorizez*No client info available for authorization    coder   S256)response_typer   redirect_uristater2   code_challenge_methodr   scope?zState parameter mismatch: z != zNo authorization code received)r   rh   redirect_urisr   rj   rk   rp   authorization_endpointrR   r{   rg   r   rb   r,   rM   r7   token_urlsafer   r2   r   rr   r   r   r   compare_digestr1   )	rZ   auth_endpointauth_base_urlpkce_paramsr   auth_paramsauthorization_urlr   returned_states	            r>   r   z5OAuthClientProvider._perform_authorization_code_grant4  sh     <'5= !YZZZ|, 	^ !\]]]|, 	^ !\]]]<& 	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@   c                     | j         j        r0| j         j        j        rt          | j         j        j                  }n4| j                             | j         j                  }t          |d          }|S )N/token)r   rp   token_endpointrR   r{   rg   r   )rZ   	token_urlr   s      r>   _get_token_endpointz'OAuthClientProvider._get_token_endpointi  sd    <& 	94<+F+U 	9DL7FGGII LCCDLD[\\Mx88Ir@   )
token_datar   r1   r   c                8  K   | j         j        j        t          d          | j         j        st          d          |                                 }|pi }|                    d|t          | j         j        j        d                   | j         j        j        |d           | j         	                    | j         j
                  r| j                                         |d<   dd	i}| j                             ||          \  }}t          j        d
|||          S )z9Build token exchange request for authorization_code flow.Nr   zMissing client infoauthorization_coder   )
grant_typer   r   r   r1   r   Content-Type!application/x-www-form-urlencodedPOSTr   r   )r   rh   r   r   rb   r   updaterR   r   r   rr   r   r   httpxRequest)rZ   r   r1   r   r   r   s         r>   r   z6OAuthClientProvider._exchange_token_authorization_codeq  s$      <'5= !YZZZ|' 	8 !6777,,..	%2
2! #DL$@$Nq$Q R R!\5?!. 	
 	
 	
 <55dl6STT 	E%)\%B%B%D%DJz" "#FG"l==j'RR
G}VYZQQQQr@   c                 r  K   |j         dk    rI|                                 d{V }|                    d          }t          d|j          d|           t	          |           d{V }|| j        _        | j                            |           | j        j        	                    |           d{V  dS )zHandle token exchange response.r   Nzutf-8zToken exchange failed (z): )
r   r   rJ   r   r   r   rs   r   ri   r_   )rZ   r   body	body_texttoken_responses        r>   _handle_token_responsez*OAuthClientProvider._handle_token_response  s      3&&!))))))))DG,,I!"`H<P"`"`U^"`"`aaa  <HEEEEEEEE '5#((888l"--n===========r@   c                   K   | j         j        r| j         j        j        st          d          | j         j        r| j         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<   ddi}| j                             ||          \  }}t!          j        d	|||
          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   rs   r   r   rb   r   rp   r   rR   r{   rg   r   r   rr   r   r   r   r   )rZ   r   r   refresh_datar   s        r>   _refresh_tokenz"OAuthClientProvider._refresh_token  s[     |* 	@$,2M2[ 	@!">???|' 	>t|/G/Q 	>!"<===<& 	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$ "#FG $ ? ?g V Vg}VY\7SSSSr@   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   r   r   r   r   r   r&   r   rs   r   ri   r_   r   	exception)rZ   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   ri   r[   rs   ra   rb   r   rY   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@   r   c                     | 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 r   N)r   rs   r   r   )rZ   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@   c                 ~   K   |                                  d {V }t          j        |          }|| j        _        d S r   )r   r%   r   r   rp   r   s       r>   _handle_oauth_metadata_responsez3OAuthClientProvider._handle_oauth_metadata_response  sG       (((((((( 4W==&.###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    rO	 t          |          }t          || j         j                  }|D ]}t#          |          }|W V }	t%          |	           d{V }
|
rL|
| j         _        t)          |
j                  dk    sJ t-          |
j        d                   | j         _         nt0                              d|            t5          | j         j        | j         j                  }|D ]a}t#          |          }|W V }t7          |           d{V \  }}|s n0|r|r|| j         _         nt0                              d|            bt;          t=          |          | j         j        | j         j                  | j         j        _         | j         j!        s9tE          | j         j        | j         j#                  rt0                              d| j         j#                    tI          | j         j#        | j         j        j%                  }|| j         _!        | j         j&        '                    |           d{V  ntQ          | j         j        | j         j        | j         )                    | j         j                            }|W V }tU          |           d{V }|| j         _!        | j         j&        '                    |           d{V  | +                                 d{V W V }| ,                    |           d{V  n)# tZ          $ r t0          .                    d	            w xY w|                     |           |W V  n|j        d
k    rt_          |d          }|dk    r	 t;          t=          |          | j         j                  | j         j        _         | +                                 d{V W V }| ,                    |           d{V  n)# tZ          $ r t0          .                    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.NFi  r   z.Protected resource metadata discovery failed: z!OAuth metadata discovery failed: z"Using URL-based client ID (CIMD): )r   zOAuth flow errori  errorinsufficient_scope)0r   rv   r   r   r   getr"   rr   r   r   r   r   r   r   r   r   rg   r   r   ro   lenr   rR   rq   r   r   r   r   rp   r   r   rh   r   rb   r!   rn   r   r   ri   rd   r   r{   r   r   r   	Exceptionr   r   )rZ   r   refresh_requestrefresh_responser   www_auth_resource_metadata_urlprm_discovery_urlsr   discovery_requestdiscovery_responseprmasm_discovery_urlsoauth_metadata_requestoauth_metadata_responseokasmclient_informationregistration_requestregistration_responser   r  s                        r>   async_auth_flowz#OAuthClientProvider.async_auth_flow  s     <$ D	 D	 D	 D	 D	 D	 D	 D	$ )&&((((((((( -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**S5\]e5f5f2 *Z68O* *&  2 a a,I#,N,N)3D-D-D-D*$FGY$Z$ZZZZZZZ aGJDLD !$C$= > > B B B B <?s?XYZ?[;\;\DL8!E"LL)_Z])_)_````)a4dl6M* *&
  2 T T1Ns1S1S.8N2N2N2N/(EF](^(^"^"^"^"^"^"^C! "!E T# T:=DL7!E"LL)RS)R)RSSSS :T3H==@3: :DL06  <3 [9 L79Y  [ #LL)pdlNn)p)pqqq1U $ @.2l.J.X2 2 2. 8JDL4"&,"6"F"FGY"Z"ZZZZZZZZZ 4V $ ; $ < $ G GH_ ` `4 40
 ;O4N4N4N17STi7j7j1j1j1j1j1j1j.7IDL4"&,"6"F"FGY"Z"ZZZZZZZZ 261L1L1N1N+N+N+N+N+N+N%N%N%NN55nEEEEEEEEEE    $$%7888
 %%g...%,,3HgFF 000=W7AA4<Ck> >4:
 6:5P5P5R5R/R/R/R/R/R/R)R)R)R"99.IIIIIIIIII$   (();<<<
 %%g...ID	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	 D	sD   C=UL	PU&Q?UA.S21U2&TU
UU)NNrl   Nr   ) rN   rO   rP   rQ   requires_response_bodyrR   r$   rW   r   r   r   r   r   r   Responser   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  rU   r@   r>   r   r      s        
 " EISW*.+" +"+" -+" 	+"
 #C5)D/#9:TA+" #2ysC$J1G'H#HIDP+" +" !4Z+" +" +" +"Z%. UY    @em    34sCx 34 34 34 34jS     Z\R R RR-0RAEc3hRVAVR	R R R R>>U^ > > > > >Tem T T T T<u~ $    *! ! ! !d d$ d d d d
/en /QU / / / /
FU] F~em]b]kNk?l F F F F F Fr@   r   )CrQ   rH   rD   loggingr7   r9   r   collections.abcr   r   r   dataclassesr   r   typingr   r	   urllib.parser
   r   r   r   r   r   pydanticr   r   r   mcp.client.auth.exceptionsr   r   mcp.client.auth.utilsr   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   mcp.client.streamable_httpr"   mcp.shared.authr#   r$   r%   r&   r'   mcp.shared.auth_utilsr(   r)   r*   	getLoggerrN   r   r,   rW   rf   Authr   rU   r@   r>   <module>r(     s$          ? ? ? ? ? ? ? ? ? ? ( ( ( ( ( ( ( (                 < < < < < < < < < < < <   6 6 6 6 6 6 6 6 6 6 F F F F F F F F                                 " < ; ; ; ; ;                       
	8	$	$O O O O OY O O O    8   ( y y y y y y y yxO O O O O%* O O O O Or@   