Ë
    Í—Äj_3  ã                  ó
  — d dl m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 d dlmZ d dlmZ d dlmZmZ d dlmZ dd	lmZmZ dd
lmZ ddlmZmZ ddlmZ  G d„ de	j@                  jB                  «      Z" G d„ d«      Z#y)é    )ÚannotationsN)Ú	lru_cache)Ú
SSLContext)ÚAny)Ú	HTTPErrorÚURLError)Úurlparseé   )ÚPyJWKÚPyJWKSet)Údecode_complete)ÚPyJWKClientConnectionErrorÚPyJWKClientError)ÚJWKSetCachec                  ó0   — e Zd Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zy)Ú_NoRedirectHandlerc                 ó   — y )N© )ÚselfÚreqÚfpÚcodeÚmsgÚheadersÚnewurls          úTC:\Users\pivot\Documents\cueki\casual-preloader\Lib\site-packages\jwt/jwks_client.pyÚredirect_requestz#_NoRedirectHandler.redirect_request   s   € ð ó    N)r   zurllib.request.Requestr   r   r   Úintr   Ústrr   r   r   r    Úreturnzurllib.request.Request | None)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r      sK   „ ð	à#ð	ð ð	ð ð		ð
 ð	ð ð	ð ð	ð 
'ô	r   r   c                  óª   — e Zd Z	 	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Zddd„Zedd„«       Zddd„Zedd„«       Z	dd„Z
dd	„Zedd
„«       Zy)ÚPyJWKClientNc
                ó$  — |€i }t        |«      j                  j                  «       }
|
dvrt        d|
›d�«      ‚|| _        d| _        || _        || _        || _        |	dk  rt        d|	› d�«      ‚t        j                  |	«      st        d|	› d�«      ‚|	| _        d| _        t        j                  «       | _        |r%|dk  rt        d	|› d�«      ‚t!        |«      | _        nd| _        |r$ t#        |¬
«      | j$                  «      }|| _        yy)u$
  A client for retrieving signing keys from a JWKS endpoint.

        ``PyJWKClient`` uses a two-tier caching system to avoid unnecessary
        network requests:

        **Tier 1 â€” JWK Set cache** (enabled by default):
        Caches the entire JSON Web Key Set response from the endpoint.
        Controlled by:

        - ``cache_jwk_set``: Set to ``True`` (the default) to enable this
          cache. When enabled, the JWK Set is fetched from the network only
          when the cache is empty or expired.
        - ``lifespan``: Time in seconds before the cached JWK Set expires.
          Defaults to ``300`` (5 minutes). Must be greater than 0.

        Unknown key IDs can trigger one forced refresh after the cooldown
        period configured by ``cooldown_duration``. Every successful fetch
        starts this cooldown, including the initial fetch and cache-expiry
        fetches. A newly rotated key may therefore wait for the cooldown
        period before it is fetched; set ``cooldown_duration`` to ``0`` to
        disable this behavior. The cooldown is bypassed when
        ``cache_jwk_set`` is ``False``.

        **Tier 2 â€” Signing key cache** (disabled by default):
        Caches individual signing keys (looked up by ``kid``) using an LRU
        cache with **no time-based expiration**. Keys are evicted only when
        the cache reaches its maximum size. Controlled by:

        - ``cache_keys``: Set to ``True`` to enable this cache.
          Defaults to ``False``.
        - ``max_cached_keys``: Maximum number of signing keys to keep in
          the LRU cache. Defaults to ``16``.

        :param uri: The URL of the JWKS endpoint.
        :type uri: str
        :param cache_keys: Enable the per-key LRU cache (Tier 2).
        :type cache_keys: bool
        :param max_cached_keys: Max entries in the signing key LRU cache.
        :type max_cached_keys: int
        :param cache_jwk_set: Enable the JWK Set response cache (Tier 1).
        :type cache_jwk_set: bool
        :param lifespan: TTL in seconds for the JWK Set cache.
        :type lifespan: float
        :param headers: Optional HTTP headers to include in requests.
        :type headers: dict or None
        :param timeout: HTTP request timeout in seconds.
        :type timeout: float
        :param ssl_context: Optional SSL context for the request.
        :type ssl_context: ssl.SSLContext or None
        :param cooldown_duration: Minimum time in seconds between forced
            refreshes after an unknown key ID. Defaults to ``30``.
        :type cooldown_duration: float
        N)ÚhttpÚhttpszInvalid JWKS URI scheme z(: only 'http' and 'https' are supported.r   zDCooldown duration must be greater than or equal to 0, the input is "Ú"z0Cooldown duration must be finite, the input is "z/Lifespan must be greater than 0, the input is ")Úmaxsize)r	   ÚschemeÚlowerr   ÚuriÚjwk_set_cacher   ÚtimeoutÚssl_contextÚmathÚisfiniteÚcooldown_durationÚ_last_successful_fetchÚ	threadingÚRLockÚ_client_lockr   r   Úget_signing_key)r   r.   Ú
