
    AHjT                     4   d Z ddlZddlZddl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mZmZmZmZmZmZmZmZ 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jF                  dk  rddl	m$Z$ ddl%m&Z& nddl'm$Z$ ddl	m&Z&  ejP                  e)      Z* ed      Z+ e&d      Z, G d de      Z- G d de.      Z/ G d de.      Z0 G d de      Z1 G d dejd                        Z3 G d de.      Z4de$e,e+f   de$e,e+f   fdZ5 G d d       Z6y)!zSSO login base dependency.    N)TracebackType)AnyClassVarDictListLiteralOptionalType	TypedDictTypeVarUnionoverload)WebApplicationClient)HTTPException)Request)RedirectResponse)get_pkce_challenge_pair)generate_random_state)   
   )Callable)	ParamSpecTPc                   0    e Zd ZU dZeed<   eed<   eed<   y)DiscoveryDocumentzDiscovery document.authorization_endpointtoken_endpointuserinfo_endpointN)__name__
__module____qualname____doc__str__annotations__     L/root/tools/cai/cai_env/lib/python3.12/site-packages/fastapi_sso/sso/base.pyr   r   $   s    r'   r   c                       e Zd ZdZy)UnsetStateWarningz$Warning about unset state parameter.Nr    r!   r"   r#   r&   r'   r(   r*   r*   ,   s    .r'   r*   c                       e Zd ZdZy)ReusedOauthClientWarningz+Warning about reused oauth client instance.Nr+   r&   r'   r(   r-   r-   0   s    5r'   r-   c                       e Zd ZdZy)SSOLoginErrorzRaised when any login-related error ocurrs.

    Such as when user is not verified or if there was an attempt for fake login.
    Nr+   r&   r'   r(   r/   r/   4   s    r'   r/   c                       e Zd ZU dZdZee   ed<   dZee	j                     ed<   dZee   ed<   dZee   ed<   dZee   ed<   dZee   ed<   dZee   ed	<   y)
OpenIDzOClass (schema) to represent information got from sso provider in a common form.Nidemail
first_name	last_namedisplay_namepictureprovider)r    r!   r"   r#   r2   r	   r$   r%   r3   pydanticEmailStrr4   r5   r6   r7   r8   r&   r'   r(   r1   r1   ;   sn    YB)-E8H%%&- $J$#Ix}#"&L(3-&!GXc]!"Hhsm"r'   r1   c                       e Zd ZdZy)SecurityWarningz&Raised when insecure usage is detectedNr+   r&   r'   r(   r<   r<   G   s    0r'   r<   funcreturnc                 `     dt         j                  dt         j                  dt        f fd}|S )Nargskwargsr>   c                      | rt        | d   t              s | i |S | d   j                  st        j                  dt
        d        | i |S )Nr   zPlease make sure you are using SSO provider in an async context (using 'async with provider:'). See https://github.com/tomasvotava/fastapi-sso/issues/186 for more information.   )category
