U
    gz]                     @   s  d dl Z d dlmZ d dlmZ d dlm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 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 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 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! 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' 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/ d d)l0m1Z1 G d*d+ d+e2Z3dS ),    N)Any)Callable)Optional)Flask)DecodeError)ExpiredSignatureError)InvalidAudienceError)InvalidIssuerError)InvalidTokenError)MissingRequiredClaimError)config)"default_additional_claims_callback)default_blocklist_callback)default_decode_key_callback)default_encode_key_callback)default_expired_token_callback)default_invalid_token_callback)default_jwt_headers_callback)"default_needs_fresh_token_callback)default_revoked_token_callback)#default_token_verification_callback)*default_token_verification_failed_callback)default_unauthorized_callback)default_user_identity_callback)"default_user_lookup_error_callback)	CSRFError)FreshTokenRequired)InvalidHeaderError)InvalidQueryParamError)JWTDecodeError)NoAuthorizationError)RevokedTokenError)UserClaimsVerificationError)UserLookupError)WrongTokenError)_decode_jwt)_encode_jwt)ExpiresDelta)Fresh)current_user_context_processorc                   @   s  e Zd ZdZd3ee eddddZd4eeddddZedd	d
dZ	e
edd	ddZeedddZeedddZeedddZeedddZeedddZeedddZeedddZeedddZeeddd Zeedd!d"Zeedd#d$Zeedd%d&Zeedd'd(Zeedd)d*Zeedd+d,Zd5eeeee ed-d.d/Z d6eee!d0d1d2Z"dS )7
JWTManagera&  
    An object used to hold JWT settings and callback functions for the
    Flask-JWT-Extended extension.

    Instances of :class:`JWTManager` are *not* bound to specific apps, so
    you can create one in the main body of your code and then bind it
    to your app in a factory function.
    NF)appadd_context_processorreturnc                 C   sr   t | _t| _t| _t| _t| _	t
| _t| _t| _t| _t| _t| _t| _d| _t| _t| _|dk	rn| || dS )a	  
        Create the JWTManager instance. You can either pass a flask application
        in directly here to register this extension with the flask app, or
        call init_app after creating this object (in a factory pattern).

        :param app:
            The Flask Application object
        :param add_context_processor:
            Controls if `current_user` is should be added to flasks template
            context (and thus be available for use in Jinja templates). Defaults
            to ``False``.
        N)r   _decode_key_callbackr   _encode_key_callbackr   _expired_token_callbackr   _invalid_token_callbackr   _jwt_additional_header_callbackr   _needs_fresh_token_callbackr   _revoked_token_callbackr   _token_in_blocklist_callbackr   _token_verification_callbackr   _unauthorized_callbackr   _user_claims_callbackr   _user_identity_callback_user_lookup_callbackr   _user_lookup_error_callbackr   #_token_verification_failed_callbackinit_appselfr+   r,    r@   B/tmp/pip-unpacked-wheel-qm6yk1_p/flask_jwt_extended/jwt_manager.py__init__;   s$    zJWTManager.__init__c                 C   s@   t |dsi |_| |jd< |r(|t | | | | dS )aY  
        Register this extension with the flask app.

        :param app:
            The Flask Application object
        :param add_context_processor:
            Controls if `current_user` is should be added to flasks template
            context (and thus be available for use in Jinja templates). Defaults
            to ``False``.
        
extensionszflask-jwt-extendedN)hasattrrC   Zcontext_processorr)   "_set_default_configuration_options_set_error_handler_callbacksr>   r@   r@   rA   r=   b   s    



zJWTManager.init_app)r+   r-   c                    sd  | t fdd}| t fdd}| t fdd}| t fdd}| t fd	d
}| t fdd}| t fdd}| t fdd}	| t	 fdd}
| t
 fdd}| t fdd}| t fdd}| t fdd}| t fdd}| t fdd}| t fdd }d S )!Nc                    s     t| S Nr7   strer?   r@   rA   handle_csrf_errorz   s    zBJWTManager._set_error_handler_callbacks.<locals>.handle_csrf_errorc                    s     t| S rG   r1   rI   rJ   rL   r@   rA   handle_decode_error~   s    zDJWTManager._set_error_handler_callbacks.<locals>.handle_decode_errorc                    s     | j| jS rG   )r0   
