
    Mhi                    |   d Z ddlm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	Z
ddlZddlmZmZ ddlmZ ddlmZmZmZ ddlmZmZmZmZmZ ddlmZ dd	lmZ d
dlm Z m!Z! d
dl"m#Z#  ej$        d          Z%e G d d                      Z&ddZ' G d de          Z( G d de(          Z) G d de)          Z*dS )zIdentity Provider interface

This defines the _authentication_ layer of Jupyter Server,
to be used in combination with Authorizer for _authorization_.

.. versionadded:: 2.0
    )annotationsN)asdict	dataclass)Morsel)escapehttputilweb)BoolDictTypeUnicodedefault)LoggingConfigurable)_i18n   )passwd_checkset_password)get_anonymous_usernamez[^A-Za-z0-9]c                  p    e Zd ZU dZded<   dZded<   dZded<   dZded	<   dZded
<   dZ	ded<   d Z
d ZdS )UserziObject representing a User

    This or a subclass should be returned from IdentityProvider.get_user
    strusername namedisplay_nameN
str | Noneinitials
avatar_urlcolorc                .    |                                   d S N)fill_defaultsselfs    \/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/jupyter_server/auth/identity.py__post_init__zUser.__post_init__:   s        c                    | j         sd|  }t          |          | j        s| j         | _        | j        s| j        | _        dS dS )zFill out default fields in the identity model

        - Ensures all values are defined
        - Fills out derivative values for name fields fields
        - Fills out null values for optional fields
        z!user.username must not be empty: N)r   
ValueErrorr   r   )r$   msgs     r%   r"   zUser.fill_defaults=   sa     } 	"<d<<CS//! y 	&DI  	* $	D	* 	*r'   )__name__
__module____qualname____doc____annotations__r   r   r   r   r   r&   r"    r'   r%   r   r   "   s          
 MMM DNNNN L  H!J!!!!E
  * * * * *r'   r   got_usert.Anyreturnc                d   t          | t                    rt          |           S t          | t                    rci }d| vrd| v r| d         |d<   t          j        D ]}|| v r| |         ||<   	 t          di |S # t
          $ r d|  }t          |          dw xY wd|  }t          |          )a  Backward-compatibility for LoginHandler.get_user

    Prior to 2.0, LoginHandler.get_user could return anything truthy.

    Typically, this was either a simple string username,
    or a simple dict.

    Make some effort to allow common patterns to keep working.
    )r   r   r   zUnrecognized user: Nr0   )
isinstancer   r   dict__dataclass_fields__	TypeErrorr)   )r1   kwargsfieldr*   s       r%   _backward_compat_userr;   Q   s     (C   X&&&&	Hd	#	# X%%&H*<*<!)&!1F:. 	0 	0E   (u	,>>&>>! 	, 	, 	,222CS//t+	, /H..oos   /A; ; Bc                     e Zd ZU dZ edd ed                    Zded<    ed ed                    Z	 e
d	dd ed
                    Zded<    ed ed                    Z ed ed                                        d          Zded<    edej        d ed                    Z edej        d ed                    ZdZ ed          d             Z e
d          Zded<   dId!ZdJd#ZdKd'ZdLd)ZdMd+ZdNd-ZdOd.ZdPd0Z	 dQdRd6Z dSd7Z!dId8Z" e#j$        d9e#j%                  Z&dTd:Z'dJd;Z(dUd<Z)dVd>Z*dVd?Z+	 dWdXdDZ,dJdEZ-e.dF             Z/e.dG             Z0e.dH             Z1d	S )YIdentityProvideraC  
    Interface for providing identity management and authentication.

    Two principle methods:

    - :meth:`~jupyter_server.auth.IdentityProvider.get_user` returns a :class:`~.User` object
      for successful authentication, or None for no-identity-found.
    - :meth:`~jupyter_server.auth.IdentityProvider.identity_model` turns a :class:`~jupyter_server.auth.User` into a JSONable dict.
      The default is to use :py:meth:`dataclasses.asdict`,
      and usually shouldn't need override.

    Additional methods can customize authentication.

    .. versionadded:: 2.0
    r   TzJName of the cookie to set for persisting login. Default: username-${Host}.confighelpzstr | Unicode[str, str | bytes]cookie_nameziExtra keyword arguments to pass to `set_secure_cookie`. See tornado's set_secure_cookie docs for details.NzSpecify whether login cookie should have the `secure` property (HTTPS-only).Only needed when protocol-detection gives the wrong answer due to proxies.)
allow_noner?   r@   z+bool | Bool[bool | None, bool | int | None]secure_cookieziExtra keyword arguments to pass to `get_secure_cookie`. See tornado's get_secure_cookie docs for details.z<generated>a  Token used for authenticating first-time connections to the server.

        The token can be read from the file referenced by JUPYTER_TOKEN_FILE or set directly
        with the JUPYTER_TOKEN environment variable.

        When no password is enabled,
        the default is to generate a new, random token.

        Setting to an empty string disables authentication altogether, which is NOT RECOMMENDED.

        Prior to 2.0: configured as ServerApp.token
        )r@   )r?   tokenz*jupyter_server.auth.login.LoginFormHandlerz'The login handler class to use, if any.)default_valueklassr?   r@   z(jupyter_server.auth.logout.LogoutHandlerz The logout handler class to use.Fc                   t          j        d          rd| _        t           j        d         S t          j        d          rRd| _        t	          t           j        d                   5 }|                                cd d d            S # 1 swxY w Y   | j        s	d| _        dS d| _        t          j        t          j	        d                    
                    d          S )NJUPYTER_TOKENFJUPYTER_TOKEN_FILEr   T   ascii)osgetenvtoken_generatedenvironopenread
