o
    RDiAA                     @  s4  d dl mZ d dlZd dlZd dlZd dlZd dlmZm	Z	 d dl
mZmZ d dlmZmZ ddlmZmZmZmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ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+ erddl,m-Z- e.e/Z0G dd dZ1G dd de*e1eZ2dS )    )annotationsN)ABCabstractmethod)TYPE_CHECKINGAny)	HTTPErrorURLError   )ER_FAILED_TO_REQUESTER_IDP_CONNECTION_ERRORER_NO_CLIENT_IDER_NO_CLIENT_SECRET)ErrorProgrammingError)OAUTH_AUTHENTICATOR)get_proxy_url)SecretDetector)
TokenCacheTokenKey	TokenType)urllib3)get_environ_proxiesselect_proxy)ProxyManager   )AuthByPluginAuthType)SnowflakeConnectionc                   @  s   e Zd ZdZd(d
dZd)ddZd*ddZd*ddZd+ddZd,ddZ	d,ddZ
d-ddZd.d/d!d"Zd.d0d$d%Zd1d&d'ZdS )2_OAuthTokensMixina]  Manages OAuth token caching to avoid repeated browser authentication flows.

    Access tokens: Short-lived (typically 10 minutes), cached to avoid immediate re-auth.
    Refresh tokens: Long-lived (hours/days), used to obtain new access tokens silently.

    Tokens are cached per (user, IDP host) to support multiple OAuth providers/accounts.
    token_cacheTokenCache | Nonerefresh_token_enabledboolidp_hoststrreturnNonec                 C  sR   d | _ || _| jrd | _|| _| jr%td || _d | _| jr'd | _d S d S d S )Nz)token cache is going to be used if needed)	_access_token_refresh_token_enabled_refresh_token_token_cacheloggerdebug	_idp_host_access_token_key_refresh_token_key)selfr   r!   r#    r1   ]/var/www/Datamplify/venv/lib/python3.10/site-packages/snowflake/connector/auth/_oauth_base.py__init__.   s   

z_OAuthTokensMixin.__init__userc                 C  s   | j r|| _d S d S N)r*   _user)r0   r4   r1   r1   r2   _update_cache_keys@   s   
z$_OAuthTokensMixin._update_cache_keysTokenKey | Nonec                 C  s"   | j r| jrt| j| jtjS d S r5   )r*   r6   r   r-   r   OAUTH_ACCESS_TOKENr0   r1   r1   r2   _get_access_token_cache_keyD   s   z-_OAuthTokensMixin._get_access_token_cache_keyc                 C  s(   | j r| jr| jrt| j| jtjS d S r5   )r(   r*   r6   r   r-   r   OAUTH_REFRESH_TOKENr:   r1   r1   r2   _get_refresh_token_cache_keyK   s   z._OAuthTokensMixin._get_refresh_token_cache_keykey
str | Nonec                 C  s"   | j d u s	|d u rd S | j |S r5   )r*   retrieve)r0   r>   r1   r1   r2   _pop_cached_tokenR   s   z#_OAuthTokensMixin._pop_cached_tokenc                 C  s   |  |  | _| jduS )zRetrieves OAuth access token from the token cache if enabled, available and still valid.

        Returns True if cached token found, allowing authentication to skip OAuth flow.
        N)rA   r;   r'   r:   r1   r1   r2   _pop_cached_access_tokenW   s   
z*_OAuthTokensMixin._pop_cached_access_tokenc                 C  s$   | j r| |  | _| jduS dS )zRetrieves OAuth refresh token from the token cache (if enabled) to silently obtain new access token.

        Returns True if refresh token found, enabling automatic token renewal without user interaction.
        NF)r(   rA   r=   r)   r:   r1   r1   r2   _pop_cached_refresh_token_   s   
z+_OAuthTokensMixin._pop_cached_refresh_tokentokenc                 C  s<   | j d u s	|d u rd S |r| j || d S | j | d S r5   )r*   storeremove)r0   r>   rD   r1   r1   r2   _reset_cached_tokenk   s
   z%_OAuthTokensMixin._reset_cached_tokenNaccess_tokenc                 C  s8   t d|rdt| nd || _| |  | j dS )zKUpdates OAuth access token both in memory and in the token cache if enabledzresetting access token to %s*N)r+   r,   lenr'   rG   r;   )r0   rH   r1   r1   r2   _reset_access_tokens   s   z%_OAuthTokensMixin._reset_access_tokenrefresh_tokenc                 C  sB   | j rtd|rdt| nd || _| |  | j dS dS )zNUpdates OAuth refresh token both in memory and in the token cache if necessaryzresetting refresh token to %srI   N)r(   r+   r,   rJ   r)   rG   r=   )r0   rL   r1   r1   r2   _reset_refresh_token|   s   
