
    kKj1r                       d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZmZ ddlmZ ddlm Z m!Z!m"Z"m#Z# ddl$m%Z% erddl&m'Z'  e%e(      Z)d"dZ* G d de      Z+ G d de,      Z- G d de,      Z.e	 G d d             Z/e	 G d d             Z0 G d d      Z1 G d d      Z2 G d  d!      Z3y)#a  CIMD (Client ID Metadata Document) support for FastMCP.

.. warning::
    **Beta Feature**: CIMD support is currently in beta. The API may change
    in future releases. Please report any issues you encounter.

CIMD is a simpler alternative to Dynamic Client Registration where clients
host a static JSON document at an HTTPS URL, and that URL becomes their
client_id. See the IETF draft: draft-parecki-oauth-client-id-metadata-document

This module provides:
- CIMDDocument: Pydantic model for CIMD document validation
- CIMDFetcher: Fetch and validate CIMD documents with SSRF protection
- CIMDClientManager: Manages CIMD client operations
    )annotationsN)Mapping)	dataclass)timezone)parsedate_to_datetime)TYPE_CHECKINGAnyLiteral)urlparse)jwk)	JoseError)
AnyHttpUrl	BaseModelFieldfield_validator)matches_allowed_pattern)	SSRFErrorSSRFFetchErrorssrf_safe_fetch_responsevalidate_url)
get_loggerJWTVerifierc                    | j                  d      }|dk(  r3t        j                  | d      j                         j	                  d      S |dk(  r3t        j                  | d      j                         j	                  d      S t        d|      )NktyRSAzutf-8ECzUnsupported JWK key type: )getr   
import_keyas_pemdecode
ValueError)key_datakey_types     i/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/server/auth/cimd.py_jwk_to_pemr&   0   s}    ||E"H5~~h.557>>wGG4~~h-446==gFF
1(>
??    c                  F   e Zd ZU dZ edd      Zded<    edd	      Zd
ed<    edd	      Zded<    edd	      Z	ded<    edd      Z
ded<    edd	      Zded<    ed d      Zded<    ed d      Zded<    edd	      Zd
ed <    edd!	      Zd"ed#<    edd$	      Zded%<    edd&	      Zded'<    edd(	      Zded)<    edd*	      Zd+ed,<    edd-	      Zd
ed.<    edd/	      Zd
ed0<    ed      ed3d1              Z ed      ed4d2              Zy)5CIMDDocumenta  CIMD document per draft-parecki-oauth-client-id-metadata-document.

    The client metadata document is a JSON document containing OAuth client
    metadata. The client_id property MUST match the URL where this document
    is hosted.

    Key constraint: token_endpoint_auth_method MUST NOT use shared secrets
    (client_secret_post, client_secret_basic, client_secret_jwt).

    redirect_uris is required and must contain at least one entry.
    .z0Must match the URL where this document is hosted)descriptionr   	client_idNz!Human-readable name of the client)defaultr*   