cache_keysÚmax_cached_keysÚcache_jwk_setÚlifespanr   r0   r1   r4   r,   r9   s               r   Ú__init__zPyJWKClient.__init__#   sM  € ðB ˆ?ØˆGô
 ˜#“×%Ñ%×+Ñ+Ó-ˆØÐ*Ñ*Ü"Ø*¨6¨*ð 5!ð "óð ð ˆŒØ15ˆÔØˆŒØˆŒØ&ˆÔØ˜qÒ Ü"ð!Ø!2Ð 3°1ð6óð ô �}‰}Ð.Ô/Ü"ØBÐCTÐBUÐUVÐWóð ð "3ˆÔØ48ˆÔ#Ü%ŸO™OÓ-ˆÔáð ˜1Š}Ü&ØEÀhÀZÈqÐQóð ô "-¨XÓ!6ˆDÕà!%ˆDÔáà@œi°Ô@À×AUÑAUÓVˆOà#2ˆDÕ ð	 r   c                ó:  — 	 t         j                  j                  | j                  | j                  ¬«      }t        «       g}| j                  �9|j                  t         j                  j                  | j                  ¬«      «       t        j                  j                  |Ž }|j                  || j                  ¬«      5 }t        j                  |«      }ddd«       | j/                  «      }| j0                  �| j0                  j3                  |«       t5        j6                  «       | _        |S # 1 sw Y   Œ\xY w# t        t        t         j"                  j$                  f$ r5}t'        |t(        «      r|j+                  «        t-        d|› d�«      |‚d}~ww xY w)a7  Fetch the JWK Set from the JWKS endpoint.

        Makes an HTTP request to the configured ``uri`` and returns the
        parsed JSON response. If the JWK Set cache is enabled, the
        response is stored in the cache.

        :returns: The parsed JWK Set as a dictionary.
        :raises PyJWKClientConnectionError: If the HTTP request fails.
        :raises PyJWKClientError: If the endpoint does not return a JSON
            object.
        :raises PyJWKSetError: If the JWK Set cache is enabled and the
            response contains no usable keys.
        )Úurlr   N)Úcontext)r0   z'Fail to fetch data from the url, err: "r*   )ÚurllibÚrequestÚRequestr.   r   r   r1   ÚappendÚHTTPSHandlerÚbuild_openerÚopenr0   ÚjsonÚloadr   ÚTimeoutErrorr(   ÚclientÚHTTPExceptionÚ
