o
    c۷i%/                  
   @   s   d dl Z d dlZd dl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 d dlmZ d dlmZmZmZmZmZ d dlmZ e eZd	ed
ededB fddZd	ededB fddZd	ededB fddZdedB dedee fddZ 	d7dedB dedB dedB dedB fddZ!dedB dedee fddZ"d	ededB fddZ#d	ede$e%edB f fd d!Z&d"edefd#d$Z'd%edB d&ed'edefd(d)Z(d	edefd*d+Z)d"edB de%fd,d-Z*d.edB d/edB de%fd0d1Z+	d7d/ed2ee	 dB defd3d4Z,d	edefd5d6Z-dS )8    N)urljoinurlparse)RequestResponse)AnyUrlValidationError)OAuthRegistrationErrorOAuthTokenError)MCP_PROTOCOL_VERSION)OAuthClientInformationFullOAuthClientMetadataOAuthMetadata
OAuthTokenProtectedResourceMetadata)LATEST_PROTOCOL_VERSIONresponse
field_namereturnc                 C   sF   | j d}|s
dS | d}t||}|r!|dp |dS dS )z
    Extract field from WWW-Authenticate header.

    Returns:
        Field value if found in WWW-Authenticate header, None otherwise
    zWWW-AuthenticateNz=(?:"([^"]+)"|([^\s,]+))      )headersgetresearchgroup)r   r   www_auth_headerpatternmatch r   K/home/ubuntu/vllm_env/lib/python3.10/site-packages/mcp/client/auth/utils.pyextract_field_from_www_auth   s   
r    c                 C   s
   t | dS )z
    Extract scope parameter from WWW-Authenticate header as per RFC6750.

    Returns:
        Scope string if found in WWW-Authenticate header, None otherwise
    scope)r    r   r   r   r   extract_scope_from_www_auth,   s   
r#   c                 C   s   | r| j dkr	dS t| 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
    i  Nresource_metadata)status_coder    r"   r   r   r   'extract_resource_metadata_from_www_auth6   s   
r&   www_auth_url
server_urlc                 C   sp   g }| r	| |  t|}|j d|j }|jr,|jdkr,t|d|j }| | t|d}| | |S )a;  
    Build ordered list of URLs to try for protected resource metadata discovery.

    Per SEP-985, the client MUST:
    1. Try resource_metadata from WWW-Authenticate header (if present)
    2. Fall back to path-based well-known URI: /.well-known/oauth-protected-resource/{path}
    3. Fall back to root-based well-known URI: /.well-known/oauth-protected-resource

    Args:
        www_auth_url: optional resource_metadata url extracted from the WWW-Authenticate header
        server_url: server url

    Returns:
        Ordered list of URLs to try for discovery
    :///z%/.well-known/oauth-protected-resource)appendr   schemenetlocpathr   )r'   r(   urlsparsedbase_urlpath_based_urlroot_based_urlr   r   r   0build_protected_resource_metadata_discovery_urlsC   s   



r4   www_authenticate_scopeprotected_resource_metadataauthorization_server_metadatac                 C   sL   | dur| S |dur|j durd|j S |dur$|j dur$d|j S dS )zLSelect scopes as outlined in the 'Scope Selection Strategy' in the MCP spec.N )scopes_supportedjoin)r5   r6   r7   r   r   r   get_client_metadata_scopesi   s   r;   auth_server_urlc                 C   s   | st |}|j d|j dgS g }t | }|j d|j }|jr]|jdkr]d|jd }|t|| d|jd }|t|| |jd d}|t|| |S |t|d |t|d |S )a  
    Generate ordered list of (url, type) tuples for discovery attempts.

    Args:
        auth_server_url: URL for the OAuth Authorization Metadata URL if found, otherwise None
        server_url: URL for the MCP server, used as a fallback if auth_server_url is None
    r)   z'/.well-known/oauth-authorization-serverr*   z!/.well-known/openid-configuration)r   r,   r-   r.   rstripr+   r   )r<   r(   r0   r/   r1   