str | Noneclient_namezURL of the client's home pagezAnyHttpUrl | None
client_urizURL of the client's logo imagelogo_urizWArray of allowed redirect URIs (may include wildcards like http://localhost:*/callback)	list[str]redirect_urisnonezDAuthentication method for token endpoint (no shared secrets allowed)z"Literal['none', 'private_key_jwt']token_endpoint_auth_methodc                     dgS )Nauthorization_code r7   r'   r%   <lambda>zCIMDDocument.<lambda>_   s    !5 6r'   z%OAuth grant types the client will use)default_factoryr*   grant_typesc                     dgS )Ncoder7   r7   r'   r%   r8   zCIMDDocument.<lambda>c   s    r'   z(OAuth response types the client will useresponse_typesz5Space-separated list of scopes the client may requestscopez,Contact information for the client developerlist[str] | Nonecontactsz$URL of the client's terms of servicetos_uriz"URL of the client's privacy policy
policy_uriz:URL of the client's JSON Web Key Set (for private_key_jwt)jwks_uriz/Client's JSON Web Key Set (for private_key_jwt)zdict[str, Any] | Nonejwksz)Unique identifier for the client softwaresoftware_idzVersion of the client softwaresoftware_versionc                4    h d}||v rt        d| d      |S )z.Ensure no shared-secret auth methods are used.>   client_secret_jwtclient_secret_postclient_secret_basicz6CIMD documents cannot use shared-secret auth methods: z*. Use 'none' or 'private_key_jwt' instead.)r"   )clsv	forbiddens      r%   validate_auth_methodz!CIMDDocument.validate_auth_method   s7     W		>H L; ;  r'   c                
   |st        d      |D ]p  }|r|j                         st        d      t        |      }|j                  st        d|      |j                  rR|j                  d      rdt        d|       |S )z@Ensure redirect_uris is non-empty and each entry is a valid URI.z5CIMD documents must include at least one redirect_uriz,CIMD redirect_uris must be non-empty stringszACIMD redirect_uri must have a scheme (e.g. http:// or https://): zurn:z$CIMD redirect_uri must have a host: )r"   stripr   schemenetloc
startswith)rK   rL   uriparseds       r%   validate_redirect_urisz#CIMDDocument.validate_redirect_uris   s     TUUCciik !OPPc]F== WX[W^_  ==)? #Gw!OPP  r'   )rL   strreturnrW   )rL   r1   rX   r1   )__name__
__module____qualname____doc__r   r+   __annotations__r.   r/   r0   r2   r4   r:   r=   r>   r@   rA   rB   rC   rD   rE   rF   r   classmethodrN   rV   r7   r'   r%   r)   r)   9   s   
 "FIz  $7K  %*3%J!  #(4#H   %m M9  FKZF B  #6;K  !&(>!NI  KE:  "'B"H  "':"G  %*8%J!  #(P#H  #(E#D
  $?K  $)4$j 
 12  3 _%  &r'   r)   c                      e Zd ZdZy)CIMDValidationErrorz+Raised when CIMD document validation fails.NrY   rZ   r[   r\   r7   r'   r%   r`   r`      s    5r'   r`   c                      e Zd ZdZy)CIMDFetchErrorz)Raised when CIMD document fetching fails.Nra   r7   r'   r%   rc   rc      s    3r'   rc   c                  N    e Zd ZU dZded<   ded<   ded<   ded<   ded	<   d
ed<   y)_CIMDCacheEntryz8Cached CIMD document and associated HTTP cache metadata.r)   docr-   etaglast_modifiedfloat
expires_atfreshness_lifetimeboolmust_revalidateNrY   rZ   r[   r\   r]   r7   r'   r%   re   re      s)    B	
r'   re   c                  N    e Zd ZU dZded<   ded<   ded<   ded<   ded	<   ded
<   y)_CIMDCachePolicyz>Normalized cache directives parsed from HTTP response headers.r-   rg   rh   ri   rj   rk   rl   no_storerm   Nrn   r7   r'   r%   rp   rp      s(    H
Nr'   rp   c                  Z    e Zd ZdZdZdZ	 d	 ddZ	 	 	 	 	 	 ddZddZddZ	ddZ
dd	Zy
)CIMDFetcheras  Fetch and validate CIMD documents with SSRF protection.

    Delegates HTTP fetching to ssrf_safe_fetch_response, which provides DNS
    pinning, IP validation, size limits, and timeout enforcement. Documents are
    cached using HTTP caching semantics (Cache-Control/ETag/Last-Modified), with
    a TTL fallback when response headers do not define caching behavior.
    i   i  c                     || _         i | _        y)zxInitialize the CIMD fetcher.

        Args:
            timeout: HTTP request timeout in seconds (default 10.0)
        N)timeout_cache)selfru   s     r%   __init__zCIMDFetcher.__init__   s     24r'   c                   |j                         D ci c]  \  }}|j                         | }}}|j                  dd      }|j                  d      D ch c]1  }|j	                         s|j	                         j                         3 }}d|v }	d|v }
