o
    ©D®f|  ã                   @   s4   d dl mZ ddlmZmZmZ G dd„ deƒZdS )é    )Údefault_json_headersé   )ÚTokenEndpointÚInvalidRequestErrorÚUnsupportedTokenTypeErrorc                   @   sL   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dd„ ZdS )ÚIntrospectionEndpointz‰Implementation of introspection endpoint which is described in
    `RFC7662`_.

    .. _RFC7662: https://tools.ietf.org/html/rfc7662
    Úintrospectionc                 C   sD   |   ||¡ |  |jd |j d¡¡}|r|  |||¡r |S dS dS )aw  The protected resource calls the introspection endpoint using an HTTP
        ``POST`` request with parameters sent as
        "application/x-www-form-urlencoded" data. The protected resource sends a
        parameter representing the token along with optional parameters
        representing additional context that is known by the protected resource
        to aid the authorization server in its response.

        token
            **REQUIRED**  The string value of the token. For access tokens, this
            is the ``access_token`` value returned from the token endpoint
            defined in OAuth 2.0. For refresh tokens, this is the
            ``refresh_token`` value returned from the token endpoint as defined
            in OAuth 2.0.

        token_type_hint
            **OPTIONAL**  A hint about the type of the token submitted for
            introspection.
        ÚtokenÚtoken_type_hintN)Úcheck_paramsÚquery_tokenÚformÚgetÚcheck_permission)ÚselfÚrequestÚclientr	   © r   ú]/home/ubuntu/webapp/venv/lib/python3.10/site-packages/authlib/oauth2/rfc7662/introspection.pyÚauthenticate_token   s
   ÿz(IntrospectionEndpoint.authenticate_tokenc                 C   s:   |j }d|vr
tƒ ‚| d¡}|r|| jvrtƒ ‚d S d S )Nr	   r
   )r   r   r   ÚSUPPORTED_TOKEN_TYPESr   )r   r   r   ÚparamsÚhintr   r   r   r   +   s   
ÿz"IntrospectionEndpoint.check_paramsc                 C   s*   |   |¡}|  ||¡}|  |¡}d|tfS )zpValidate introspection request and create the response.

        :returns: (status_code, body, headers)
        éÈ   )Úauthenticate_endpoint_clientr   Úcreate_introspection_payloadr   )r   r   r   r	   Úbodyr   r   r   Úcreate_endpoint_response4   s   


z.IntrospectionEndpoint.create_endpoint_responsec                 C   sB   |sddiS |  ¡ s| ¡ rddiS |  |¡}d|vrd|d< |S )NÚactiveFT)Ú
is_expiredÚ
is_revokedÚintrospect_token)r   r	   Úpayloadr   r   r   r   D   s   
z2IntrospectionEndpoint.create_introspection_payloadc                 C   ó   t ƒ ‚)aU  Check if the request has permission to introspect the token. Developers
        MUST implement this method::

            def check_permission(self, token, client, request):
                # only allow a special client to introspect the token
                return client.client_id == 'introspection_client'

        :return: bool
        ©ÚNotImplementedError)r   r	   r   r   r   r   r   r   R   s   
z&IntrospectionEndpoint.check_permissionc                 C   r#   )a’  Get the token from database/storage by the given token string.
        Developers should implement this method::

            def query_token(self, token_string, token_type_hint):
                if token_type_hint == 'access_token':
                    tok = Token.query_by_access_token(token_string)
                elif token_type_hint == 'refresh_token':
                    tok = Token.query_by_refresh_token(token_string)
                else:
                    tok = Token.query_by_access_token(token_string)
                    if not tok:
                        tok = Token.query_by_refresh_token(token_string)
                return tok
        r$   )r   Útoken_stringr
   r   r   r   r   ^   s   z!IntrospectionEndpoint.query_tokenc                 C   r#   )a  Read given token and return its introspection metadata as a
        dictionary following `Section 2.2`_::

            def introspect_token(self, token):
                return {
                    'active': True,
                    'client_id': token.client_id,
                    'token_type': token.token_type,
                    'username': get_token_username(token),
                    'scope': token.get_scope(),
                    'sub': get_token_user_sub(token),
                    'aud': token.client_id,
                    'iss': 'https://server.example.com/',
                    'exp': token.expires_at,
                    'iat': token.issued_at,
                }

        .. _`Section 2.2`: https://tools.ietf.org/html/rfc7662#section-2.2
        r$   )r   r	   r   r   r   r!   o   s   z&IntrospectionEndpoint.introspect_tokenN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚENDPOINT_NAMEr   r   r   r   r   r   r!   r   r   r   r   r   	   s    	r   N)Úauthlib.constsr   Úrfc6749r   r   r   r   r   r   r   r   Ú<module>   s    