oauth_path	oidc_pathr   r   r   8build_oauth_authorization_server_metadata_discovery_urls   s"   	r@   c                    sD   | j dkr z|  I dH }t|}|W S  ty   Y dS w dS )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
       N)r%   areadr   model_validate_jsonr   )r   contentmetadatar   r   r   "handle_protected_resource_response   s   

rF   c                    s`   | j dkr"z|  I d H }t|}d|fW S  ty!   Y dS w | j dk s,| j dkr.dS dS )NrA   T)TNi  i  )FN)r%   rB   r   rC   r   )r   rD   asmr   r   r   handle_auth_metadata_response   s   


rH   urlc                 C   s   t d| ttidS )NGET)r   )r   r
   r   )rI   r   r   r   create_oauth_metadata_request   s   rK   auth_server_metadataclient_metadataauth_base_urlc                 C   sD   | r| j rt| j }nt|d}|jdddd}td||ddidS )	z9Build registration request or skip if already registered.z	/registerTjson)by_aliasmodeexclude_nonePOSTzContent-Typezapplication/json)rO   r   )registration_endpointstrr   
model_dumpr   )rL   rM   rN   registration_urlregistration_datar   r   r   "create_client_registration_request   s
   

rY   c              
      sx   | j dvr|  I dH  td| j  d| j z|  I dH }t|}|W S  ty; } ztd| d}~ww )zHandle registration response.)rA      NzRegistration failed: r8   zInvalid registration response: )r%   rB   r   textr   rC   r   )r   rD   client_infoer   r   r   handle_registration_response   s   

r^   c                 C   s<   | sdS zt | }|jdko|jdvW S  ty   Y dS w )zValidate that a URL is suitable for use as a client_id (CIMD).

    The URL must be HTTPS with a non-root pathname.

    Args:
        url: The URL to validate

    Returns:
        True if the URL is a valid HTTPS URL with a non-root pathname
    Fhttps) r*   )r   r,   r.   	Exception)rI   r0   r   r   r   is_valid_client_metadata_url   s   rb   oauth_metadataclient_metadata_urlc                 C   s   |sdS | sdS | j du S )a  Determine if URL-based client ID (CIMD) should be used instead of DCR.

    URL-based client IDs should be used when:
    1. The server advertises client_id_metadata_document_supported=true
    2. The client has a valid client_metadata_url configured

    Args:
        oauth_metadata: OAuth authorization server metadata
        client_metadata_url: URL-based client ID (already validated)

    Returns:
        True if CIMD should be used, False if DCR should be used
    FT)%client_id_metadata_document_supported)rc   rd   r   r   r   should_use_client_metadata_url
  s
   
rf   redirect_urisc                 C   s   t | d|dS )a  Create client information using a URL-based client ID (CIMD).

    When using URL-based client IDs, the URL itself becomes the client_id
    and no client_secret is used (token_endpoint_auth_method="none").

    Args:
        client_metadata_url: The URL to use as the client_id
        redirect_uris: The redirect URIs from the client metadata (passed through for
            compatibility with OAuthClientInformationFull which inherits from OAuthClientMetadata)

    Returns:
        OAuthClientInformationFull with the URL as client_id
    none)	client_idtoken_endpoint_auth_methodrg   )r   )rd   rg   r   r   r   $create_client_info_from_metadata_url$  s
   rk   c              
      sH   z|   I dH }t|}|W S  ty# } ztd| d}~ww )av  Parse and validate token response with optional scope validation.

    Parses token response JSON. Callers should check response.status_code before calling.

    Args:
        response: HTTP response from token endpoint (status already checked by caller)

    Returns:
        Validated OAuthToken model

    Raises:
        OAuthTokenError: If response JSON is invalid
    NzInvalid token response: )rB   r   rC   r   r	   )r   rD   token_responser]   r   r   r   handle_token_response_scopes;  s   
rm   )N).loggingr   urllib.parser   r   httpxr   r   pydanticr   r   mcp.client.authr   r	   mcp.client.streamable_httpr
   mcp.shared.authr   r   r   r   r   	mcp.typesr   	getLogger__name__loggerrU   r    r#   r&   listr4   r;   r@   rF   tupleboolrH   rK   rY   r^   rb   rf   rk   rm   r   r   r   r   <module>   s~    

)
,