d}|D ]J  }|j                  d      s|j                  d      j	                         }	 t        dt        |            } n d}|||z   }nOd
|v rK	 t        |d
         }|j                   |j                  t        j                         }|j#                         }||| j&                  z   }t        d||z
        }t)        |j                  d      |j                  d      |||	|
      S c c}}w c c}w # t        $ r t        j                  d	|       Y w xY w# t$        t        f$ r t        j                  d|d
          Y w xY w)z3Parse HTTP cache headers and derive cache behavior.cache-control ,zno-storezno-cacheNzmax-age=r   z0Ignoring invalid Cache-Control max-age value: %sexpires)tzinfoz4Ignoring invalid Expires header on CIMD response: %sg        rg   zlast-modifiedrg   rh   rj   rk   rq   rm   )itemslowerr   splitrP   rS   removeprefixmaxintr"   loggerdebugr   r~   replacer   utc	timestamp	TypeErrorDEFAULT_CACHE_TTL_SECONDSrp   )rw   headersnowkrL   
normalizedcache_controlpart
directivesrq   rm   max_age	directivevaluerj   dtrk   s                    r%   _parse_cache_policyzCIMDFetcher._parse_cache_policy   s    07}}?tq!aggil
?";-:-@-@-E
-ETDJJL -E 	 
 +$
2"#I##J/!..z:@@B!!SZ0G
  $ $(
wJ*$	*:i+@A99$8<<8B\\^
 t===J j3&67'$..9!1+
 	
Q @
 " LLJE z* Jy)s6   FF- FF7A
G  F=<F= (G+*G+c                Z    |D ch c]  }|j                          }}d|v xs d|v S c c}w )z>Return True when response includes cache freshness directives.rz   r}   )r   )rw   r   r   r   s       r%   _has_freshness_headersz"CIMDFetcher._has_freshness_headers  s6    )01Aaggi
1*,G	Z0GG 2s   (c                    |sy	 t        |      }|j                  dk(  xr% t        |j                        xr |j                  dvS # t
        t        f$ r Y yw xY w)ztCheck if a client_id looks like a CIMD URL.

        CIMD URLs must be HTTPS with a host and non-root path.
        Fhttps)r{   /)r   rQ   rl   rR   pathr"   AttributeError)rw   r+   rU   s      r%   is_cimd_client_idzCIMDFetcher.is_cimd_client_id  se    
 	i(F( 1'1KKy0
 N+ 		s   A A AAc           	       K   | j                   j                  |      }t        j                         }d}dh}|e|j                  s||j                  k  r|j
                  S i }|j                  r|j                  |d<   |j                  r|j                  |d<   |rddh}	 t        |d| j                  | j                  d||       d{   }|j                   dk(  rA|t        d	      t        j                         }| j#                  |j$                        r| j'                  |j$                  |      }n2t)        dd||j*                  z   |j*                  d
|j                        }|j,                  st/        |j
                  |j                  xs |j                  |j                  xs |j                  |j                  |j*                  |j                        | j                   |<   |j
                  S | j                   j1                  |d       |j
                  S t        j                         }| j'                  |j$                  |      }	 t3        j4                  |j6                        }		 t:        j=                  |	      }