stacklevel)
isinstanceSSOBase	_in_stackwarningswarnr<   )r@   rA   r=   s     r(   wrapperz'requires_async_context.<locals>.wrapperL   sZ    :d1gw7(((Aw  MMb(	 T$V$$r'   )r   r@   rA   r   )r=   rK   s   ` r(   requires_async_contextrL   K   s,    
%qvv 
% 
%a 
% Nr'   c                      e Zd ZU dZeZeed<   eZeed<   eZ	eed<   eZ
eeej                  ef      ed<   g Zeee      ed<   dZeeeeef         ed<   d	Zeed
<   d	Zeed<   dZeed<   	 	 	 	 d;dededeeej                  ef      dededeee      fdZedee   fd       Zeedefd              Zeedee   fd              Z eedee   fd              Z!eedee   fd              Z"d<de#dee$jJ                     de&fdZ'de(fdZ)edee   fd       Z*edee   fd       Z+edee   fd       Z,dddddeeej                  ef      deeeef      d ee   defd!Z-dddddee   deeeef      d ee   de.fd"Z/e0dddd#d$d%e1deeeef      d&eeeef      dee   d'e2d#   dee&   fd(       Z3e0dddd)d%e1deeeef      d&eeeef      dee   d'e2d	   deeeef      fd*       Z3edddd#d$d%e1deeeef      d&eeeef      dee   d'ee2d#   e2d	   f   deee&   eeeef      f   fd+       Z3d=d,Z4d=d-Z5d.ee6e7      d/ee7   d0ee8   ddfd1Z9d.ee6e7      d/ee7   d0ee8   ddfd2Z:edefd3       Z;e0ddddd#d4d5ed%e1deeeef      deeeef      dee   d6ee   d'e2d#   dee&   fd7       Z<e0ddddd8d5ed%e1deeeef      deeeef      dee   d6ee   d'e2d	   deeeef      fd9       Z<eddddd#d4d5ed%e1deeeef      deeeef      dee   d6ee   d'ee2d#   e2d	   f   deee&   eeeef      f   fd:       Z<y)>rG   z!Base class for all SSO providers.r8   	client_idclient_secretredirect_uriscopeNadditional_headersF	uses_pkcerequires_state`   _pkce_challenge_lengthallow_insecure_http	use_statec                    || _         || _        || _        || _        t	        j
                         | _        d| _        d| _        d| _	        | j                  r=t        j                  d| j                  j                         dt        j                  d<   |rt!        j"                  dt$               |xs | j&                  | _        d| _        d| _        d| _        d| _        d| _        d| _        y)z)Base class (mixin) for all SSO providers.FNz-Initializing %s with allow_insecure_http=True1OAUTHLIB_INSECURE_TRANSPORTzArgument 'use_state' of SSOBase's constructor is deprecated and will be removed in future releases. Use 'state' argument of individual methods instead.S256)rN   rO   rP   rW   asyncioLock_login_lockrH   _oauth_client_generated_stateloggerdebug	__class__r    osenvironrI   rJ   DeprecationWarningrQ   _scope_refresh_token	_id_token_state_pkce_code_challenge_pkce_code_verifier_pkce_challenge_method)selfrN   rO   rP   rW   rX   rQ   s          r(   __init__zSSOBase.__init__i   s     ("/GS)< "<<>=A/3##LLH$..JaJab8;BJJ45 MM[ # )tzz-1(,%)37!26 &,#r'   r>   c                 f    | j                   t        j                  dt               | j                   S )ag  Retrieves the state as it was returned from the server.

        Warning:
            This will emit a warning if the state is unset, implying either that
            the server didn't return a state or `verify_and_process` hasn't been
            called yet.

        Returns:
            Optional[str]: The state parameter returned from the server.
        z'state' parameter is unset. This means the server either didn't return state (was this expected?) or 'verify_and_process' hasn't been called yet.)rk   rI   rJ   r*   ro   s    r(   statezSSOBase.state   s/     ;;MMk!
 {{r'   c                     | j                   t        k(  rt        d| j                   d      | j                  t        | j                         | _        | j                  S )a  Retrieves the OAuth Client to aid in generating requests and parsing responses.

        Raises:
            NotImplementedError: If the provider is not supported or `client_id` is not set.

        Returns:
            WebApplicationClient: OAuth client instance.
        	Provider  not supported)rN   NotImplementedNotImplementedErrorr8   r`   r   rr   s    r(   oauth_clientzSSOBase.oauth_client   sQ     >>^+%	$--&OPP%!5dnn!ED!!!r'   c                 .    | j                   j                  S )zRetrieves the access token from token endpoint.

        Returns:
            Optional[str]: The access token if available.
        )ry   access_tokenrr   s    r(   r{   zSSOBase.access_token   s       ---r'   c                 J    | j                   xs | j                  j                  S )zRetrieves the refresh token if returned from provider.

        Returns:
            Optional[str]: The refresh token if available.
        )ri   ry   refresh_tokenrr   s    r(   r}   zSSOBase.refresh_token   s!     ""Ed&7&7&E&EEr'   c                     | j                   S )zRetrieves the id token if returned from provider.

        Returns:
            Optional[str]: The id token if available.
        )rj   rr   s    r(   id_tokenzSSOBase.id_token   s     ~~r'   responsesessionc                 <   K   t        d| j                   d      w)a  Converts a response from the provider's user info endpoint to an OpenID object.

        Args:
            response (dict): The response from the user info endpoint.
            session (Optional[httpx.AsyncClient]): The HTTPX AsyncClient session.

        Raises:
            NotImplementedError: If the provider is not supported.

        Returns:
            OpenID: The user information in a standardized format.
        ru   rv   rx   r8   )ro   r   r   s      r(   openid_from_responsezSSOBase.openid_from_response   s       "Idmm_N"KLL   c                 <   K   t        d| j                   d      w)a  Retrieves the discovery document containing useful URLs.

        Raises:
            NotImplementedError: If the provider is not supported.

        Returns:
            DiscoveryDocument: A dictionary containing important endpoints like authorization, token and userinfo.
        ru   rv   r   rr   s    r(   get_discovery_documentzSSOBase.get_discovery_document   s       "Idmm_N"KLLr   c                 `   K   | j                          d{   }|j                  d      S 7 w)z8Return `authorization_endpoint` from discovery document.Nr   r   getro   	discoverys     r(   r   zSSOBase.authorization_endpoint   s.      5577	}}566 8   .,.c                 `   K   | j                          d{   }|j                  d      S 7 w)z0Return `token_endpoint` from discovery document.Nr   r   r   s     r(   r   zSSOBase.token_endpoint   s.      5577	}}-.. 8r   c                 `   K   | j                          d{   }|j                  d      S 7 w)z3Return `userinfo_endpoint` from discovery document.Nr   r   r   s     r(   r   zSSOBase.userinfo_endpoint   s.      5577	}}011 8r   rP   paramsrs   r   rs   c          	      T  K   |xs i }|xs | j                   }|t        d      | j                  rMt        | j                  | j
                  f      s,t        j                  | j                  j                  d       | j                  rF|sD| j                  ,t        j                  | j                  j                  d       | j                  } | j                  j                  | j                   d{   f||| j                  | j
                  | j                   d|}|S 7 /w)a  Generates and returns the prepared login URL.

        Args:
            redirect_uri (Optional[str]): Overrides the `redirect_uri` specified on this instance.
            params (Optional[Dict[str, Any]]): Additional query parameters to add to the login request.
            state (Optional[str]): The state parameter for the OAuth 2.0 authorization request.

        Raises:
            ValueError: If `redirect_uri` is not provided either at construction or request time.

        Returns:
            str: The prepared login URL.
        NzEredirect_uri must be provided, either at construction or request timez| uses PKCE and no code was generated yet. Use SSO class as a context manager to get rid of this warning and possible errors.z requires state in the request but none was provided nor generated automatically. Use SSO as a context manager. The login process will most probably fail.)rP   rs   rQ   code_challengecode_challenge_method)rP   