jwt_headerjwt_datarJ   rL   r@   rA   handle_expired_error   s    zEJWTManager._set_error_handler_callbacks.<locals>.handle_expired_errorc                    s     | j| jS rG   )r3   rP   rQ   rJ   rL   r@   rA   handle_fresh_token_required   s    zLJWTManager._set_error_handler_callbacks.<locals>.handle_fresh_token_requiredc                    s     t| S rG   rN   rJ   rL   r@   rA   #handle_missing_required_claim_error   s    zTJWTManager._set_error_handler_callbacks.<locals>.handle_missing_required_claim_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_invalid_audience_error   s    zNJWTManager._set_error_handler_callbacks.<locals>.handle_invalid_audience_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_invalid_issuer_error   s    zLJWTManager._set_error_handler_callbacks.<locals>.handle_invalid_issuer_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_invalid_header_error   s    zLJWTManager._set_error_handler_callbacks.<locals>.handle_invalid_header_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_invalid_token_error   s    zKJWTManager._set_error_handler_callbacks.<locals>.handle_invalid_token_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_jwt_decode_error   s    zHJWTManager._set_error_handler_callbacks.<locals>.handle_jwt_decode_errorc                    s     t| S rG   rH   rJ   rL   r@   rA   handle_auth_error   s    zBJWTManager._set_error_handler_callbacks.<locals>.handle_auth_errorc                    s     t| S rG   rN   rJ   rL   r@   rA    handle_invalid_query_param_error   s    zQJWTManager._set_error_handler_callbacks.<locals>.handle_invalid_query_param_errorc                    s     | j| jS rG   )r4   rP   rQ   rJ   rL   r@   rA   handle_revoked_token_error   s    zKJWTManager._set_error_handler_callbacks.<locals>.handle_revoked_token_errorc                    s     | j| jS rG   )r<   rP   rQ   rJ   rL   r@   rA    handle_failed_token_verification   s    zQJWTManager._set_error_handler_callbacks.<locals>.handle_failed_token_verificationc                    s     | j| jS rG   )r;   rP   rQ   rJ   rL   r@   rA   handler_user_lookup_error   s    zJJWTManager._set_error_handler_callbacks.<locals>.handler_user_lookup_errorc                    s     t| S rG   rN   rJ   rL   r@   rA   handle_wrong_token_error   s    zIJWTManager._set_error_handler_callbacks.<locals>.handle_wrong_token_error)Zerrorhandlerr   r   r   r   r   r   r	   r   r
   r   r    r   r!   r"   r#   r$   )r?   r+   rM   rO   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r@   rL   rA   rF   y   s@    z'JWTManager._set_error_handler_callbacksc                 C   sh  | j dtjdd | j dd | j dd | j dd	 | j d