z&_OAuthTokensMixin._reset_refresh_tokenc                 C  s&   d | _ | jr	d | _| jrd | _d S d S r5   )r'   r(   r)   r*   r6   r:   r1   r1   r2   _reset_temporary_state   s   
z(_OAuthTokensMixin._reset_temporary_state)r   r    r!   r"   r#   r$   r%   r&   )r4   r$   r%   r&   )r%   r8   )r>   r8   r%   r?   )r%   r"   )r>   r8   rD   r?   r%   r&   r5   )rH   r?   r%   r&   )rL   r?   r%   r&   r%   r&   )__name__
__module____qualname____doc__r3   r7   r;   r=   rA   rB   rC   rG   rK   rM   rN   r1   r1   r1   r2   r   %   s    







	r   c                      s   e Zd ZdZd@ fddZedAddZedBddZdCddZe	dDd!d"Z
e	dBd#d$ZedEd'd(ZdFd*d+ZdGd,d-ZdHd0d1ZdId2d3ZdJd5d6ZdKd9d:ZdLd;d<ZedMd>d?Z  ZS )NAuthByOAuthBasez.A base abstract class for OAuth authenticators	client_idr$   client_secrettoken_request_urlscoper   r    r!   r"   r%   r&   c                   sx   t  jdi | tj| ||tj|jd || _|| _|| _	|| _
|r:td |  j
| j
r2dndd 7  _
d S d S )N)r   r!   r#   z1oauth refresh token is going to be used if needed  offline_accessr1   )superr3   r   urllibparseurlparsehostname
_client_id_client_secret_token_request_url_scoper+   r,   )r0   rU   rV   rW   rX   r   r!   kwargs	__class__r1   r2   r3      s   

 zAuthByOAuthBase.__init__connr   authenticatorservice_namer?   accountr4   passwordre   r   (str | None, str | None)c                K     t )zRequest new access and optionally refresh tokens from IdP.

        This function should implement specific tokens querying flow.
        NotImplementedError)r0   rh   ri   rj   rk   r4   rl   re   r1   r1   r2   _request_tokens   s   zAuthByOAuthBase._request_tokensc                 C  rn   )zGet OAuth specific authenticator id to be passed to Snowflake.

        This function should return a unique OAuth authenticator id.
        ro   r:   r1   r1   r2   _get_oauth_type_id   s   z"AuthByOAuthBase._get_oauth_type_idc                 C  s   t d |   d S )Nzresetting secrets)r+   r,   rN   r:   r1   r1   r2   reset_secrets   s   
zAuthByOAuthBase.reset_secretsr   c                 C  s   t jS r5   )r   OAUTHr:   r1   r1   r2   type_   s   zAuthByOAuthBase.type_c                 C  s
   | j pdS )zReturns the token.rZ   )r'   r:   r1   r1   r2   assertion_content   s   
z!AuthByOAuthBase.assertion_content
connectiontuple[str, str]c                 C  sT   | d u s| dkrt |d tdtd |d u s|dkr&t |d tdtd | |fS )NrZ   z0Oauth code flow requirement 'client_id' is empty)msgerrnoz4Oauth code flow requirement 'client_secret' is empty)r   errorhandler_wrapperr   r   r   )rU   rV   rw   r1   r1   r2   $_validate_client_credentials_present   s&   	
z4AuthByOAuthBase._validate_client_credentials_presentdict[str, bool]c                K  s8   |    |  rtd | j|d ||  ddiS )NzJOAuth refresh token is available, try to use it and get a new access token)rh   successT)rK   rC   r+   r,   _do_refresh_tokenauthenticate_with_retry)r0   rh   re   r1   r1   r2   reauthenticate   s   
zAuthByOAuthBase.reauthenticatec          	      K  sd   t d | j|d |  rt d dS | jd|||||d|\}}| | | | dS )z!Web Browser based Authentication.z1authenticating with OAuth authorization code flow)r4   zJOAuth access token is already available in cache, no need to authenticate.N)rh   ri   rj   rk   r4   r1   )r+   r,   r7   rB   inforq   rK   rM   )	r0   rh   ri   rj   rk   r4   re   rH   rL   r1   r1   r2   prepare   s$   


zAuthByOAuthBase.preparebodydict[Any, Any]c                 C  sJ   t |d d< | j|d d< d|d vri |d d< |  |d d d< dS )zUsed by Auth to update the request that gets sent to /v1/login-request.

        Args:
            body: existing request dictionary
        dataAUTHENTICATORTOKENCLIENT_ENVIRONMENT
OAUTH_TYPEN)r   r'   rr   )r0   r   r1   r1   r2   update_body  s
   zAuthByOAuthBase.update_bodyc              
   C  s   | j s