need_tokenbinasciihexlifyurandomdecode)r$   
token_files     r%   _token_defaultzIdentityProvider._token_default   s   9_%% 	/#(D :o..9)** 	)#(D bj!5677 ):!(() ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 	D#(D 2#'D #BJrNN33::7CCCs   (B		BBz%bool | Bool[bool, t.Union[bool, int]]rR   handlerweb.RequestHandlerr3   &User | None | t.Awaitable[User | None]c                ,    |                      |          S )zGet the authenticated user for a request

        Must return a :class:`jupyter_server.auth.User`,
        though it may be a subclass.

        Return None if the request is not authenticated.

        _may_ be a coroutine
        )	_get_userr$   rY   s     r%   get_userzIdentityProvider.get_user   s     ~~g&&&r'   User | Nonec                  K   t          |dd          rt          j        t          |j                  S |                     |          }t          |t          j                  r| d{V }|}|                     |          }t          |t          j                  r| d{V }|}|p|}|%|#||k    r| 	                    ||           d|_
        ||                     |          }|                    |          }|2| j                            d|            |                     |           | j        s+|                     |          }| 	                    ||           |S )Get the user._jupyter_current_userNTz&Clearing invalid/expired login cookie )getattrtcastr   rc   get_user_tokenr5   	Awaitableget_user_cookieset_login_cookie_token_authenticatedget_cookie_name
get_cookielogwarningclear_login_cookieauth_enabledgenerate_anonymous_user)	r$   rY   _token_user
token_user_cookie_usercookie_useruserrA   cookies	            r%   r]   zIdentityProvider._get_user   s     73T:: 	?6$ =>>>>B>Q>QRY>Z>Zk1;// 	, +++++++K"-
++G44lAK00 	.!-------L#/ ([
 6 {""%%gt444 ,0G(< ..w77K''44F!  !W+!W!WXXX''000$ 5 33G<< %%gt444r'   rw   r   dict[str, t.Any]c                     t          |          S )z"Return a User as an Identity model)r   )r$   rw   s     r%   identity_modelzIdentityProvider.identity_model  s     d||r'   list[tuple[str, object]]c                    g }| j         r|                    d| j        f           | j        r|                    d| j        f           |S )zwReturn list of additional handlers for this identity provider

        For example, an OAuth callback handler.
        z/loginz/logout)login_availableappendlogin_handler_classlogout_availablelogout_handler_class)r$   handlerss     r%   get_handlerszIdentityProvider.get_handlers  sZ    
  	COOY(@ABBB  	EOOZ)BCDDDr'   r   c                l    t          j        |j        |j        |j        |j        |j        d          }|S )zSerialize a user to a string for storage in a cookie

        If overriding in a subclass, make sure to define user_from_cookie as well.

        Default is just the user's username.
        )r   r   r   r   r   )jsondumpsr   r   r   r   r   )r$   rw   rx   s      r%   user_to_cookiezIdentityProvider.user_to_cookie!  s@      M	 $ 1 M 
 
 r'   cookie_valuec           	         t          j        |          }t          |d         |d         |d         |d         d|d                   S )zInverse of user_to_cookier   r   r   r   Nr   )r   loadsr   )r$   r   rw   s      r%   user_from_cookiez!IdentityProvider.user_from_cookie4  sL    z,''L M
 
 	