d | j dd | j dd | j dd | j dd | j dd  | j dd  | j dd | j dd | j dd | j dddddg | j dd  | j dd  | j d d  | j d!d" | j d#d  | j d$d  | j d%d& | j d'd( | j d)d* | j d+d, | j d-d. | j d/d  | j d0d  | j d1d2 | j d3d4 | j d5d6 | j d7d | j d8d9 | j d:d | j d;d | j d<d | j d=d> | j d?tjd@dA | j dBd  | j dCd | j dDdE | j dFd d S )GNZJWT_ACCESS_TOKEN_EXPIRES   )minutesZJWT_ACCESS_COOKIE_NAMEZaccess_token_cookieZJWT_ACCESS_COOKIE_PATH/ZJWT_ACCESS_CSRF_COOKIE_NAMEZcsrf_access_tokenZJWT_ACCESS_CSRF_COOKIE_PATHZJWT_ACCESS_CSRF_FIELD_NAMEZ
csrf_tokenZJWT_ACCESS_CSRF_HEADER_NAMEzX-CSRF-TOKENZJWT_ALGORITHMZHS256ZJWT_COOKIE_CSRF_PROTECTTZJWT_COOKIE_DOMAINZJWT_COOKIE_SAMESITEZJWT_COOKIE_SECUREFZJWT_CSRF_CHECK_FORMZJWT_CSRF_IN_COOKIESZJWT_CSRF_METHODSPOSTPUTPATCHDELETEZJWT_DECODE_ALGORITHMSZJWT_DECODE_AUDIENCEZJWT_DECODE_ISSUERZJWT_DECODE_LEEWAYr   ZJWT_ENCODE_AUDIENCEZJWT_ENCODE_ISSUERZJWT_ERROR_MESSAGE_KEYmsgZJWT_HEADER_NAMEAuthorizationZJWT_HEADER_TYPEZBearerZJWT_IDENTITY_CLAIMsubZJWT_JSON_KEYZaccess_tokenZJWT_PRIVATE_KEYZJWT_PUBLIC_KEYZJWT_QUERY_STRING_NAMEjwtZJWT_QUERY_STRING_VALUE_PREFIX ZJWT_REFRESH_COOKIE_NAMEZrefresh_token_cookieZJWT_REFRESH_COOKIE_PATHZJWT_REFRESH_CSRF_COOKIE_NAMEZcsrf_refresh_tokenZJWT_REFRESH_CSRF_COOKIE_PATHZJWT_REFRESH_CSRF_FIELD_NAMEZJWT_REFRESH_CSRF_HEADER_NAMEZJWT_REFRESH_JSON_KEYZrefresh_tokenZJWT_REFRESH_TOKEN_EXPIRES   )daysZJWT_SECRET_KEYZJWT_SESSION_COOKIEZJWT_TOKEN_LOCATION)headersZJWT_ENCODE_NBF)r   
setdefaultdatetime	timedelta)r+   r@   r@   rA   rE      sZ     
z-JWTManager._set_default_configuration_options)callbackr-   c                 C   s
   || _ |S )aF  
        This decorator sets the callback function used to add additional claims
        when creating a JWT. The claims returned by this function will be merged
        with any claims passed in via the ``additional_claims`` argument to
        :func:`~flask_jwt_extended.create_access_token` or
        :func:`~flask_jwt_extended.create_refresh_token`.

        The decorated function must take **one** argument.

        The argument is the identity that was used when creating a JWT.

        The decorated function must return a dictionary of claims to add to the JWT.
        )r8   r?   rr   r@   r@   rA   additional_claims_loader   s    z#JWTManager.additional_claims_loaderc                 C   s
   || _ |S )aK  
        This decorator sets the callback function used to add additional headers
        when creating a JWT. The headers returned by this function will be merged
        with any headers passed in via the ``additional_headers`` argument to
        :func:`~flask_jwt_extended.create_access_token` or
        :func:`~flask_jwt_extended.create_refresh_token`.

        The decorated function must take **one** argument.

        The argument is the identity that was used when creating a JWT.

        The decorated function must return a dictionary of headers to add to the JWT.
        )r2   rs   r@   r@   rA   additional_headers_loader   s    z$JWTManager.additional_headers_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for dynamically setting the JWT
        decode key based on the **UNVERIFIED** contents of the token. Think
        carefully before using this functionality, in most cases you probably
        don't need it.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the
        unverified JWT.

        The second argument is a dictionary containing the payload data of the
        unverified JWT.

        The decorated function must return a *string* that is used to decode and
        verify the token.
        )r.   rs   r@   r@   rA   decode_key_loader  s    zJWTManager.decode_key_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for dynamically setting the JWT
        encode key based on the tokens identity. Think carefully before using this
        functionality, in most cases you probably don't need it.

        The decorated function must take **one** argument.

        The argument is the identity used to create this JWT.

        The decorated function must return a *string* which is the secrete key used to
        encode the JWT.
        )r/   rs   r@   r@   rA   encode_key_loader   s    zJWTManager.encode_key_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for returning a custom
        response when an expired JWT is encountered.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return a Flask Response.
        )r0   rs   r@   r@   rA   expired_token_loader0  s    zJWTManager.expired_token_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for returning a custom
        response when an invalid JWT is encountered.

        This decorator sets the callback function that will be used if an
        invalid JWT attempts to access a protected endpoint.

        The decorated function must take **one** argument.

        The argument is a string which contains the reason why a token is invalid.

        The decorated function must return a Flask Response.
        )r1   rs   r@   r@   rA   invalid_token_loader@  s    zJWTManager.invalid_token_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for returning a custom
        response when a valid and non-fresh token is used on an endpoint
        that is marked as ``fresh=True``.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return a Flask Response.
        )r3   rs   r@   r@   rA   needs_fresh_token_loaderQ  s    z#JWTManager.needs_fresh_token_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function for returning a custom
        response when a revoked token is encountered.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return a Flask Response.
        )r4   rs   r@   r@   rA   revoked_token_loaderb  s    zJWTManager.revoked_token_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used to check if a JWT has
        been revoked.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must be return ``True`` if the token has been
        revoked, ``False`` otherwise.
        )r5   rs   r@   r@   rA   token_in_blocklist_loaderr  s    z$JWTManager.token_in_blocklist_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used to return a custom
        response when the claims verification check fails.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return a Flask Response.
        )r<   rs   r@   r@   rA    token_verification_failed_loader  s    z+JWTManager.token_verification_failed_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used for custom verification
        of a valid JWT.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return ``True`` if the token is valid, or
        ``False`` otherwise.
        )r6   rs   r@   r@   rA   token_verification_loader  s    z$JWTManager.token_verification_loaderc                 C   s
   || _ |S )aF  
        This decorator sets the callback function used to return a custom
        response when no JWT is present.

        The decorated function must take **one** argument.

        The argument is a string that explains why the JWT could not be found.

        The decorated function must return a Flask Response.
        )r7   rs   r@   r@   rA   unauthorized_loader  s    zJWTManager.unauthorized_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used to convert an identity to
        a JSON serializable format when creating JWTs. This is useful for
        using objects (such as SQLAlchemy instances) as the identity when
        creating your tokens.

        The decorated function must take **one** argument.

        The argument is the identity that was used when creating a JWT.

        The decorated function must return JSON serializable data.
        )r9   rs   r@   r@   rA   user_identity_loader  s    zJWTManager.user_identity_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used to convert a JWT into
        a python object that can be used in a protected endpoint. This is useful
        for automatically loading a SQLAlchemy instance based on the contents
        of the JWT.

        The object returned from this function can be accessed via
        :attr:`~flask_jwt_extended.current_user` or
        :meth:`~flask_jwt_extended.get_current_user`

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function can return any python object, which can then be
        accessed in a protected endpoint. If an object cannot be loaded, for
        example if a user has been deleted from your database, ``None`` must be
        returned to indicate that an error occurred loading the user.
        )r:   rs   r@   r@   rA   user_lookup_loader  s    zJWTManager.user_lookup_loaderc                 C   s
   || _ |S )a  
        This decorator sets the callback function used to return a custom
        response when loading a user via
        :meth:`~flask_jwt_extended.JWTManager.user_lookup_loader` fails.

        The decorated function must take **two** arguments.

        The first argument is a dictionary containing the header data of the JWT.

        The second argument is a dictionary containing the payload data of the JWT.

        The decorated function must return a Flask Response.
        )r;   rs   r@   r@   rA   user_lookup_error_loader  s    z#JWTManager.user_lookup_error_loader)identity