td dS | |}|std |   dS z t|j	 }| 
|d  d|v r:| |d  W dS W dS  tjtfy^   td tdtt|j |   Y dS w )zIf a refresh token is available exchanges it with a new access token.
        Updates self as a side-effect. Needs at lest self._refresh_token and client_id set.
        z!refresh_token feature is disabledNz@failed to exchange the refresh token on a new OAuth access tokenrH   rL   z>refresh token exchange response did not contain 'access_token'zFreceived the following response body when exchanging refresh token: %s)r(   r+   r,   _get_refresh_token_responser   rM   jsonloadsr   decoderK   JSONDecodeErrorKeyErrorerrorr   mask_secretsr$   )r0   rh   resp	json_respr1   r1   r2   r   &  s:   


z!AuthByOAuthBase._do_refresh_tokenurllib3.BaseHTTPResponse | Nonec                 C  s  d| j d}| jr| j|d< z | || j}|rt|dnt }|jd| jd|  |dW S  t	yW } z| j
|td|j d	|j d
|j dd W Y d }~d S d }~w tyw } z| j
|td|j dd W Y d }~d S d }~w ty   | j
|tddd Y d S w )NrL   )
grant_typerL   rX   	proxy_urlPOSTF)encode_multipartheadersfieldszCFailed to request new OAuth access token with a refresh token, url=z, code=z	, reason=codemessagerh   retzGFailed to request new OAuth access token with a refresh token, reason: zOFailed to request new OAuth access token with a refresh token by unknown reason)r)   rd   _resolve_proxy_urlrc   r   r   PoolManagerrequest_encode_body_create_token_request_headersr   _handle_failurer
   urlr   reasonr   	Exception)r0   rh   r   r   http_clienter1   r1   r2   r   H  sf   

z+AuthByOAuthBase._get_refresh_token_responser   dict[str, str]c           	   
   C  s   |  || j}|rt|dnt }|jd| j|  d|d}ztd t	
|j}|d }|d}||fW S  t	jtfy`   td td	tt|j | j|td
dd Y dS w )Nr   r   F)r   r   r   z,OAuth IdP response received, try to parse itrH   rL   z7oauth response invalid, does not contain 'access_token'zDreceived the following response body when requesting oauth token: %szLInvalid HTTP request from web browser. Idp authentication could have failed.r   r   )NN)r   rc   r   r   r   r   r   r+   r,   r   r   r   getr   r   r   r   r   r$   r   r   )	r0   rw   r   r   r   r   r   rH   rL   r1   r1   r2   _get_request_token_response{  sB   




z+AuthByOAuthBase._get_request_token_responsec                 C  s,   dt | j d| j    dddS )NzBasic :zapplication/jsonz0application/x-www-form-urlencoded; charset=UTF-8)AuthorizationAcceptzContent-Type)base64	b64encodera   rb   encoder   r:   r1   r1   r2   r     s   z-AuthByOAuthBase._create_token_request_headersrequest_urlc                 C  s0   t | j| j| j| j}|r|S t|}t||S )zIResolve proxy URL from explicit config first, then environment variables.)r   
proxy_host
proxy_port
proxy_userproxy_passwordr   r   )rw   r   r   proxiesr1   r1   r2   r     s   
z"AuthByOAuthBase._resolve_proxy_url)rU   r$   rV   r$   rW   r$   rX   r$   r   r    r!   r"   r%   r&   )rh   r   ri   r$   rj   r?   rk   r$   r4   r$   rl   r?   re   r   r%   rm   )r%   r$   rO   )r%   r   )rU   r$   rV   r$   rw   r   r%   rx   )rh   r   re   r   r%   r}   )rh   r   ri   r$   rj   r?   rk   r$   r4   r$   re   r   r%   r&   )r   r   r%   r&   )rh   r   r%   r&   )rh   r   r%   r   )rw   r   r   r   r%   rm   )r%   r   )rw   r   r   r$   r%   r?   )rP   rQ   rR   rS   r3   r   rq   rr   rs   propertyru   rv   staticmethodr|   r   r   r   r   r   r   r   r   __classcell__r1   r1   rf   r2   rT      s.    





"
3
*
rT   )3
__future__r   r   r   loggingurllib.parser]   abcr   r   typingr   r   urllib.errorr   r   	errorcoder
   r   r   r   errorsr   r   networkr   proxyr   secret_detectorr   r   r   r   r   vendoredr   vendored.requests.utilsr   r   vendored.urllib3.poolmanagerr   	by_pluginr   r   rZ   r   	getLoggerrP   r+   r   rT   r1   r1   r1   r2   <module>   s.   
k