ValueErrorrS   allrm   rl   rI   rJ   rd   r    rT   ra   ry   prepare_request_urir   rh   rn   )ro   rP   r   rs   request_uris        r(   get_login_urlzSSOBase.get_login_url   s'    ( 2#8t'8'8dee>>#t'?'?AZAZ&["\MM>>**- .e e u$$,~~..1 2x x ))E;d'';;---
%++44"&"="=
 
  .s   C4D(6D&70D(c                   K   | j                   r|s| j                  }| j                  |||       d{   }t        |d      }| j                  r%|j                  dt        | j                               |S 7 Cw)a  Constructs and returns a redirect response to the login page of OAuth SSO provider.

        Args:
            redirect_uri (Optional[str]): Overrides the `redirect_uri` specified on this instance.
            params (Optional[Dict[str, Any]]): Additional query parameters to add to the login request.
            state (Optional[str]): The state parameter for the OAuth 2.0 authorization request.

        Returns:
            RedirectResponse: A Starlette response directing to the login page of the OAuth SSO provider.
        r   Ni/  pkce_code_verifier)rT   ra   r   r   rS   
set_cookier$   rm   )ro   rP   r   rs   	login_urir   s         r(   get_login_redirectzSSOBase.get_login_redirect/  ss     " u))E,,,v]b,cc	#Is3>> 4c$:R:R6ST	 ds   2A:A8AA:T)r   headersrP   convert_responserequestr   r   c                   K   y wNr&   ro   r   r   r   rP   r   s         r(   verify_and_processzSSOBase.verify_and_processH  s         )r   r   rP   c                   K   y wr   r&   r   s         r(   r   zSSOBase.verify_and_processS  s      $'r   c          	        K   |xs i }|j                   j                  d      }|Bt        j                  d|j                  |j
                  |j                          t        dd      |j                   j                  d      | _        d}| j                  r2|j                  j                  d      }|t        j                  d       | j                  |||||||	       d{   S 7 w)