token_typefreshexpires_deltar-   c           	      C   s   |  |}|d k	r|| | |}|d k	r8|| |d krV|dkrPtj}ntj}ttjtj|tj	|||| 
|tjtjtj| ||tjdS )Naccess)	algorithmaudienceclaim_overridesZcsrfr   r   header_overridesr   identity_claim_keyissuerjson_encodersecretr   Znbf)r2   updater8   r   Zaccess_expiresZrefresh_expiresr&   r   Zencode_audienceZcookie_csrf_protectr9   r   Zencode_issuerr   r/   Z
encode_nbf)	r?   r   r   Zclaimsr   r   rn   r   r   r@   r@   rA   _encode_jwt_from_config  s4    	



z"JWTManager._encode_jwt_from_config)encoded_tokenallow_expiredr-   c           	   
   C   s   t j|tjddid}t |}| ||}tjtj||tjtjtj	|tjd k	d	}zt
f |d|iW S  tk
r } z ||_t
f |ddi|_ W 5 d }~X Y nX d S )NZverify_signatureF)
algorithmsoptions)	r   r   
csrf_valuer   r   r   leewayr   Z
verify_audr   T)rj   decoder   Zdecode_algorithmsZget_unverified_headerr.   Zdecode_audiencer   Zdecode_issuerr   r%   r   rP   rQ   )	r?   r   r   r   Zunverified_claimsZunverified_headersr   kwargsrK   r@   r@   rA   _decode_jwt_from_config  s.    
z"JWTManager._decode_jwt_from_config)NF)F)NFNN)NF)#__name__
__module____qualname____doc__r   r   boolrB   r=   rF   staticmethodrE   r   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   rI   r(   r'   r   dictr   r@   r@   r@   rA   r*   1   sZ   
    'A.    )    r*   )4rp   typingr   r   r   rj   Zflaskr   r   r   r   r	   r
   r   Zflask_jwt_extended.configr   Z$flask_jwt_extended.default_callbacksr   r   r   r   r   r   r   r   r   r   r   r   r   r   Zflask_jwt_extended.exceptionsr   r   r   r   r   r    r!   r"   r#   r$   Zflask_jwt_extended.tokensr%   r&   Zflask_jwt_extended.typingr'   r(   Zflask_jwt_extended.utilsr)   objectr*   r@   r@   r@   rA   <module>   sT   