
    k7i                     r    S r SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSK	J
r
  SS	KJr   " S
 S\
5      rg)zauthlib.oauth2.rfc9068.token_validator.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Implementation of Validating JWT Access Tokens per `Section 4`_.

.. _`Section 7`: https://www.rfc-editor.org/rfc/rfc9068.html#name-validating-jwt-access-token
    )jwt)DecodeError)	JoseError)InsufficientScopeError)InvalidTokenError)BearerTokenValidator   )JWTAccessTokenClaimsc                   V   ^  \ rS rSrSrU 4S jrS rSSS\4S jrS	 r	 SS
 jr
SrU =r$ )JWTBearerTokenValidator   a  JWTBearerTokenValidator can protect your resource server endpoints.

:param issuer: The issuer from which tokens will be accepted.
:param resource_server: An identifier for the current resource server,
    which must appear in the JWT ``aud`` claim.

Developers needs to implement the missing methods::

    class MyJWTBearerTokenValidator(JWTBearerTokenValidator):
        def get_jwks(self): ...


    require_oauth = ResourceProtector()
    require_oauth.register_token_validator(
        MyJWTBearerTokenValidator(
            issuer="https://authorization-server.example.org",
            resource_server="https://resource-server.example.org",
        )
    )

You can then protect resources depending on the JWT `scope`, `groups`,
`roles` or `entitlements` claims::

    @require_oauth(
        scope="profile",
        groups="admins",
        roles="student",
        entitlements="captain",
    )
    def resource_endpoint(): ...
c                 >   > Xl         X l        [        TU ]  " U0 UD6  g N)issuerresource_serversuper__init__)selfr   r   argskwargs	__class__s        `/home/james-whalen/.local/lib/python3.13/site-packages/authlib/oauth2/rfc9068/token_validator.pyr    JWTBearerTokenValidator.__init__4   s     .$)&)    c                     [        5       e)a"  Return the JWKs that will be used to check the JWT access token signature.
Developers MUST re-implement this method. Typically the JWKs are statically
stored in the resource server configuration, or dynamically downloaded and
cached using :ref:`specs/rfc8414`::

    def get_jwks(self):
        if "jwks" in cache:
            return cache.get("jwks")

        server_metadata = get_server_metadata(self.issuer)
        jwks_uri = server_metadata.get("jwks_uri")
        cache["jwks"] = requests.get(jwks_uri).json()
        return cache["jwks"]
)NotImplementedError)r   s    r   get_jwks JWTBearerTokenValidator.get_jwks9   s     "##r   issstrreturnc                     X R                   :H  $ r   )r   )r   claimsr   s      r   validate_iss$JWTBearerTokenValidator.validate_issJ   s     kk!!r   c                 B   SU R                   S.SS0SU R                  S.SS0SS0SS0SS0SS0SS0SS0SS0SS0SS0SS0S.nU R                  5       n [        R                  " UU[
        US9$ ! [         a$  n[        U R                  U R                  S9UeS	nAff = f)
 T)	essentialvalidater(   )r(   valueF)r   expaudsub	client_idiatjti	auth_timeacramrscopegroupsrolesentitlements)key
claims_clsclaims_optionsrealmextra_attributesN)
r$   r   r   r   decoder
   r   r   r<   r=   )r   token_stringr:   jwksexcs        r   authenticate_token*JWTBearerTokenValidator.authenticate_tokenP   s    
 "&43D3DE&!%0D0DE&%t,&&%u-''!5)"E*!5)(%0
  }}
	::/-	   	#jj43H3H	s   A0 0
B:BBc                 
    UR                  5         U R                  UR                  S/ 5      U5      (       a
  [        5       eU R                  UR                  S5      U5      (       a
  [        5       eU R                  UR                  S5      U5      (       a
  [        5       eU R                  UR                  S5      U5      (       a
  [        5       eg! [         a$  n[        U R                  U R                  S9UeSnAff = f)r'   r;   Nr4   r5   r6   r7   )r)   r   r   r<   r=   scope_insufficientgetr   )r   tokenscopesrequestr5   r6   r7   rA   s           r   validate_token&JWTBearerTokenValidator.validate_token|   s    
	NN ""599Wb#96BB(** ""599X#6??#%%""599W#5u==#%%""599^#<lKK#%% L?  	#jj43H3H	s   C 
DC==D)r   r   )NNN)__name__
__module____qualname____firstlineno____doc__r   r   boolr$   rB   rJ   __static_attributes____classcell__)r   s   @r   r   r      s=    @*
$"" "$ "*Z MQ'& '&r   r   N)rP   authlib.joser   authlib.jose.errorsr   r   authlib.oauth2.rfc6750.errorsr   r    authlib.oauth2.rfc6750.validatorr   r#   r
   r    r   r   <module>rY      s0     + ) @ ; A (P&2 P&r   