r'   c                n    | j         r| j         S t                              dd|j        j                   S )zReturn the login cookie name

        Uses IdentityProvider.cookie_name, if defined.
        Default is to generate a string taking host into account to avoid
        collisions for multiple servers on one hostname with different ports.
        -z	username-)rA   _non_alphanumsubrequesthostr^   s     r%   rl   z IdentityProvider.get_cookie_name@  s=      	N## $$S*Lgo6J*L*LMMMr'   Nonec                p   i }|                     | j                   |                    dd           | j        }||j        j        dk    }|r|                    dd           |                    d|j                   |                     |          } |j        || 	                    |          fi | dS )z9Call this on handlers to set the login cookie for successhttponlyTNhttpssecurepath)
updatecookie_options
setdefaultrC   r   protocolbase_urlrl   set_secure_cookier   )r$   rY   rw   r   rC   rA   s         r%   rj   z!IdentityProvider.set_login_cookieL  s    d1222!!*d333 * #O4?M 	6%%h555!!&'*:;;;**733!!+t/B/B4/H/H[[N[[[[[r'   /r   r   domainr   c                   t          j        |          }t          j                            t          j        j                  t          j        d          z
  }t                      }|                    |dd           t          j
        |          |d<   ||d<   |r||d<   |                    d	|                                           d
S )a  Deletes the cookie with the given name.

        Tornado's cookie handling currently (Jan 2018) stores cookies in a dict
        keyed by name, so it can only modify one cookie with a given name per
        response. The browser can store multiple cookies with the same name
        but different domains and/or paths. This method lets us clear multiple
        cookies with the same name.

        Due to limitations of the cookie protocol, you must pass the same
        path and domain to clear a cookie as were used when that cookie
        was set (but there is no way to find out on the server side
        which values were used for a given cookie).
        )tzim  )daysr   z""expiresr   r   z
Set-CookieN)r   
native_strdatetimenowtimezoneutc	timedeltar   setr   format_timestamp
add_headerOutputString)r$   rY   r   r   r   r   morsels          r%   _force_clear_cookiez$IdentityProvider._force_clear_cookie\  s       &&#''8+<+@'AAHDV\_D`D`D`` &