isinstancer   Úcloser   Ú_as_jwk_set_payloadr/   ÚputÚtimeÚ	monotonicr5   )r   ÚrÚhandlersÚopenerÚresponseÚjwk_setÚes          r   Ú
fetch_datazPyJWKClient.fetch_data“   s@  € ð	Ü—‘×&Ñ&¨4¯8©8¸T¿\¹\Ð&ÓJˆAÜ#5Ó#7Ð"8ˆHØ×ÑÐ+Ø—‘¤§¡× ;Ñ ;ÀD×DTÑDTÐ ;Ó UÔVÜ—^‘^×0Ñ0°(Ð;ˆFØ—‘˜Q¨¯©�Ô5¸ÜŸ)™) HÓ-�÷ 6ð ×*Ñ*¨7Ó3ˆð ×ÑÐ)Ø×Ñ×"Ñ" 7Ô+Ü&*§n¡nÓ&6ˆÔ#Øˆ÷+ 6Ð5ûäœ,¬¯©×(AÑ(AÐBò 	Ü˜!œYÔ'Ø—‘”	Ü,Ø9¸!¸¸AÐ>óàðûð	ús0   ‚B>D= Ã D1ÃD= Ä1D:Ä6D= Ä=(FÅ%0FÆFc                óF  — d}d}| j                   �|s| j                   j                  «       }|€| j                  «       }d}t        |t        «      r|}n$t	        j
                  | j                  |«      «      }|r'| j                   �| j                   j                  |«       |S )aN  Return the JWK Set, using the cache when available.

        :param refresh: Force a fresh fetch from the endpoint, bypassing
            the cache.
        :type refresh: bool
        :returns: The JWK Set.
        :rtype: PyJWKSet
        :raises PyJWKClientError: If the endpoint does not return a JSON
            object.
        NFT)r/   ÚgetrZ   rN   r   Ú	from_dictrP   rQ   )r   ÚrefreshÚdataÚfetchedrX   s        r   Úget_jwk_setzPyJWKClient.get_jwk_set¾   s›   € ð ˆØˆØ×ÑÐ)±'Ø×%Ñ%×)Ñ)Ó+ˆDàˆ<Ø—?‘?Ó$ˆDØˆGô
 �dœHÔ%Ø‰Gä×(Ñ(¨×)AÑ)AÀ$Ó)GÓHˆGñ �t×)Ñ)Ð5Ø×Ñ×"Ñ" 7Ô+àˆr   c                ó<   — t        | t        «      st        d«      ‚| S )Nz.The JWKS endpoint did not return a JSON object)rN   Údictr   )r_   s    r   rP   zPyJWKClient._as_jwk_set_payloadã   s   € ä˜$¤Ô%Ü"Ð#SÓTÐTàˆr   c                óF   — | j                  |«      }| j                  |«      S )a§  Return all signing keys from the JWK Set.

        Filters the JWK Set to keys whose ``use`` is ``"sig"`` (or
        unspecified) and that have a ``kid``.

        :param refresh: Force a fresh fetch from the endpoint, bypassing
            the cache.
        :type refresh: bool
        :returns: A list of signing keys.
        :rtype: list[PyJWK]
        :raises PyJWKClientError: If no signing keys are found.
        )ra   Ú_get_signing_keys_from_jwk_set)r   r^   rX   s      r   Úget_signing_keyszPyJWKClient.get_signing_keysê   s%   € ð ×"Ñ" 7Ó+ˆØ×2Ñ2°7Ó;Ð;r   c                ó�   — | j                   D �cg c]  }|j                  dv r|j                  r|‘Œ  }}|st        d«      ‚|S c c}w )N)ÚsigNz2The JWKS endpoint did not contain any signing keys)ÚkeysÚpublic_key_useÚkey_idr   )rX   Újwk_set_keyÚsigning_keyss      r   re   z*PyJWKClient._get_signing_keys_from_jwk_setú   sZ   € ð  'Ÿ|š|ó