t        |
j@                        jC                  d      |jC                  d      k7  rt        d|
j@                   d| d      |
jD                  r)t        |
jD                        }	 tG        |       d{    tH        jK                  d||
jL                         |j,                  sRt/        |
|j                  |j                  |j                  |j*                  |j                        | j                   |<   |
S | j                   j1                  |d       |
S 7 # t        $ r}t        t        |            |d}~wt        $ r}t        t        |            |d}~ww xY w# t2        j8                  $ r}t        d|       |d}~ww xY w# t>        $ r}t        d|       |d}~ww xY w7 6# t        $ r}t        d|       |d}~ww xY ww)a  Fetch and validate a CIMD document with SSRF protection.

        Uses ssrf_safe_fetch_response for the HTTP layer, which provides:
        - HTTPS only, DNS resolution with IP validation
        - DNS pinning (connects to validated IP directly)
        - Blocks private/loopback/link-local/multicast IPs
        - Response size limit and timeout enforcement
        - Redirects disabled

        Args:
            client_id_url: The URL to fetch (also the expected client_id)

        Returns:
            Validated CIMDDocument

        Raises:
            CIMDValidationError: If document is invalid or URL blocked
            CIMDFetchError: If document cannot be fetched
        N   zIf-None-MatchzIf-Modified-Sincei0  Tg      >@)require_pathmax_sizeru   overall_timeoutrequest_headersallowed_status_codesz=CIMD server returned 304 Not Modified without cached documentFr   )rf   rg   rh   rj   rk   rm   z!CIMD document is not valid JSON: zInvalid CIMD document: r   z(CIMD client_id mismatch: document says 'z' but was fetched from ''z&CIMD jwks_uri failed SSRF validation: z8CIMD document fetched and validated: %s (client_name=%s))'rv   r   timerm   rj   rf   rg   rh   r   MAX_RESPONSE_SIZEru   r   r`   rW   r   rc   status_coder   r   r   rp   rk   rq   re   popjsonloadscontentJSONDecodeErrorr)   model_validate	Exceptionr+   rstriprC   r   r   infor.   )rw   client_id_urlcachedr   r   r   responseepolicydatarf   jwks_uri_strs               r%   fetchzCIMDFetcher.fetch+  s	    ( /iik15 #u))cF4E4E.Ezz! O{{39;;0##7=7K7K 34(+Sz$	05!// $ /%9 H 3&~$S  ))+C**8+;+;<11(2B2BCH *"&"V%>%>>'-'@'@"$*$:$: ??-<

