
    ~h                         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 ddlm	Z	  ej                  d	      Z ej                  d	      Zd
 Zd Zd Z G d d      Zy)    N)to_bytes)
to_unicode)urlsafe_b64encode   )InvalidGrantError)InvalidRequestError)OAuth2Requestz^[a-zA-Z0-9\-._~]{43,128}$c                     t        j                  t        | d            j                         }t	        t        |            S )z8Create S256 code_challenge with the given code_verifier.ascii)hashlibsha256r   digestr   r   )code_verifierdatas     \/opt/mcp/mcp-sentiment/venv/lib/python3.12/site-packages/authlib/oauth2/rfc7636/challenge.pycreate_s256_code_challenger      s1    >>(=':;BBDD'-..    c                     | |k(  S N r   code_challenges     r   compare_plain_code_challenger      s     N**r   c                     t        |       |k(  S r   )r   r   s     r   compare_s256_code_challenger      s    %m4FFr   c                   L    e Zd ZdZdZddgZeedZddZ	d Z
d Zd Zd	 Zd
 Zy)CodeChallengea  CodeChallenge extension to Authorization Code Grant. It is used to
    improve the security of Authorization Code flow for public clients by
    sending extra "code_challenge" and "code_verifier" to the authorization
    server.

    The AuthorizationCodeGrant SHOULD save the ``code_challenge`` and
    ``code_challenge_method`` into database when ``save_authorization_code``.
    Then register this extension via::

        server.register_grant(AuthorizationCodeGrant, [CodeChallenge(required=True)])
    plainS256)r   r   c                     || _         y r   )required)selfr!   s     r   __init__zCodeChallenge.__init__8   s	     r   c                 t    |j                  d| j                         |j                  d| j                         y )N,after_validate_authorization_request_payloadafter_validate_token_request)register_hookvalidate_code_challengevalidate_code_verifier)r"   grants     r   __call__zCodeChallenge.__call__;   s8    :((	
 	*''	
r   c                 >   |j                   }|j                  j                  j                  d      }|j                  j                  j                  d      }|s|sy |st	        d      t        |j                  j                  j                  dg             dkD  rt	        d      t        j                  |      st	        d      |r|| j                  vrt	        d      t        |j                  j                  j                  dg             dkD  rt	        d      y )	Nr   code_challenge_methodzMissing 'code_challenge'   z%Multiple 'code_challenge' in request.zInvalid 'code_challenge'z#Unsupported 'code_challenge_method'z,Multiple 'code_challenge_method' in request.)
requestpayloadr   getr   lendatalistCODE_CHALLENGE_PATTERNmatchSUPPORTED_CODE_CHALLENGE_METHOD)r"   r*   redirect_urir/   	challengemethods         r   r(   z%CodeChallenge.validate_code_challengeE   s    !&OO((,,-=>	%%))*AB%&@AAw''++,<bABQF%&MNN%++I6%&@AAfD$H$HH%&KLLw''++,CRHIAM%&TUU Nr   c                     |j                   }|j                  j                  d      }| j                  r|j                  dk(  r|st        d      |j                  }| j                  |      }|s|sy |st        d      t        j                  |      st        d      | j                  |      }|| j                  }| j                  j                  |      }|st        d| d       |||      st        d      y )	Nr   nonezMissing 'code_verifier'zInvalid 'code_verifier'zNo verify method for ''zCode challenge failed.)description)r/   formr1   r!   auth_methodr   authorization_code get_authorization_code_challengeCODE_VERIFIER_PATTERNr5   'get_authorization_code_challenge_methodDEFAULT_CODE_CHALLENGE_METHODCODE_CHALLENGE_METHODSRuntimeErrorr   )	r"   r*   resultr/   verifierr@   r8   r9   funcs	            r   r)   z$CodeChallenge.validate_code_verifier[   s   !&<<##O4 ==W00F:8%&?@@$7799:LM	  %&?@@$**84%&?@@ ==>PQ>77F**..v6!7xqABB Hi(#0HII )r   c                     |j                   S )a[  Get "code_challenge" associated with this authorization code.
        Developers MAY re-implement it in subclass, the default logic::

            def get_authorization_code_challenge(self, authorization_code):
                return authorization_code.code_challenge

        :param authorization_code: the instance of authorization_code
        )r   r"   r@   s     r   rA   z.CodeChallenge.get_authorization_code_challenge   s     "000r   c                     |j                   S )ap  Get "code_challenge_method" associated with this authorization code.
        Developers MAY re-implement it in subclass, the default logic::

            def get_authorization_code_challenge_method(self, authorization_code):
                return authorization_code.code_challenge_method

        :param authorization_code: the instance of authorization_code
        )r-   rK   s     r   rC   z5CodeChallenge.get_authorization_code_challenge_method   s     "777r   N)T)__name__
__module____qualname____doc__rD   r6   r   r   rE   r#   r+   r(   r)   rA   rC   r   r   r   r   r   !   sK    
 %,!'.&7# .+
!
V,"JH	1	8r   r   )r   reauthlib.common.encodingr   r   r   rfc6749r   r   r	   compilerB   r4   r   r   r   r   r   r   r   <module>rU      s]     	 , . 5 ' ) #"

#@A #$AB /+G
r8 r8r   