á+�Ø×)Ñ)¨]Ñ:¸{×?QÒ?Qò Ø+ð 	ð 
ñ Ü"Ð#WÓXÐXàÐùò
s   �#Ac                óÎ  — | j                   5  | j                  «       }| j                  ||«      }|sž| j                  duxr> | j                  duxr. t        j                  «       | j                  z
  | j                  k  }|s=| j                  d¬«      }t        j                  «       | _        | j                  ||«      }|st        d|› d�«      ‚|cddd«       S # 1 sw Y   yxY w)aÎ  Return the signing key matching the given ``kid``.

        If no match is found in the current JWK Set, the set is refreshed
        from the endpoint and the lookup is retried once when the refresh
        cooldown permits it.

        :param kid: The key ID to look up.
        :type kid: str
        :returns: The matching signing key.
        :rtype: PyJWK
        :raises PyJWKClientError: If no matching key is found after
            refreshing.
        NT)r^   z,Unable to find a signing key that matches: "r*   )	r8   rf   Ú	match_kidr/   r5   rR   rS   r4   r   )r   Úkidrm   Úsigning_keyÚcooling_downs        r   r9   zPyJWKClient.get_signing_key  sà   € ð ×ÓØ×0Ñ0Ó2ˆLØŸ.™.¨°sÓ;ˆKáà×&Ñ&¨dÐ2ò -Ø×3Ñ3¸4Ð?ò-äŸ™Ó(¨4×+FÑ+FÑFØ×,Ñ,ñ-ð ñ $Ø#'×#8Ñ#8ÀÐ#8Ó#F�LÜ26·.±.Ó2B�DÔ/Ø"&§.¡.°¸sÓ"C�Ká"Ü*ØFÀsÀeÈ1ÐMóð ð ÷+ ×Òús   �CCÃC$c                ój   — t        |ddi¬«      }|d   }| j                  |j                  d«      «      S )aG  Return the signing key for a JWT by reading its ``kid`` header.

        Extracts the ``kid`` from the token's unverified header and
        delegates to :meth:`get_signing_key`.

        :param token: The encoded JWT.
        :type token: str or bytes
        :returns: The matching signing key.
        :rtype: PyJWK
        Úverify_signatureF)ÚoptionsÚheaderrp   )Údecode_tokenr9   r\   )r   ÚtokenÚ
unverifiedrv   s       r   Úget_signing_key_from_jwtz$PyJWKClient.get_signing_key_from_jwt,  s:   € ô " %Ð2DÀeÐ1LÔMˆ
Ø˜HÑ%ˆØ×#Ñ# F§J¡J¨uÓ$5Ó6Ð6r   c                ó@   — d}| D ]  }|j                   |k(  sŒ|} |S  |S )a7  Find a key in *signing_keys* that matches *kid*.

        :param signing_keys: The list of keys to search.
        :type signing_keys: list[PyJWK]
        :param kid: The key ID to match.
        :type kid: str
        :returns: The matching key, or ``None`` if not found.
        :rtype: PyJWK or None
        N)rk   )rm   rp   rq   Úkeys       r   ro   zPyJWKClient.match_kid;  s5   € ð ˆãˆCØ�z‰z˜SÓ Ø!�ØàÐð  ð
 Ðr   )Fé   Ti,  Né   Nr~   )r.   r    r:   Úboolr;   r   r<   r   r=   Úfloatr   zdict[str, Any] | Noner0   r€   r1   zSSLContext | Noner4   r€   )r!   r   )F)r^   r   r!   r   )r_   r   r!   zdict[str, Any])r^   r   r!   úlist[PyJWK])rX   r   r!   r�   )rp   r    r!   r   )rx   zstr | bytesr!   r   )rm   r�   rp   r    r!   zPyJWK | None)r"   r#   r$   r>   rZ   ra   ÚstaticmethodrP   rf   re   r9   rz   ro   r   r   r   r&   r&   "   sÜ   „ ð !Ø!Ø"ØØ)-ØØ)-Ø#%ðn3àðn3ð ðn3ð ð	n3ð
 ðn3ð ðn3ð 'ðn3ð ðn3ð 'ðn3ð !ón3ó`)ôV#ðJ òó ðô<ð  ò
ó ð
ó#óJ7ð òó ñr   r&   )$Ú
__future__r   Úhttp.clientr(   rI   r2   r6   rR   Úurllib.requestrB   Ú	functoolsr   Ússlr   Útypingr   Úurllib.errorr   r   Úurllib.parser	   Úapi_jwkr   r   Úapi_jwtr   rw   Ú
exceptionsr   r   r/   r   rC   ÚHTTPRedirectHandlerr   r&   r   r   r   Ú<module>r�      sW   ðÝ "ã Û Û Û Û Û Ý Ý Ý ß ,Ý !ç $Ý 4ß DÝ &ô
˜Ÿ™×;Ñ;ô 
÷kò kr   