
    ɯeiN-                    &   d dl mZ d dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
 ddlmZ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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#m$Z$ erddl m%Z%  ejL                  e'      Z(d Z)d Z* G d de#      Z+y)    )annotationsN)partial)TYPE_CHECKINGAnyCallable   )unescape	urlencodeurlsplit)HTTP_HEADER_ACCEPTHTTP_HEADER_CONTENT_TYPEHTTP_HEADER_SERVICE_NAMEHTTP_HEADER_USER_AGENT)ER_IDP_CONNECTION_ERRORER_INCORRECT_DESTINATION)DatabaseErrorErrorRefreshTokenError)CONTENT_TYPE_APPLICATION_JSONPYTHON_CONNECTOR_USER_AGENT)'SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED   )Auth)AuthByPluginAuthType)SnowflakeConnectionc                    t        |       }t        |      }|j                  }|s|j                  dk(  rd}|j                  }|s|j                  dk(  rd}|j                  |j                  k(  xr  ||k(  xr |j                  |j                  k(  S )zChecks if URL prefixes are identical.

    The scheme, hostname and port number are compared. If the port number is not specified and the scheme is https,
    the port number is assumed to be 443.
    https443)r   portschemehostname)url1url2parsed_url1parsed_url2port1port2s         _/var/www/html/glpi_dashboard/venv/lib/python3.12/site-packages/snowflake/connector/auth/okta.py_is_prefix_equalr*      s     4.K4.KE[''72E[''72 	 4 44 	5UN	5+"4"44    c                    t         j                  |        | j                  d      }| j                  d|      }| j                  d|dz         }t        | |dz   |       S )zGets the post back URL.

    Since the HTML is not well-formed, minidom cannot be used to convert to
    DOM. The first discovered form is assumed to be the form to post back
    and the URL is taken from action attributes.
    z<formzaction=""   )loggerdebugfindr	   )htmlidx	start_idxend_idxs       r)   _get_post_back_url_from_htmlr6   5   sX     LL
))G
C		*c*IiiY]+GDQ122r+   c                  $    e Zd ZdZd fdZddZedd       Zedd       ZddZ		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ
ddZ	 	 	 	 	 	 	 	 	 	 	 	 dd	Z	 	 	 	 	 	 	 	 	 	 dd
Ze	 	 	 	 	 	 	 	 	 	 	 	 dd       Ze	 	 	 	 	 	 	 	 dd       Z	 	 	 	 	 	 ddZ xZS )
AuthByOktazAuthenticate user by OKTA.c                @    t        |   di | d | _        || _        y )N )super__init___saml_response_application)selfapplicationkwargs	__class__s      r)   r<   zAuthByOkta.__init__G   s#    "6""'r+   c                     y Nr:   r?   s    r)   reset_secretszAuthByOkta.reset_secretsL   s    r+   c                "    t         j                  S rD   )r   OKTArE   s    r)   type_zAuthByOkta.type_O   s    }}r+   c                    | j                   S rD   r=   rE   s    r)   assertion_contentzAuthByOkta.assertion_contentS   s    """r+   c                (    | j                   |d   d<   y )NdataRAW_SAML_RESPONSErK   )r?   bodys     r)   update_bodyzAuthByOkta.update_bodyW   s    ,0,?,?V()r+   c                  t         j                  d       | j                  |||||      \  }}	}
| j                  |||	|
       | j	                  |t        | j                  |||
||      |	      }| j                  ||       y)a
  SAML Authentication.

        Steps are:
        1.  query GS to obtain IDP token and SSO url
        2.  IMPORTANT Client side validation:
            validate both token url and sso url contains same prefix
            (protocol + host + port) as the given authenticator url.
            Explanation:
            This provides a way for the user to 'authenticate' the IDP it is
            sending his/her credentials to.  Without such a check, the user could
            be coerced to provide credentials to an IDP impersonator.
        3.  query IDP token url to authenticate and retrieve access token
        4.  given access token, query IDP URL snowflake app to get SAML response
        5.  IMPORTANT Client side validation:
            validate the post back url come back with the SAML response
            contains the same prefix as the Snowflake's server url, which is the
            intended destination url to Snowflake.
        Explanation:
            This emulates the behavior of IDP initiated login flow in the user
            browser where the IDP instructs the browser to POST the SAML
            assertion to the specific SP endpoint.  This is critical in
            preventing a SAML assertion issued to one SP from being sent to
            another SP.
        zauthenticating by SAMLN)r/   r0   _step1_step2_step4r   _step3_step5)r?   connauthenticatorservice_nameaccountuserpasswordrA   headerssso_url	token_urlresponse_htmls               r)   preparezAuthByOkta.prepareZ   s    F 	-.&*kk'
#) 	D-)<DKKw	4J

 	D-(r+   c                
    ddiS )NsuccessFr:   )r?   rA   s     r)   reauthenticatezAuthByOkta.reauthenticate   s    5!!r+   c                ,   t         j                  d       t        t        t        t        t
        t        i}|r	||t        <   d}t        j                  |||j                  |j                  |j                  |j                         |j                  |j                  |j                   |j"                  |j$                  |j&                  j)                  d            }||d   d<   t         j                  d||       |j*                  j-                  ||t/        j0                  |      |j*                  j2                  j                  |j*                  j2                  j                  	      }	|	d
   s| j5                  ||	       |	d   }