4T"""$5g>>yv 	&%F8<)<)<)>)>?????r'   c                   i }|                     | j                   |                    d|j                  }|                     |          }|                    ||           |r|dk    r|                     ||           dS dS dS )z<Clear the login cookie, effectively logging out the session.r   )r   r   N)r   r   r   r   rl   clear_cookier   )r$   rY   r   r   rA   s        r%   rp   z#IdentityProvider.clear_login_cookiew  s    d1222((1ABB**733[t444 	;DCKK
 $$Wk:::::	; 	;KKr'   c                R    |j         |                     |          fi | j        }|sdS |                                }	 |                     |          S # t
          $ rG}| j                            d| d           | j                            d|            Y d}~dS d}~ww xY w)z[Get user from a cookie

        Calls user_from_cookie to deserialize cookie value
        Nz)Error unpacking user from cookie: cookie=T)exc_infoz"Error unpacking user from cookie: )	get_secure_cookierl   get_secure_cookie_kwargsrV   r   	Exceptionrn   debugerror)r$   rY   _user_cookieuser_cookiees        r%   ri   z IdentityProvider.get_user_cookie  s     1w0  ))
 
+
 
  	4"))++	((555 	 	 	HNNT{TT_cNdddHNNCCCDDD44444		s    A 
B&<B!!B&z(token|bearer)\s+(.+)c                    |                     dd          }|sO| j                            |j        j                            dd                    }|r|                    d          }|S )zGet the user token from a request

        Default:

        - in URL parameters: ?token=<token>
        - in header: Authorization: token <token>
        rD   r   Authorization   )get_argumentauth_header_patmatchr   headersgetgroup)r$   rY   
user_tokenms       r%   	get_tokenzIdentityProvider.get_token  sj     ))'266
 	($**7?+B+F+FXZ+[+[\\A (WWQZZ
r'   c                v  K   t          j        d|j                  }|sdS |                     |          }d}||k    r'| j                            d|j        j                   d}|rR|                     |          }t          |t           j
                  r| d{V }|}||                     |          }|S dS )zIdentify the user based on a token in the URL or Authorization header

        Returns:
        - uuid if authenticated
        - None if not
        r   NFz-Accepting token-authenticated request from %sT)re   rf   rD   r   rn   r   r   	remote_ipri   r5   rh   rr   )r$   rY   rD   r   authenticated_userrw   s          r%   rg   zIdentityProvider.get_user_token  s       |W]33 	4^^G,,
HNN?)   !M 	 ((11E%-- $# %D|33G<<K4r'   c                    t          j                    j        }t                      }d| x}}d|d          }d}|j                            d|            t          ||||d|          S )zGenerate a random anonymous user.

        For use when a single shared token is used,
        but does not identify a user.
        z
Anonymous Ar   Nz5Generating new user for token-authenticated request: )uuiduuid4hexr   rn   r   r   )r$   rY   user_idmoonr   r   r   r   s           r%   rr   z(IdentityProvider.generate_anonymous_user  s{     *,,"%''14111| tAw==[RY[[\\\GT<4GGGr'   boolc                .    |                      |           S )a3  Should the Handler check for CORS origin validation?

        Origin check should be skipped for token-authenticated requests.

        Returns:
        - True, if Handler must check for valid CORS origin.
        - False, if Handler should skip origin check since requests are token-authenticated.
        )is_token_authenticatedr^   s     r%   should_check_originz$IdentityProvider.should_check_origin  s     ..w7777r'   c                2    |j          t          |dd          S )zReturns True if handler has been token authenticated. Otherwise, False.

        Login with a token is used to signal certain things, such as:

        - permit access to REST API
        - xsrf protection
        - skip origin-checks for scripts
        rk   F)current_userrd   r^   s     r%   r   z'IdentityProvider.is_token_authenticated  s      	w 6>>>r'   appr2   ssl_optionsdict[str, t.Any] | Nonec                    |j         sId}||j                            | d           | j        s|j                            | d           dS dS | j        s|j                            d           dS dS )z~Check the application's security.

        Show messages, or abort if necessary, based on the security configuration.
        z<WARNING: The Jupyter server is listening on all IP addressesNz3 and not using encryption. This is not recommended.zK and not using authentication. This is highly insecure and not recommended.z`All authentication is disabled.  Anyone who can connect to this server will be able to run code.)iprn   ro   rq   )r$   r   r   ro   s       r%   validate_securityz"IdentityProvider.validate_security  s     v 	TG"7 _ _ _```$  C C C     
 " 	GOOT    	 	r'   c                "   |                     dd          }d}| j        s/| j                            d           |                     |          S | j        r8| j        |k    r-t          j        t          | 	                    |                    S |S )_Process login form data

        Return authenticated User if successful, None if not.
        passwordr   r   N6Accepting anonymous login because auth fully disabled!)
r   rq   rn   ro   rr   rD   re   rf   r   user_for_token)r$   rY   typed_passwordrw   s       r%   process_login_formz#IdentityProvider.process_login_form  s    
 !--j"-EE  	9HUVVV//888: 	E$*666$ 3 3N C CDDDr'   c                    dS )zIs authentication enabled?

        Should always be True, but may be False in rare, insecure cases
        where requests with no auth are allowed.

        Previously: LoginHandler.get_login_available
        Tr0   r#   s    r%   rq   zIdentityProvider.auth_enabled  s	     tr'   c                    | j         S z\Whether a LoginHandler is needed - and therefore whether the login page should be displayed.rq   r#   s    r%   r~   z IdentityProvider.login_available*         r'   c                    dS )z"Whether a LogoutHandler is needed.Tr0   r#   s    r%   r   z!IdentityProvider.logout_available/  s	     tr'   )rY   rZ   r3   r[   rY   rZ   r3   r`   )rw   r   r3   ry   )r3   r|   )rw   r   r3   r   )r   r   r3   r`   )rY   rZ   r3   r   )rY   rZ   rw   r   r3   r   )r   N)
rY   rZ   r   r   r   r   r   r   r3   r   )rY   rZ   r3   r   )rY   rZ   r3   r   )rY   rZ   r3   r   rY   rZ   r3   r   r!   r   r2   r   r   r3   r   )2r+   r,   r-   r.   r   r   rA   r/   r   r   r
   rC   r   tagrD   r   r	   RequestHandlerr   r   rN   r   rX   rR   r_   r]   r{   r   r   r   rl   rj   r   rp   ri   recompile
IGNORECASEr   r   rg   rr   r   r   r   r   propertyrq   r~   r   r0   r'   r%   r=   r=   n   s           4;7
U_``4 4 4K     TUA
 
  N BFUY
 
	B B BM      $tUA
 
      .5WU
 
. . .  
cc! 
    $ $B U<==	    4@ U566	   OWWD D D  9=T

JBBBB
' 
' 
' 
'+ + + +Z   

 
 
 
   &

 

 

 


N 
N 
N 
N\ \ \ \" ]a@ @ @ @ @6; ; ; ;   . !bj!92=IIO    ! ! ! !FH H H H	8 	8 	8 	8? ? ? ?  04    0       X ! ! X!   X  r'   r=   c                      e Zd ZdZ edd ed                    Z edd ed                    Z edd ed                    Z	 e
d	          d
             Zedd            Zedd            Zd ZddZ	 dd fdZ xZS )PasswordIdentityProviderzA password identity provider.r   Ta  
            Hashed password to use for web authentication.

            To generate, type in a python/IPython shell:

                from jupyter_server.auth import passwd; passwd()

            The string should be of the form type:salt:hashed-password.
            r>   Fao  
            Forces users to use a password for the Jupyter server.
            This is useful in a multi user environment, for instance when
            everybody in the LAN can access each other's machine through ssh.

            In such a case, serving on localhost is not secure since
            any user can connect to the Jupyter server via ssh.

            a  
            Allow password to be changed at login for the Jupyter server.

            While logging in with a token, the Jupyter server UI will give the opportunity to
            the user to enter a new password at the same time that will replace
            the token login mechanism.

            This can be set to False to prevent changing password from the UI/API.
            rR   c                ,    t          | j                   S r!   )r   hashed_passwordr#   s    r%   _need_token_defaultz,PasswordIdentityProvider._need_token_defaulth  s    ,----r'   r3   r   c                    | j         S r   r   r#   s    r%   r~   z(PasswordIdentityProvider.login_availablel  r   r'   c                8    t          | j        p| j                  S )z"Return whether any auth is enabled)r   r   rD   r#   s    r%   rq   z%PasswordIdentityProvider.auth_enabledq  s     D(6DJ777r'   c                ,    t          | j        |          S )z1Check password against our stored hashed password)r   r   )r$   r   s     r%   r   z%PasswordIdentityProvider.passwd_checkv  s    D0(;;;r'   rY   rZ   r`   c                   |                     dd          }|                     dd          }d}| j        s/| j                            d           |                     |          S |                     |          r|s|                     |          S | j        r| j        |k    r|                     |          }|r| j        r|j        	                    dd          }t          j                            |d          }t          ||	          | _        | j                            t!          d
                              |                     |S )r   r   r   r   new_passwordNr   
config_dirzjupyter_server_config.json)config_filezWrote hashed password to {file})file)r   rq   rn   ro   rr   r   rD   allow_password_changesettingsr   rL   r   joinr   r   infor   format)r$   rY   r   r   rw   r  r  s          r%   r   z+PasswordIdentityProvider.process_login_formz  sW   
 !--j"-EE++NB+GG  	9HUVVV//888^,, 	a\ 	a//888Z 	aDJ.88//88D a : a$-11,CC
 gll:7STT'3Lk'Z'Z'Z$e$EFFMMS^M__```r'   Nr   r2   r   r   r   c                   t                                          ||           | j        r| j        s| j                            t          d                     | j                            t          d                     | j                            t          d                     t          j        d           dS dS dS )zHandle security validation.>Jupyter servers are configured to only be run with a password.1Hint: run the following command to set a password)	$ python -m jupyter_server.auth passwordr   N)	superr   password_requiredr   rn   criticalr   sysexit)r$   r   r   	__class__s      r%   r   z*PasswordIdentityProvider.validate_security  s     	!!#{333! 	4+? 	HVWW   He$WXXYYYHe$PQQRRRHQKKKKK	 	 	 	r'   r3   r   r   r!   r   )r+   r,   r-   r.   r   r   r   r
   r  r  r   r   r   r~   rq   r   r   r   __classcell__)r  s   @r%   r   r   5  sl       ''g
U

 

  O  U

 

    !DU

 

    W\. . . ! ! ! X! 8 8 8 X8< < <   6 04          r'   r   c                      e Zd ZdZ e            Z ed          d             Z ed          d             Ze	d             Z
ddZe	dd            ZddZddZ	 dddZdS )LegacyIdentityProviderzLegacy IdentityProvider for use with custom LoginHandlers

    Login configuration has moved from LoginHandler to IdentityProvider
    in Jupyter Server 2.0.
    r  c                     | j         | j        dS )N)rD   r   )rD   r   r#   s    r%   _default_settingsz(LegacyIdentityProvider._default_settings  s     Z,
 
 	
r'   r   c                    ddl m} |S )Nr   )LegacyLoginHandler)loginr  )r$   r  s     r%   _default_login_handler_classz3LegacyIdentityProvider._default_login_handler_class  s    ------!!r'   c                    | j         S r!   )r~   r#   s    r%   rq   z#LegacyIdentityProvider.auth_enabled  s    ##r'   rY   rZ   r3   r`   c                \    | j                             |          }|dS t          |          S )rb   N)r   r_   r;   )r$   rY   rw   s      r%   r_   zLegacyIdentityProvider.get_user  s0    '0099<4$T***r'   r   c                Z    t          | j                            | j                            S r!   )r   r   get_login_availabler  r#   s    r%   r~   z&LegacyIdentityProvider.login_available  s/    $88 
 
 	
r'   c                P    t          | j                            |                    S )zWhether we should check origin.)r   r   r   r^   s     r%   r   z*LegacyIdentityProvider.should_check_origin  s!    D,@@IIJJJr'   c                P    t          | j                            |                    S )z#Whether we are token authenticated.)r   r   r   r^   s     r%   r   z-LegacyIdentityProvider.is_token_authenticated  s!    D,CCGLLMMMr'   Nr   r2   r   r   r   c                j   | j         r| j        s| j                            t	          d                     | j                            t	          d                     | j                            t	          d                     t          j        d           | j                            ||           dS )zValidate security.r
  r  r  r   N)	r  r   rn   r  r   r  r  r   r   )r$   r   r   s      r%   r   z(LegacyIdentityProvider.validate_security  s     ! 	4+? 	HVWW   He$WXXYYYHe$PQQRRRHQKKK 22	
 	
 	
 	
 	
r'   r   r  r   r!   r   )r+   r,   r-   r.   r   r  r   r  r  r   rq   r_   r~   r   r   r   r0   r'   r%   r  r    s         tvvHWZ
 
 
 W"##" " $#"
 $ $ X$+ + + + 
 
 
 X
K K K KN N N N 04
 
 
 
 
 
 
r'   r  )r1   r2   r3   r   )+r.   
__future__r   rS   r   r   rL   r   r  typingre   r   dataclassesr   r   http.cookiesr   tornador   r   r	   	traitletsr
   r   r   r   r   traitlets.configr   jupyter_server.transutilsr   securityr   r   utilsr   r   r   r   r;   r=   r   r  r0   r'   r%   <module>r.     s/    # " " " " "    				 				 



      ) ) ) ) ) ) ) )       ) ) ) ) ) ) ) ) ) ) 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0 0 0 + + + + + + 0 0 0 0 0 0 0 0 ) ) ) ) ) )
?++ +* +* +* +* +* +* +* +*\   :D D D D D* D D DNj j j j j/ j j jZA
 A
 A
 A
 A
5 A
 A
 A
 A
 A
r'   