
    #	hJ                        S r SSKrSSKrSSKrSSKrSSKJr  SSKrSSKr SSK	J
r
Jr  SSKJrJrJr  SSKJr  \R,                  " \5      rS?S	 jrS
 rS rS?S jrS rS rS rS r  " S S\5      r! " S S\
\"5      r# " S S\#5      r$ " S S\"5      r%\S:X  Ga  SSK&r&SSK'r'SSK(J)r)  \RT                  " \RV                  S9  \&RX                  " \&RZ                  \ S-   S9=r.r/\.Ra                  SS S!S"9  \.Ra                  S#S$S%9  \.Ra                  S&\1SS'S(9  \.Ra                  S)\1S*S+S(9  \.Ra                  S,S-S.S/9  \.Ra                  S0SS1S/9  \/Re                  5       r3\)" S2\3Rh                  0\3Rj                  5      r6\%" \3Rn                  S39 r8\6Rs                  \3Rt                  (       a  \3Rt                  Rw                  5       OSS4Ry                  \3Rz                  \8R}                  5       S59S69r?\@" \'R                  " \8R                  \?S7   S8S9S:\3R                  \?S;   S<9S=S>95        SSS5        gg! \ a     SSKJ
r
Jr  SSKJrJr  SSKJr  SSKJr   GNf = f! , (       d  f       g= f)@a$  A one-stop helper for desktop app to acquire an authorization code.

It starts a web server to listen redirect_uri, waiting for auth code.
It optionally opens a browser window to guide a human user to manually login.
After obtaining an auth code, the web server will automatically shut down.
    N)Template)
HTTPServerBaseHTTPRequestHandler)urlparseparse_qs	urlencode)escape)r   r   )r   c                     [        U S9 nUR                  USS9R                  S5      sS S S 5        $ ! , (       d  f       g = f)Nportz<html><body>
                Open this link to <a href='$auth_uri'>Sign In</a>
                (You may want to use incognito window)
                <hr><a href='$abort_uri'>Abort</a>
                </body></html>)auth_uriwelcome_templatecode)AuthCodeReceiverget_auth_responseget)listen_portr   receivers      I/var/www/html/env/lib/python3.13/site-packages/msal/oauth2cli/authcode.pyobtain_auth_coder      s>    	{	+x))" *  c&k 
,	+	+s	   3
Ac                  \    [        S5       n U R                  5        HD  nUR                  SS5      S   R                  5       nUR                  5       S:w  d  M<    S S S 5        g   S S S 5        [
        R                  R                  S5      $ ! , (       d  f       N-= f! [         a     N<f = f)Nz/proc/1/cgroup:   /Tz/.dockerenv)open	readlinessplitstripIOErrorospathexists)flinecgroup_paths      r   _is_inside_dockerr&   *   s    	"#q "jja0399;$$&#- $# & $ 77>>-(( $#  sA   B A	BBB $B&B 
BB B 
B+*B+c                      SS K n U R                  5       n[        USUS   5      R                  5       n[        USUS   5      R                  5       nUS:H  =(       a    SU;   $ )Nr   systemreleaser   linux	microsoft)platformunamegetattrlower)r,   r-   platform_namer)   s       r   is_wslr1   8   s^    
 NNEE8U1X6<<>MeYa1779GG#>w(>>    c                 .   SSK nU(       a!  UR                  U5      R                  U 5      nOUR                  U 5      nU(       d?  [        5       (       a0   SSKnUR                  SSSSR                  U 5      /5      nUS:H  nU$ U$ ! [         a     U$ f = f)zJBrowse uri with named browser. Default browser is customizable by $BROWSERr   Nzpowershell.exez