|
d   }|
d   }|||fS )Nz0step 1: query GS to obtain IDP token and SSO urlz/session/authenticator-requestF)use_pooling)session_managerrN   AUTHENTICATORzaccount=%s, authenticator=%s)timeoutsocket_timeoutrd   )rX   rettokenUrlssoUrl)r/   r0   r   r   r   r   r   r   r   base_auth_datar@   _internal_application_name_internal_application_version
_ocsp_modecert_revocation_check_modelogin_timeoutnetwork_timeoutrk   "platform_detection_timeout_seconds_session_managerclone_rest_post_requestjsondumps_connection_handle_failure)r?   rX   rY   rZ   r[   r\   r^   urlrP   rl   rN   r`   r_   s                r)   rS   zAuthByOkta._step1   s}    	GH %&C ="$?

 0<G,-.""++..OO++  33 1177E7J
 )6V_%*	

 jj&&JJtJJ**88::11?? ' 
 9~  d 46{$	x.**r+   c                    t         j                  d       t        ||      rt        ||      sFt        j                  |j
                  j                  d t        d| d| d| t        t        d       y y )NzGstep 2: validate Token and SSO URL has the same prefix as authenticatorz.The specified authenticator is not supported: z, token_url: z, sso_url: msgerrnosqlstate)
r/   r0   r*   r   errorhandler_wrapperry   r}   r   r   r   )r?   rX   rY   r_   r`   s        r)   rT   zAuthByOkta._step2   s     	U	
  y9AQ7B
 &&

&& I(/yk B$$+9. 5 G	B
r+   c           	        t         j                  d       ||d}| j                  j                  d||t	        j
                  |      | j                  j                  j                  | j                  j                  j                  d      }|j                  d|j                  d            }|sMt        j                  | j                  j                  d t        dj                  ||	      t        t        d
       |S )NzEstep 3: query IDP token url to authenticate and retrieve access token)usernamer]   postT)rN   rj   rk   catch_okta_unauthorized_errorsessionTokencookieTokenz4The authentication failed for {user} by {token_url}.)r`   r\   r   )r/   r0   restfetchr{   r|   ry   r}   rt   getr   r   r   formatr   r   )rX   r^   r`   r\   r]   rN   rl   one_time_tokens           r)   rV   zAuthByOkta._step3   s     	V	
  
 iiooD!JJ**88::11??*.  
 1GH&&

&&**0&&/!% +1 +
 5 G
	  r+   c           	        t         j                  d       | j                  r!t        j                         | j                  z   nd }i }|}|t        j                         |k  rd	 d |       d}|dz   t	        |      z   }t
        di}|r|t        j                         z
  nd }| j                  j                  d||||dd      }	 |S |S # t        $ r t         j                  d	       Y nw xY w|t        j                         |k  rB)
Nz8step 4: query IDP URL snowflake app to get SAML responsez/some/deep/link)
RelayStateonetimetoken?z*/*r   T)rj   rk   is_raw_textis_okta_authenticationz*step4: refresh token for re-authentication)	r/   r0   rt   timer
   r   r   r   r   )	rX   generate_one_time_tokenr_   timeout_timera   origin_sso_urlurl_parametersr^   remaining_timeouts	            r)   rU   zAuthByOkta._step4  s    	RS;?;M;Mtyy{T%7%77SW "diikL&@K"3$;$=" )3.>1JJ& COL499;$>TX! $		-#4 $+/ !0 !  } % KIJK+ "diikL&@s   #A C C)(C)c           	        t         j                  d       t        |      }dj                  |j                  j
                  |j                  j                  |j                  j                        }t        |dd      sYt        ||      sMt        j                  |j                  j                  d t        dj                  ||      t        t        d       || _        y )	Nz4step 5: validate post_back_url matches Snowflake URLz{protocol}://{host}:{port})protocolhostr    _disable_saml_url_checkFzThe specified authenticator and destination URL in the SAML assertion do not match: expected: {url}, post back: {post_back_url})r   post_back_urlr   )r/   r0   r6   r   ry   	_protocol_host_portgetattrr*   r   r   r}   r   r   r   r=   )r?   rX   ra   r   full_urls        r)   rW   zAuthByOkta._step52  s    
 	KL4]C/66ZZ))!!!! 7 

 t6>GW8H
 &&

&&5 6<V (*7 6< 6
 6 G	$ ,r+   )r@   strreturnNone)r   r   )r   r   )r   r   )rP   dict[Any, Any]r   r   )rX   r   rY   r   rZ   
str | Noner[   r   r\   r   r]   r   rA   r   r   r   )rA   r   r   zdict[str, bool])rX   r   rY   r   rZ   r   r[   r   r\   r   r   ztuple[dict[str, str], str, str])
rX   r   rY   r   r_   r   r`   r   r   r   )rX   r   r^   zdict[str, str]r`   r   r\   r   r]   r   r   r   )rX   r   r   r   r_   r   r   r   )rX   r   ra   r   r   r   )__name__
__module____qualname____doc__r<   rF   propertyrI   rL   rQ   rb   re   rS   rT   staticmethodrV   rU   rW   __classcell__)rB   s   @r)   r8   r8   D   s   $(
   # #@1) "1) 	1)
 !1) 1) 1) 1) 1) 
1)f"5+!5+ 5+ !	5+
 5+ 5+ 
)5+n!  	
  
8 )!)) ) 	)
 ) 
) )V  ! !)    
	   D!,!!, !, 
	!,r+   r8   ),
__future__r   r{   loggingr   	functoolsr   typingr   r   r   compatr	   r
   r   	constantsr   r   r   r   	errorcoder   r   errorsr   r   r   networkr   r   r   r    r   	by_pluginr   r   r   	getLoggerr   r/   r*   r6   r8   r:   r+   r)   <module>r      sr    "     / / 2 2  J < < P >  -&			8	$.3O, O,r+   