at  Processes the login given a FastAPI (Starlette) Request object. This should be used for the /callback path.

        Args:
            request (Request): FastAPI or Starlette request object.
            params (Optional[Dict[str, Any]]): Additional query parameters to pass to the provider.
            headers (Optional[Dict[str, Any]]): Additional headers to pass to the provider.
            redirect_uri (Optional[str]): Overrides the `redirect_uri` specified on this instance.
            convert_response (bool): If True, userinfo response is converted to OpenID object.

        Raises:
            SSOLoginError: If the 'code' parameter is not found in the callback request.

        Returns:
            Optional[OpenID]: User information as OpenID instance (if convert_response == True)
            Optional[Dict[str, Any]]: The original JSON response from the API.
        codeNz9Callback request:
	URI: %s
	Headers: %s
	Query params: %si  z2'code' parameter was not found in callback requestrs   r   zaPKCE code verifier was not found in the request Cookie. This will probably lead to a login error.r   rR   rP   r   r   )query_paramsr   rb   rc   urlr   r/   rk   rS   cookiesrI   rJ   process_login)ro   r   r   r   rP   r   r   r   s           r(   r   zSSOBase.verify_and_process^  s     4 -R##''/<LLQ$$	  %YZZ**..w7,0>>!(!4!45I!J!)w ''&%1- ( 
 
 	
 
s   C!C*#C($C*c                    t        j                  dt        d       d | _        d | _        d | _        d | _        | j                  rt               | _	        | j                  r"t        | j                        \  | _        | _        | S )NzSSO Providers are supposed to be used in async context, please change 'with provider' to 'async with provider'. See https://github.com/tomasvotava/fastapi-sso/issues/186 for more information.rC   )rE   )rI   rJ   rg   r`   ri   rj   rk   rT   r   ra   rS   r   rV   rm   rl   rr   s    r(   	__enter__zSSOBase.__enter__  sv    u		
 ""$9$;D!>>BYZ^ZuZuBv?D$d&?r'   c                 .  K   | j                   j                          d {    d| _        d | _        d | _        d | _        d | _        | j                  rt               | _	        | j                  r"t        | j                        \  | _        | _        | S 7 rw)NT)r_   acquirerH   r`   ri   rj   rk   rT   r   ra   rS   r   rV   rm   rl   rr   s    r(   
__aenter__zSSOBase.__aenter__  s     &&(((!"$9$;D!>>BYZ^ZuZuBv?D$d&? 	)s   BBA3B	_exc_type_exc_val_exc_tbc                 N   K   d| _         | j                  j                          y w)NF)rH   r_   releasero   r   r   r   s       r(   	__aexit__zSSOBase.__aexit__  s!        "s   #%c                      y r   r&   r   s       r(   __exit__zSSOBase.__exit__  s     r'   c                     i S r   r&   rr   s    r(   _extra_query_paramszSSOBase._extra_query_params  s    	r'   r   r   r   c                   K   y wr   r&   ro   r   r   r   rR   rP   r   r   s           r(   r   zSSOBase.process_login  s      r   )r   rR   rP   r   c                   K   y wr   r&   r   s           r(   r   zSSOBase.process_login  s      $'r   c                R  K   | j                   /d| _         d| _        d| _        t        j                  dt
               |xs i }|j                  | j                         |xs i }|j                  | j                  xs i        |j                  }| j                  s+|j                  dk7  rt        |      j                  dd      }	nt        |      }	|j                   d|j                   |j                   }