3"("6"6"N&:N:N%00'-'@'@$*$:$:.M* :: t4::iik))(*:*:C@	V::h../D	L--d3C s}}$$S)]-A-A#-FF%:3==/ J))6q:  <<s||,L"<000 	FOO	
 )8[[$22!,,#)#<#< & 6 6*DKK& 
 KKOOM40
  	5%c!f-14 	0 Q(a/	0T ## 	V%(I!&MNTUU	V
  	L%(?s&CD!K	L 1 )<QC@s   BQ)N+ N(	N+ FQO2 /P A3Q8P? P<P? BQ(N+ +	O/4O		O/O**O//Q2PPPQ	P9%P44P99Q<P? ?	QQQQc                    |j                   sy|j                  d      }|j                   D ]!  }|j                  d      }t        ||      s! y y)u  Validate that a redirect_uri is allowed by the CIMD document.

        Uses component-level matching (scheme, host, port, path) which correctly
        handles RFC 8252 §7.3 loopback port flexibility and wildcard patterns.

        Args:
            doc: The CIMD document
            redirect_uri: The redirect URI to validate

        Returns:
            True if valid, False otherwise
        Fr   T)r2   r   r   )rw   rf   redirect_uriallowedallowed_strs        r%   validate_redirect_uriz!CIMDFetcher.validate_redirect_uri  sR        $**3/((G!..-K&|[A )
 r'   N)g      $@)ru   ri   )r   Mapping[str, str]r   ri   rX   rp   )r   r   rX   rl   r+   rW   rX   rl   )r   rW   rX   r)   )rf   r)   r   rW   rX   rl   )rY   rZ   r[   r\   r   r   rx   r   r   r   r   r   r7   r'   r%   rs   rs      s\      $ 
5
53
(3
/43
	3
jH
"ENr'   rs   c                  N    e Zd ZdZdZd Zd	dZd	dZ	 	 	 	 	 	 	 	 	 	 d
dZddZ	y)CIMDAssertionValidatora  Validates JWT assertions for private_key_jwt CIMD clients.

    Implements RFC 7523 (JSON Web Token (JWT) Profile for OAuth 2.0 Client
    Authentication and Authorization Grants) for CIMD client authentication.

    JTI replay protection uses TTL-based caching to ensure proper security:
    - JTIs are cached with expiration matching the JWT's exp claim
    - Expired JTIs are automatically cleaned up
    - Maximum assertion lifetime is enforced (5 minutes)
    i,  c                    i | _         d| _        t        j                         | _        d| _        i | _        d| _        t        t              | _
        y )Ni'  <   d   )
_jti_cache_jti_cache_max_sizer   	monotonic_last_cleanup_cleanup_interval_verifier_cache_verifier_cache_max_sizer   rY   r   )rw   s    r%   rx   zCIMDAssertionValidator.__init__  sF    ,.#( !^^-!# 8:(+% *r'   c                   t        j                          }| j                  j                         D cg c]  \  }}||k  s| }}}|D ]  }| j                  |=  |r&| j                  j	                  dt        |             yyc c}}w )zRemove expired JTIs from cache.z%Cleaned up %d expired JTIs from cacheN)r   r   r   r   r   len)rw   r   jtiexpexpireds        r%   _cleanup_expired_jtisz,CIMDAssertionValidator._cleanup_expired_jtis  sw    iik'+'<'<'>L'>83#)3'>LC$ KKEs7|T  Ms   B Bc                    t        j                         }|| j                  z
  | j                  kD  r| j	                          || _        yy)z>Periodically cleanup expired JTIs to prevent unbounded growth.N)r   r   r   r   r   )rw   r   s     r%   _maybe_cleanupz%CIMDAssertionValidator._maybe_cleanup  s@    nn###d&<&<<&&(!$D =r'   c                l  K   ddl m} | j                          |j                  rt	        |j                        }| d| d| }| j
                  j                  |      }| ||||d      }t        | j
                        | j                  k\  r+t        t        | j
                              }	| j
                  |	= || j
                  |<   n?|j                  r(| j                  ||j                        }
 ||
||      }nt        d      |j                  |       d{   }|st        d	      |j                  }t!        j                          }|j                  d
      }|j                  d      }|st        d      ||dz
  k  rt        d      |rD||dz   kD  rt        d      ||z
  | j"                  kD  rJt        d||z
   d| j"                   d      ||| j"                  z   kD  rt        d| j"                   d      |j                  d      |k7  rt        d|       |j                  d      }|st        d      || j$                  v r0| j$                  |   }||kD  rt        d| d      | j$                  |= || j$                  |<   t        | j$                        | j&                  kD  rc| j)                          t        | j$                        | j&                  kD  r1| j*                  j-                  d| j&                         t        d      | j*                  j/                  d|       y7 w)a  Validate JWT assertion from client.

        Args:
            assertion: The JWT assertion string
            client_id: Expected client_id (must match iss and sub claims)
            token_endpoint: Token endpoint URL (must match aud claim)
            cimd_doc: CIMD document containing JWKS for key verification

        Returns:
            True if valid

        Raises:
            ValueError: If validation fails
        r   r   |NT)rC   issueraudience	ssrf_safe)