-NoProfilez-CommandzStart-Process "{}")
webbrowserr   r   r1   
subprocesscallformatFileNotFoundError)r   browser_namer4   browser_openedr5   	exit_codes         r   _browser<   D   s    #5::8D $2 fhh	 #!<=Q=X=XYa=bceI&!^N > ! 		s   -B 
BBc           	          U R                  5        VVs0 s H1  u  pU[        U[        5      (       a  [        U5      S:X  a  US   OU_M3     snn$ s  snnf )z;Flatten parse_qs()'s single-item lists into the item itself   r   )items
isinstancelistlen)qskvs      r   _qs2kvrF   [   sR     HHJ DA z!T**s1v{qtA     s   8Ac                 $    U R                  S5      $ )N<)
startswithtexts    r   _is_htmlrL   a   s    ??3r2   c                 l    U R                  5        VVs0 s H  u  pU[        U5      _M     snn$ s  snnf N)r?   r	   )key_value_pairsrD   rE   s      r   _escaperP   e   s/    %4%:%:%<=%<TQAvayL%<===s   0c                 p    [        U [        5      (       a   U R                  5       (       d  [        U 5      $ U $ rN   )r@   strisprintablereprrJ   s    r   	_printifyrU   i   s+    #D#..t7G7G7I7I4:StSr2   c                   *    \ rS rSrS rSS jrS rSrg)_AuthCodeHandlern   c                    [        [        U R                  5      R                  5      nUR	                  S5      (       d  UR	                  S5      (       Ga  [        U5      n[        R                  SU5        U R                  R                  (       a;  U R                  R                  UR	                  S5      :w  a  U R                  S5        g SU;   a  U R                  R                  OU R                  R                  n[        UR                  5      (       a  [        U5      nOUnU R                  UR                   " S0 UD65        X R                  l        g U R                  U R                  R$                  5        g )Nr   errorzGot auth response: %sstatezState mismatch )r   r   r!   queryr   rF   loggerdebugserver
auth_state_send_full_responsesuccess_templateerror_templaterL   templaterP   safe_substituteauth_responsewelcome_page)selfrC   rg   re   	safe_datas        r   do_GET_AuthCodeHandler.do_GETo   s    htyy)//066&>>RVVG__"2JMLL0-@{{%%$++*@*@MDUDUV]D^*^ (()9: | !KK88)-)C)C H--.. ' 6I -I(()A)A)NI)NO,9)$$T[[%=%=>r2   c                     U R                  U(       a  SOS5        [        U5      (       a  SOSnU R                  SU5        U R                  5         U R                  R                  UR                  S5      5        g )N   i  z	text/htmlz
text/plainzContent-typezutf-8)send_responserL   send_headerend_headerswfilewriteencode)ri   bodyis_okcontent_types       r   rb   $_AuthCodeHandler._send_full_response   sZ    %3S1&.tnn{,6

W-.r2   c                 N    [         R                  " U/[        [        U5      Q76   g rN   )r^   r_   maprU   )ri   r7   argss      r   log_message_AuthCodeHandler.log_message   s    V3c)T23r2   r\   N)T)__name__
__module____qualname____firstlineno__rk   rb   r|   __static_attributes__r\   r2   r   rW   rW   n   s    ?0/4r2   rW   c                   .   ^  \ rS rSrU 4S jrS rSrU =r$ )_AuthCodeHttpServer   c                    > Uu  pEU(       a*  [         R                  S:X  d  [        5       (       a  SU l        [        [
        U ]  " U/UQ70 UD6  g )Nwin32F)sysr,   r1   allow_reuse_addresssuperr   __init__)ri   server_addressr{   kwargs_r   	__class__s         r   r   _AuthCodeHttpServer.__init__   sB     S\\W,
 (-D$!41.R4R6Rr2   c                     [        S5      e)Nz"Timeout. No auth response arrived.)RuntimeErrorri   s    r   handle_timeout"_AuthCodeHttpServer.handle_timeout   s     ?@@r2   )r   )r~   r   r   r   r   r   r   __classcell__)r   s   @r   r   r      s    SA Ar2   r   c                   ,    \ rS rSr\R
                  rSrg)_AuthCodeHttpServer6   r\   N)r~   r   r   r   socketAF_INET6address_familyr   r\   r2   r   r   r      s    __Nr2   r   c                   R    \ rS rSrSS jrS rSS jr    SS jrS rS r	S	 r
S
rg)r      Nc                     [        5       (       a  SOSn[        U=(       d    / 5      U l        SU;   a  [        O[        nU" X1=(       d    S4[
        5      U l        SU l        g)a  Create a Receiver waiting for incoming auth response.

:param port:
    The local web server will listen at http://...:<port>
    You need to use the same port when you register with your app.
    If your Identity Provider supports dynamic port, you can use port=0 here.
    Port 0 means to use an arbitrary unused port, per this official example:
    https://docs.python.org/2.7/library/socketserver.html#asynchronous-mixins

:param scheduled_actions:
    For example, if the input is
    ``[(10, lambda: print("Got stuck during sign in? Call 800-000-0000"))]``
    then the receiver would call that lambda function after
    waiting the response for 10 seconds.
z0.0.0.0	127.0.0.1r   r   FN)r&   sorted_scheduled_actionsr   r   rW   _server_closing)ri   r   scheduled_actionsaddressServers        r   r   AuthCodeReceiver.__init__   sV       122) #)):)@b"A),%=P w	24DEr2   c                 4    U R                   R                  S   $ )z*The port this server actually listening tor>   )r   r   r   s    r   get_portAuthCodeReceiver.get_port   s     ||**1--r2   c                    0 n[         R                  " U R                  U4US9nSUl        UR	                  5         [
        R
                  " 5       nU(       a  [
        R
                  " 5       U-
  U:  a  O [
        R                  " S5        UR                  5       (       d  OU R                  (       a  [
        R
                  " 5       U-
  U R                  S   S   :  ac  U R                  R                  S5      u  pgU" 5         U R                  (       a.  [
        R
                  " 5       U-
  U R                  S   S   :  a  Mc  U(       a  [
        R
                  " 5       U-
  U:  a  M  OM  U=(       d    S$ )a  Wait and return the auth response. Raise RuntimeError when timeout.

:param str auth_uri:
    If provided, this function will try to open a local browser.
:param int timeout: In seconds. None means wait indefinitely.
:param str state:
    You may provide the state you used in auth_uri,
    then we will use it to validate incoming response.
:param str welcome_template:
    If provided, your end user will see it instead of the auth_uri.
    When present, it shall be a plaintext or html template following
    `Python Template string syntax <https://docs.python.org/3/library/string.html#template-strings>`_,
    and include some of these placeholders: $auth_uri and $abort_uri.
:param str success_template:
    The page will be displayed when authentication was largely successful.
    Placeholders can be any of these:
    https://tools.ietf.org/html/rfc6749#section-5.1
:param str error_template:
    The page will be displayed when authentication encountered error.
    Placeholders can be any of these:
    https://tools.ietf.org/html/rfc6749#section-5.2
:param callable auth_uri_callback:
    A function with the shape of lambda auth_uri: ...
    When a browser was unable to be launch, this function will be called,
    so that the app could tell user to manually visit the auth_uri.
:param str browser_name:
    If you did
    ``webbrowser.register("xyz", None, BackgroundBrowser("/path/to/browser"))``
    beforehand, you can pass in the name "xyz" to use that browser.
    The default value ``None`` means using default browser,
    which is customizable by env var $BROWSER.
:return:
    The auth response of the first leg of Auth Code flow,
    typically {"code": "...", "state": "..."} or {"error": "...", ...}
    See https://tools.ietf.org/html/rfc6749#section-4.1.2
    and https://openid.net/specs/openid-connect-core-1_0.html#AuthResponse
    Returns None when the state was mismatched, or when timeout occurred.
)targetr{   r   Tr>   r   N)
	threadingThread_get_auth_responsedaemonstarttimesleepis_aliver   pop)ri   timeoutr   resulttbeginr   callbacks           r   r   "AuthCodeReceiver.get_auth_response   s   j **&6K				18tyy{U"W,dJJqM::<<**		e+d.E.Ea.H.KK"5599!<
 **		e+d.E.Ea.H.KK 29tyy{U"W,d ~r2   c
                 
   SR                  U R                  5       S9n
SR                  U
S9n[        R                  SU5        [	        U=(       d    S5      R                  X+S9U R                  l        U(       aw  U(       a  U
OUn[        R                  SU-  5        S	n [        XS
9nU(       dA  U(       d2  [        R                  SR                  XU R                  5       S95        OU" U5        [	        U=(       d    S5      U R                  l        [	        U=(       d    S5      U R                  l        X0R                  l        0 U R                  l        X@R                  l        U R"                  (       dI  U R                  R%                  5         U R                  R                  (       a  OU R"                  (       d  MI  UR'                  U R                  R                  5        g !   [        R                  S5         GNY= f)Nzhttp://localhost:{p})pz{loc}?error=abort)loczAbort by visit %s )r   	abort_uriz*Open a browser on this device to visit: %sF)r9   z_browse(...) unsuccessfula  Found no browser in current environment. If this program is being run inside a container which either (1) has access to host network (i.e. started by `docker run --net=host -it ...`), or (2) published port {port} to host network (i.e. started by `docker run -p 127.0.0.1:{port}:{port} -it ...`), you can use browser on host to visit the following link. Otherwise, this auth attempt would either timeout (current timeout setting is {timeout}) or be aborted by CTRL+C. Auth URI: {auth_uri})r   r   r   z8Authentication completed. You can close this window now.z?Authentication failed. $error: $error_description. ($error_uri))r7   r   r^   r_   r   rf   r   rh   infor<   	exceptionwarningrc   rd   r   rg   ra   r   handle_requestupdate)ri   r   r   r   r[   r   rc   rd   auth_uri_callbackr9   welcome_urir   _urir:   s                 r   r   #AuthCodeReceiver._get_auth_response  s   
 -33dmmo3F'..;.?	()4$,-=-C$D$T$T %U %4!"2;DKKDtKL"N>!(!I
 "(NN	H IO%) IO IRS &d+(01A 2GF)H%&.~ 0NM'O#  '%'""'-- LL'')||)) --- 	dll001I>   !<=s    	G( (Hc                 F    SU l         U R                  R                  5         g)zGEither call this eventually; or use the entire class as context managerTN)r   r   server_closer   s    r   closeAuthCodeReceiver.closeP  s    !!#r2   c                     U $ rN   r\   r   s    r   	__enter__AuthCodeReceiver.__enter__U  s    r2   c                 $    U R                  5         g rN   )r   )ri   exc_typeexc_valexc_tbs       r   __exit__AuthCodeReceiver.__exit__X  s    

r2   )r   r   r   )NNrN   )NNNNNNNN)r~   r   r   r   r   r   r   r   r   r   r   r   r\   r2   r   r   r      s9    !F.
CJ MQIM"42l$
r2   r   __main__r>   )Client)levelz/The auth code received will be shown at stdout.)formatter_classdescriptionz
--endpointzThe auth endpoint for your app.z>https://login.microsoftonline.com/common/oauth2/v2.0/authorize)helpdefault	client_idz!The client_id of your application)r   z--portzThe port in redirect_uri)typer   r   z	--timeout<   zTimeout value, in secondz--hostr   zThe host of redirect_uri)r   r   z--scopezThe scope listauthorization_endpointr   zhttp://{h}:{p})hr   )scoperedirect_urir   zA<a href='$auth_uri'>Sign In</a>, or <a href='$abort_uri'>Abort</az<html>Oh no. $error</html>zOh yeah. Got $coder[   )r   r   rd   rc   r   r[      )indentrN   )D__doc__loggingr    r   r   stringr   r   r   http.serverr   r   urllib.parser   r   r   htmlr	   ImportErrorBaseHTTPServerurllibcgi	getLoggerr~   r^   r   r&   r1   r<   rF   rL   rP   rU   rW   objectr   r   r   argparsejsonoauth2r   basicConfigINFOArgumentParserArgumentDefaultsHelpFormatterr   parseradd_argumentint
parse_argsr{   endpointr   clientr   r   initiate_auth_code_flowr   r   r7   hostr   flowprintdumpsr   r   r\   r2   r   <module>r     sz    	  
   >:: 
		8	$	)	?.  >T
"4- "4JA*f A(%. %nv nd zgll+(( >>OOQ QA NN<P  R NN;%HNINN8#q7QNRNN;S";UNVNN8[7QNRNN9d1ANBD-t}}=t~~NF	tyy	)X--(,

$**""$)00499@Q@Q@S0T .  	djj33*%S71LLw- 4   	 
*	)# S
  A+ 	t
 
*	)s   H/ 
BI/"II
I&