|r|j                  d|i        | j                   j"                  | j$                   d{   f|	|xs | j&                  xs |
|d|\  }}}|y|j                  |       t)        j*                  | j,                  | j.                        }t)        j0                         4 d{   }|j3                  ||||	       d{   }|j5                         }|j7                  d
      | _        |j7                  d      | _        | j                   j9                  t5        j:                  |             | j                   j=                  | j>                   d{         \  }}}|j                  |       |j@                  j                  |       |j7                  |       d{   }|j5                         }|r+| jC                  ||       d{   cddd      d{    S |cddd      d{    S 7 7 U7 ;7 7 _7 57 '7 # 1 d{  7  sw Y   yxY ww)a  Processes login from the callback endpoint to verify the user and request user info endpoint.
        It's a lower-level method, typically, you should use `verify_and_process` instead.

        Args:
            code (str): The authorization code.
            request (Request): FastAPI or Starlette request object.
            params (Optional[Dict[str, Any]]): Additional query parameters to pass to the provider.
            additional_headers (Optional[Dict[str, Any]]): Additional headers to be added to all requests.
            redirect_uri (Optional[str]): Overrides the `redirect_uri` specified on this instance.
            pkce_code_verifier (Optional[str]): A PKCE code verifier sent to the server to verify the login request.
            convert_response (bool): If True, userinfo response is converted to OpenID object.

        Raises:
            ReusedOauthClientWarning: If the SSO object is reused, which is not safe and caused security issues.

        Returns:
            Optional[OpenID]: User information in OpenID format if the login was successful (convert_response == True).
            Optional[Dict[str, Any]]: Original userinfo API endpoint response.
        NzReusing the SSO object is not safe and caused a security issue in previous versions.To make sure you don't see this warning, please use the SSO object as a context manager.httpszhttp://zhttps://z://code_verifier)authorization_responseredirect_urlr   )r   contentauthr}   r   )"r`   ri   rj   rI   rJ   r-   updater   rR   r   rW   schemer$   replacenetlocpathry   prepare_token_requestr   rP   httpx	BasicAuthrN   rO   AsyncClientpostjsonr   parse_request_body_responsedumps	add_tokenr   r   r   )ro   r   r   r   rR   rP   r   r   r   current_urlcurrent_path	token_urlr   bodyr   r   r   r   uri_s                       r(   r   zSSOBase.process_login  s    > )!%D"&D!DNMMo ) 2d..//52!!$"9"9"?R@kk''CJJ',Ac(**9jAKc(K**SSXXJ?MM?,>?@#J4#4#4#J#J%%%$
#.%J):):Jl	$

 $
 	7D )*t~~t/A/AB$$& 	 	'$\\)WdY]\^^HmmoG")++o">D$[[4DN99$**W:MN"//99@V@V:VWOC!NN-.OO""7+$[[--HmmoG!66wHH	 	 	 	 	 	 &	^ ;W . I	 	 	 	 	s   D1L'3K?4A9L'-L.L'1L
LBLL
AL*L
++LLLL'&L'L',L-L'9L:L'L'LL
LLL'L'L$LL$ L')NFFNr   )r>   rG   )=r    r!   r"   r#   rw   r8   r$   r%   rN   rO   rP   r	   r   r9   
AnyHttpUrlrQ   r   r   rR   r   r   rS   boolrT   rV   intrp   propertyrs   rL   r   ry   r{   r}   r   dictr   r   r1   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
   BaseExceptionr   r   r   r   r   r&   r'   r(   rG   rG   [   sc   +"Hc"#Is#'M3'>LL(5!4!4c!9:;L!#E8DI#=A$sCx.!9:AIt ND "$C$ CG$)%)&-&- &- uX%8%8#%=>?	&-
 "&- &- S	"&-P x}  & "2 "  " .hsm .  . Fx} F  F (3-   M4 M(5K\K\B] Mio M	M.? 	M 7hsm 7 7
 /hsm / /
 2# 2 2 CG+/#- uX%8%8#%=>?- c3h(	-
 }- 
-d '++/# sm c3h(	
 } 
2 
 ,0,0&**. c3h(	
 $sCx.) sm "$- 
&	  
 ,0,0&*'' c3h(	'
 $sCx.)' sm' "%.' 
$sCx.	!' ' 
 ,0,0&*AE3
3
 c3h(	3

 $sCx.)3
 sm3
  wu~ =>3
 
x$sCx.!99	:3
 3
j"#D/0# =)# -(	#
 
#D/0 =) -(	
 
 T    ,07;&*,0*.

 

 c3h(
 %T#s(^4
 sm
 %SM
 "$-
 
&	
 
  ,07;&*,0
'
' 
'
 c3h(
' %T#s(^4
' sm
' %SM
' "%.
' 
$sCx.	!
' 
'  ,07;&*,0AEWW W
 c3h(W %T#s(^4W smW %SMW  wu~ =>W 
x$sCx.!99	:W Wr'   rG   )7r#   r]   r   loggingre   sysrI   typesr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r9   oauthlib.oauth2r   starlette.exceptionsr   starlette.requestsr   starlette.responsesr   fastapi_sso.pkcer   fastapi_sso.stater   version_infor   typing_extensionsr   collections.abc	getLoggerr    rb   r   r   r   UserWarningr*   r-   r/   	BaseModelr1   r<   rL   rG   r&   r'   r(   <module>r      s         	 
   j j j j   0 . & 0 4 3g+( 			8	$CLcN	 / /6{ 6M 	#X 	#1k 1!Q$ HQTN  ^ ^r'   