public_keyr   r   z<CIMD document must have jwks_uri or jwks for private_key_jwtzInvalid JWT assertionr   iatz Assertion must include exp claim   zAssertion has expiredzAssertion iat is in the futurezAssertion lifetime too long: zs (max zs)z%Assertion exp too far in future (max subzAssertion sub claim must be r   z Assertion must include jti claimzAssertion replay detected: jti z already usedz/JTI cache at max capacity (%d), possible attackzServer overloaded, please retryz2JWT assertion validated successfully for client %s)!fastmcp.server.auth.providers.jwtr   r   rC   rW   r   r   r   r   nextiterrD   _extract_public_key_from_jwksr"   load_access_tokenclaimsr   MAX_ASSERTION_LIFETIMEr   r   r   r   warningr   )rw   	assertionr+   token_endpointcimd_doc_JWTVerifierr   	cache_keyverifier
oldest_keyr   access_tokenr   r   r   r   r   
cached_exps                     r%   validate_assertionz)CIMDAssertionValidator.validate_assertion  sB    * 	R 	 x001L'.)An5EFI++//	:H')$+"	 t++,0M0MM!%d4+?+?&@!AJ,,Z82:$$Y/]];;Ix}}UJ#% 'H N 
 &77	BB455$$ iikjjjj?@@ r>455 S2X~ !ABBSy4666 3C#I;gdFaFaEbbde 
 S46666 ;D<W<W;XXZ[ 
 ::e	);I;GHH jj?@@ $//!-JC #B3%}!UVV$  # t$":"::&&(4??#d&>&>>##E,, !!BCC@)	
 I Cs   DL4L1HL4c                   	 |j                  d      d   }|ddt        |      dz  z
  z  z  }t        j                  t	        j
                  |            }|j                  d      }|j                  dg       }|st        d	      d}|D ]  }	|s|	j                  d      |k(  s|	} n |s>t        |      d
k(  r!|d   }| j                  j                  d       nt        d| d      	 t        |      S # t        t        t        j                  f$ r}t        d|       |d}~ww xY w# t        t        t        f$ r}t        d|       |d}~ww xY w)a  Extract public key from inline JWKS.

        Args:
            token: JWT token to extract kid from
            jwks: JWKS document containing keys

        Returns:
            PEM-encoded public key

        Raises:
            ValueError: If key cannot be found or extracted
        .r   =   kidz%Failed to extract key ID from token: NkeyszJWKS document contains no keys   z3No matching kid in JWKS, using single available keyzNo matching key found for kid=z in JWKSzFailed to convert JWK to PEM: )r   r   r   r   base64urlsafe_b64decoder   
IndexErrorr"   r   r   r   r&   r   r   )
rw   tokenrD   
header_b64headerr   r   r   matching_keykeys
             r%   r   z4CIMDAssertionValidator._extract_public_key_from_jwksw  sd   	QS)!,J#S_q%8!899JZZ 8 8 DEF**U#C
 xx#=>>Cswwu~," 
 4yA~#Aw##I !#A#h!OPP	J|,,5 J(<(<= 	QDQCHIqP	Q6 9j1 	J=aSABI	Js0   A$C5 *
D* 5D'D""D'*E>EEN)rX   None)
r   rW   r+   rW   r   rW   r   r)   rX   rl   )r   rW   rD   dictrX   rW   )
rY   rZ   r[   r\   r   rx   r   r   r   r   r7   r'   r%   r   r     sa    	 !
+U%|| | 	|
 | 
||/Jr'   r   c                  N    e Zd ZdZ	 	 	 d	 	 	 	 	 ddZd	dZd
dZ	 	 	 	 	 	 ddZy)CIMDClientManageraW  Manages all CIMD client operations for OAuth proxy.

    This class encapsulates:
    - CIMD client detection
    - Document fetching and validation
    - Synthetic OAuth client creation
    - Private key JWT assertion validation

    This allows the OAuth proxy to delegate all CIMD-specific logic to a
    single, focused manager class.
    Nc                    || _         || _        || _        t               | _        t               | _        t        t              | _	        y)a!  Initialize CIMD client manager.

        Args:
            enable_cimd: Whether CIMD support is enabled
            default_scope: Default scope for CIMD clients if not specified in document
            allowed_redirect_uri_patterns: Allowed redirect URI patterns (proxy's config)
        N)
enableddefault_scopeallowed_redirect_uri_patternsrs   _fetcherr   _assertion_validatorr   rY   r   )rw   enable_cimdr  r	  s       r%   rx   zCIMDClientManager.__init__  s;     #*-J*#$:$<! *r'   c                T    | j                   xr | j                  j                  |      S )zCheck if client_id is a CIMD URL.

        Args:
            client_id: Client ID to check

        Returns:
            True if client_id is an HTTPS URL (CIMD format)
        )r  r
  r   )rw   r+   s     r%   r   z#CIMDClientManager.is_cimd_client_id  s"     ||J ? ?	 JJr'   c                  K   | j                   sy	 | j                  j                  |       d{   }ddlm} d} ||d||j                  |j                  xs | j                  |j                  | j                  |j                  |t        j                         
      }| j
                  j!                  d||j                         |S 7 # t        t        f$ r'}| j
                  j                  d||       Y d}~yd}~ww xY ww)a  Fetch CIMD document and create synthetic OAuth client.

        Args:
            client_id_url: HTTPS URL pointing to CIMD document

        Returns:
            OAuthProxyClient with CIMD document attached, or None if fetch fails

        Note:
            Return type is left untyped to avoid circular import with oauth_proxy.
            Returns OAuthProxyClient instance or None.
        NzCIMD fetch failed for %s: %sr   )ProxyDCRClient)
r+   client_secretr2   r:   r>   r4   r	  r.   cimd_documentcimd_fetched_atz"CIMD client resolved: %s (name=%s))r  r
  r   rc   r`   r   r   &fastmcp.server.auth.oauth_proxy.modelsr  r:   r>   r  r4   r	  r.   r   r   )rw   r   r   r   r  r2   clients          r%   
get_clientzCIMDClientManager.get_client  s      ||	!]]00??H 	J
 #' ,,..6D$6$6'/'J'J*.*L*L ,," IIK
 	0  	

 = @ 34 	KK >qQ	s>   DC C	C BD	C DC<7D<DDc                   K   t        |d      r|j                  st        d      |j                  }|j                  dk7  rt        d      | j                  j                  ||j                  ||       d{   S 7 w)a  Validate JWT assertion for private_key_jwt auth.

        Args:
            assertion: JWT assertion string from client
            client: OAuth proxy client (must have cimd_document)
            token_endpoint: Token endpoint URL for aud validation

        Returns:
            True if assertion is valid

        Raises:
            ValueError: If client doesn't have CIMD document or validation fails
        r  z2Client must have CIMD document for private_key_jwtprivate_key_jwtz6CIMD document must specify private_key_jwt auth methodN)hasattrr  r"   r4   r  r   r+   )rw   r   r  r   r   s        r%   validate_private_key_jwtz*CIMDClientManager.validate_private_key_jwt  s~     & v/v7K7KQRR''..2CCUVV..AAv''
 
 	
 
s   A5A>7A<8A>)Tr{   N)r  rl   r  rW   r	  r?   r   )r   rW   )r   rW   r   rW   rX   rl   )rY   rZ   r[   r\   rx   r   r  r  r7   r'   r%   r  r    s`    
 !:>	++ + (8	+*	K/b

 	

 

r'   r  )r#   zdict[str, Any]rX   rW   )4r\   
__future__r   r   r   r   collections.abcr   dataclassesr   datetimer   email.utilsr   typingr   r	   r
   urllib.parser   joserfcr   joserfc.errorsr   pydanticr   r   r   r   'fastmcp.server.auth.redirect_validationr   fastmcp.server.auth.ssrfr   r   r   r   fastmcp.utilities.loggingr   r   r   rY   r   r&   r)   r   r`   rc   re   rp   rs   r   r  r7   r'   r%   <module>r'     s     #    # !  - . . !  $ B B K  1=	H	@j9 jZ6) 64Y 4      E EPXJ XJvz
 z
r'   