
    #	hˤ                     b   S r SSKr SSKJrJrJrJrJr  SSK
r
SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJr   \  \R2                  S   S	:  a  \4O\4r " S
 S\5      r " S S\5      r S r!SS jr" " S S\ 5      r#g! \ a    SSKJrJrJr  SSK	JrJr   Nf = f!   SSKJr   Nk= f)zIThis OAuth2 client implementation aims to be spec-compliant, and generic.    N)	urlencodeparse_qs
quote_plusurlparse
urlunparse)r   r   r   )r   r      )AuthCodeReceiver)error   c                       \ rS rSrSrg)BrowserInteractionTimeoutError    N)__name__
__module____qualname____firstlineno____static_attributes__r       G/var/www/html/env/lib/python3.13/site-packages/msal/oauth2cli/oauth2.pyr   r      s    r   r   c                       \ rS rSr\S 5       rSrSr\\0r\	S 5       r
\
R                  S 5       r
         SS jrS	 r    SS
 jrSS jrS rSrg)
BaseClient"   c                 L    [         R                  " U 5      R                  S5      $ )N   =)base64urlsafe_b64encoderstrip)	assertions    r   encode_saml_assertion BaseClient.encode_saml_assertion'   s    ''	299$??r   z6urn:ietf:params:oauth:client-assertion-type:jwt-bearerz8urn:ietf:params:oauth:client-assertion-type:saml2-bearerc                 P    [         R                  " S[        5        U R                  $ Nz"Will be gone in next major releasewarningswarnDeprecationWarning_http_client)selfs    r   sessionBaseClient.session/   s    :<NO   r   c                 F    [         R                  " S[        5        Xl        g r#   r$   )r)   values     r   r*   r+   4   s    :<NO!r   Nc                 *   U(       d  [        S5      eXl        X l        X@l        XPl        U=(       d    0 U l        U=(       d    0 U l        Ub  X`R                  S'   [        R                  " [        5      U l
        U(       a  U	c  U
c  Ub  [        S5      eX0l        gSSKnUR                  5       U l        U	c  SOU	U R                  l        XR                  l        [         R"                  " U R                  R$                  US9U R                  l        g)a  Initialize a client object to talk all the OAuth2 grants to the server.

Args:
    server_configuration (dict):
        It contains the configuration (i.e. metadata) of the auth server.
        The actual content typically contains keys like
        "authorization_endpoint", "token_endpoint", etc..
        Based on RFC 8414 (https://tools.ietf.org/html/rfc8414),
        you can probably fetch it online from either
        https://example.com/.../.well-known/oauth-authorization-server
        or
        https://example.com/.../.well-known/openid-configuration
    client_id (str): The client's id, issued by the authorization server

    http_client (http.HttpClient):
        Your implementation of abstract class :class:`http.HttpClient`.
        Defaults to a requests session instance.

        There is no session-wide `timeout` parameter defined here.
        Timeout behavior is determined by the actual http client you use.
        If you happen to use Requests, it disallows session-wide timeout
        (https://github.com/psf/requests/issues/3341). The workaround is:

            s = requests.Session()
            s.request = functools.partial(s.request, timeout=3)

        and then feed that patched session instance to this class.

    client_secret (str):  Triggers HTTP AUTH for Confidential Client
    client_assertion (bytes, callable):
        The client assertion to authenticate this client, per RFC 7521.
        It can be a raw SAML2 assertion (we will base64 encode it for you),
        or a raw JWT assertion in bytes (which we will relay to http layer).
        It can also be a callable (recommended),
        so that we will do lazy creation of an assertion.
    client_assertion_type (str):
        The type of your :attr:`client_assertion` parameter.
        It is typically the value of :attr:`CLIENT_ASSERTION_TYPE_SAML2` or
        :attr:`CLIENT_ASSERTION_TYPE_JWT`, the only two defined in RFC 7521.
    default_headers (dict):
        A dict to be sent in each request header.
        It is not required by OAuth2 specs, but you may use it for telemetry.
    default_body (dict):
        A dict to be sent in each token request body. For example,
        you could choose to set this as {"client_secret": "your secret"}
        if your authorization server wants it to be in the request body
        (rather than in the request header).

    verify (boolean):
        It will be passed to the
        `verify parameter in the underlying requests library
        <http://docs.python-requests.org/en/v2.9.1/user/advanced/#ssl-cert-verification>`_.
        When leaving it with default value (None), we will use True instead.

        This does not apply if you have chosen to pass your own Http client.

    proxies (dict):
        It will be passed to the
        `proxies parameter in the underlying requests library
        <http://docs.python-requests.org/en/v2.9.1/user/advanced/#proxies>`_.

        This does not apply if you have chosen to pass your own Http client.

    timeout (object):
        It will be passed to the
        `timeout parameter in the underlying requests library
        <http://docs.python-requests.org/en/v2.9.1/user/advanced/#timeouts>`_.

        This does not apply if you have chosen to pass your own Http client.

z,Missing input parameter server_configurationNclient_assertion_typezEverify, proxies, or timeout is not allowed when http_client is in user   T)timeout)
ValueErrorconfiguration	client_idclient_secretclient_assertiondefault_headersdefault_bodylogging	getLoggerr   loggerr(   requestsSessionverifyproxies	functoolspartialrequest)r)   server_configurationr3   http_clientr4   r5   r/   r6   r7   r=   r>   r0   r;   s                r   __init__BaseClient.__init__:   s    j $KLL1"* 0.4"(.B ,9N56''1!W%8G<O 12 2 !, ( 0 0 2D/5~t6D$(/%(1(9(9!!))7)<D%r   c                     U R                  U5      nU R                  US.nUR                  U5        UR                  5        VVs0 s H  u  pEUc  M
  XE_M     nnnUR	                  S5      (       a  U R                  US   5      US'   U$ s  snnf )N)r3   response_typescope)
_stringifyr3   updateitemsget)r)   rG   kwargsparamskvs         r   _build_auth_request_params%BaseClient._build_auth_request_params   s~    
 6#~~Nf#)<<>C>41Q$!$>C::g"oofWo>F7O Ds   	B
B
c           	         U R                   US.nU R                  R                  S5      (       az  U R                  (       ai  U R                  R                  U R                  S   S 5      nU" [        U R                  5      (       a  U R                  5       OU R                  5      US'   UR                  U R                  5        UR                  U=(       d    0 5        UR                  5        V	V
s0 s H  u  pU
(       d  M  X_M     nn	n
UR                  S5      (       a  U R                  US   5      US'   SS0nUR                  U R                  5        UR                  U=(       d    0 5        U R                  (       a  U R                   (       ap  S[        R                  " S	R                  [        U R                   5      [        U R                  5      5      R                  S
5      5      R!                  S
5      -   US'   SU R"                  ;  a  [%        S5      eU=(       d    U R&                  R(                  " U R"                  S   4XUS.UD6nUR*                  S:  a  UR-                  5          [.        R0                  " UR2                  5      $ s  sn
n	f ! [$         a(    U R4                  R7                  SUR2                  5        e f = f)N)r3   
grant_typer/   c                     U $ Nr   as    r   <lambda>*BaseClient._obtain_token.<locals>.<lambda>       !r   r5   rH   Acceptzapplication/jsonzBasic {}:{}asciiAuthorizationtoken_endpointz)token_endpoint not found in configuration)headersrN   datai  z(Token response is not in json format: %s)r3   r7   rL   r5   client_assertion_encoderscallablerJ   rK   rI   r6   r4   r   	b64encodeformatr   encodedecoder2   r1   r(   poststatus_coderaise_for_statusjsonloadstextr:   	exception)r)   rT   rN   rb   ra   ri   rM   _dataencoderrO   rP   _headersresps                r   _obtain_tokenBaseClient._obtain_token   s^    #nnJG  !899d>S>S4488%%&=>MG(/D1122 %%'8<8M8M)E$% 	T&&'TZR "'++-5-$!1-599W!__U7^<E'N01,,-2& $..(063C3CGNN 4>>*Jt7I7I,JE &/4# $*6'?)3H_% 4#5#55HII.)).../0%  s"!!#	 ::dii((M 6N  	KK!!>		K	s   2JJ6J 2Kc                     [        U[        5      (       d   eUR                  S0 5      nUR                  XS9  U R                  " SSU0UD6$ )a  Obtain an access token via a refresh token.

:param refresh_token: The refresh token issued to the client
:param scope: If omitted, is treated as equal to the scope originally
    granted by the resource owner,
    according to https://tools.ietf.org/html/rfc6749#section-6
rb   )refresh_tokenrH   )rw   )
isinstancestring_typespoprJ   rt   )r)   rw   rH   rM   rb   s        r   obtain_token_by_refresh_token(BaseClient.obtain_token_by_refresh_token   sN     -6666zz&"%-=!!GGGGr   c                 z    [        U[        [        [        45      (       a  SR	                  [        U5      5      $ U$ )N )rx   listsettuplejoinsorted)r)   sequences     r   rI   BaseClient._stringify  s/    hsE 23388F8,--r   )r(   r5   r3   r4   r2   r7   r6   r:   )	NNNNNNNNN)NNNNrV   )r   r   r   r   staticmethodr    CLIENT_ASSERTION_TYPE_JWTCLIENT_ASSERTION_TYPE_SAML2rc   propertyr*   setterrD   rQ   rt   r{   rI   r   r   r   r   r   r   "   s    
 @ @ !Y"\!<>S T! ! ^^" " !"& o<b  BHHr   r   c                     U b"  [        U [        [        [        45      (       d   eU (       a  [        U 5      $ [        / 5      $ rV   )rx   r   r   r   rH   s    r   
_scope_setr     s5    =JutS%.@AAAA3u:+CG+r   c                 n   SU s=::  a  S::  d   e   eSR                  [        R                  " [        R                  [        R
                  -   S-   U 5      5      n[        R                  " [        R                  " UR                  S5      5      R                  5       5      R                  S5      nUSUS.$ )	N+       z-._~r^   r   S256)code_verifiertransformationcode_challenge)r   randomsamplestringascii_lettersdigitsr   r   hashlibsha256rg   digestr   )lengthverifierr   s      r   _generate_pkce_code_verifierr     s    3wwf**V]]:VCVLNH 	  0H!I!P!P!RS	 
 " (
 
r   c                   f  ^  \ rS rSrSrSSS.rSrSrSr\\	R                  0rS"S
 jrS rS 4S jr S#S jr S#S jr S#S jr S"S jr  S$S jr          S%S jr\S"S j5       r S$S jr S$S jr S"S jrS"S jrS S S 4U 4S jjr   S&U 4S jjrS	S S	S	4U 4S jjr S"S  jrS!rU =r $ )'Clienti%  zrThis is the main API for oauth2 client.

Its methods define and document parameters mentioned in OAUTH2 RFC 6749.
z,urn:ietf:params:oauth:grant-type:device_codedevice_code)
GRANT_TYPEDEVICE_CODE)authorization_pending	slow_downz-urn:ietf:params:oauth:grant-type:saml2-bearerz+urn:ietf:params:oauth:grant-type:jwt-bearerNc                 @   SnU R                   R                  U5      (       d  [        S5      eU R                  R                  " U R                   U   4U R
                  U R                  U=(       d    / 5      S.[        U R                  40 UR                  S0 5      D6S.UD6n[        R                  " UR                  5      n[        UR                  SS5      5      US'   [        UR                  SS	5      5      US'   [        R                  " 5       US   -   US
'   U$ )az  Initiate a device flow.

Returns the data defined in Device Flow specs.
https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.2

You should then orchestrate the User Interaction as defined in here
https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3

And possibly here
https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3.1
device_authorization_endpointz1You need to provide device authorization endpoint)r3   rH   ra   )rb   ra   interval   
expires_ini  
expires_at)r2   rL   r1   r(   ri   r3   rI   dictr6   rz   rl   rm   rn   inttime)r)   rH   rM   DAErs   flows         r   initiate_device_flowClient.initiate_device_flow4  s     .!!%%c**PQQ  %%d&8&8&= #~~QS8TU--KIr1JK  zz$))$txx
A67Z ,!=>\!YY[4+==\r   c                    [         R                   " 5       nSnUR                  SS5      UR                  SS5      -   U-
  U:  a  [        R                  " S5        UR	                  S0 5      nUR                  SU R                  U R                  S	   US
   05        U R                  " U R                  S   4SU0UD6nUR                  S5      S:X  a  UR                  SS5      S-   US'   X1S'   U$ )Nr   latest_attempt_atr   r   r   z:Attempted too soon. Please do time.sleep(flow["interval"])rb   r3   r   r   r   r
   r   )	r   rL   r%   r&   rz   rJ   r3   DEVICE_FLOWrt   )r)   r   rM   nowskewrb   results          r   _obtain_token_by_device_flow#Client._obtain_token_by_device_flowP  s     iik88'+dhhz1.EELsRMMVWzz&"%]+T--@ 	 ##\*A15A9?A::g+-#xx
A6:D$' !r   c                 R    U R                  SS5      [        R                  " 5       :  $ )Nr   r   )rL   r   )r   s    r   rY   Client.<lambda>f  s    q(ADIIK(Or   c                     U R                   " U40 UD6nUR                  S5      U R                  ;  a  U$ [        UR                  SS5      5       H*  nU" U5      (       a  Us  $ [        R
                  " S5        M,     M  )a  Obtain token by a device flow object, with customizable polling effect.

Args:
    flow (dict):
        An object previously generated by initiate_device_flow(...).
        Its content WILL BE CHANGED by this method during each run.
        We share this object with you, so that you could implement
        your own loop, should you choose to do so.

    exit_condition (Callable):
        This method implements a loop to provide polling effect.
        The loop's exit condition is calculated by this callback.

        The default callback makes the loop run until the flow expires.
        Therefore, one of the ways to exit the polling early,
        is to change the flow["expires_at"] to a small number such as 0.

        In case you are doing async programming, you may want to
        completely turn off the loop. You can do so by using a callback as:

            exit_condition = lambda flow: True

        to make the loop run only once, i.e. no polling, hence non-block.
r
   r   r   r   )r   rL   DEVICE_FLOW_RETRIABLE_ERRORSranger   sleep)r)   r   exit_conditionrM   r   is         r   obtain_token_by_device_flow"Client.obtain_token_by_device_flowd  sr    : 66tFvFFzz'"$*K*KK488J23!$''!M

1 4	 r   c                     SU R                   ;  a  [        S5      eU R                   S   nU R                  " U4X#US.UD6nSU;   a  SOSnU< U< [        U5      < 3$ )Nauthorization_endpointz1authorization_endpoint not found in configurationredirect_urirH   state?&)r2   r1   rQ   r   )	r)   rG   r   rH   r   rM   r   rN   seps	            r   _build_auth_request_uriClient._build_auth_request_uri  sx     $4+=+==PQQ!%!3!34L!M00(4 22c13	&8IJJr   c                 d    [         R                  " S[        5        U R                  " U4X#US.UD6$ )zGenerate an authorization uri to be visited by resource owner.

Parameters are the same as another method :func:`initiate_auth_code_flow()`,
whose functionality is a superset of this method.

:return: The auth uri as a string.
z'Use initiate_auth_code_flow() instead. r   )r%   r&   r'   r   )r)   rG   r   rH   r   rM   s         r   build_auth_request_uriClient.build_auth_request_uri  s<     	?AST++(4 	r   c           	      F   UR                  SS5      nSU;   a  [        S5      e[        5       nU=(       d4    SR                  [        R
                  " [        R                  S5      5      UUS.nU R                  " U4US   US	   S
.[        U40 UD6D6nXS'   US   US'   U$ )a  Initiate an auth code flow.

Later when the response reaches your redirect_uri,
you can use :func:`~obtain_token_by_auth_code_flow()`
to complete the authentication/authorization.

This method also provides PKCE protection automatically.

:param list scope:
    It is a list of case-sensitive strings.
    Some ID provider can accept empty string to represent default scope.
:param str redirect_uri:
    Optional. If not specified, server will use the pre-registered one.
:param str state:
    An opaque value used by the client to
    maintain state between the request and callback.
    If absent, this library will automatically generate one internally.
:param kwargs: Other parameters, typically defined in OpenID Connect.

:return:
    The auth code flow. It is a dict in this form::

        {
            "auth_uri": "https://...",  // Guide user to visit this
            "state": "...",  // You may choose to verify it by yourself,
                             // or just let obtain_token_by_auth_code_flow()
                             // do that for you.
            "...": "...",  // Everything else are reserved and internal
        }

    The caller is expected to::

    1. somehow store this content, typically inside the current session,
    2. guide the end user (i.e. resource owner) to visit that auth_uri,
    3. and then relay this dict and subsequent auth response to
       :func:`~obtain_token_by_auth_code_flow()`.
rG   codetokenz(response_type="token ..." is not allowedr      )r   r   rH   r   r   )r   code_challenge_methodauth_urir   )
rz   r1   r   r   r   r   r   r   r   r   )	r)   rH   r   r   rM   rG   pkcer   r   s	            r   initiate_auth_code_flowClient.initiate_auth_code_flow  s    V 

?F; m# GHH+-NbggfmmF4H4H"&MN(
 //$ 01"&'7"8$ 4"6"	$
 $Z $_ 5_r   c                    [        U[        5      (       a  [        U[        5      (       d   eUR                  S5      (       d  [        S5      eUR                  S5      UR                  S5      :w  a9  [        SR	                  UR                  S5      UR                  S5      5      5      eU(       aI  [        U5      [        UR                  S/ 5      5      -
  (       a  [        SUR                  S5      -  5      eUR                  S5      (       a\  U R                  " US   4UR                  S5      U=(       d    UR                  S5      [        UR                  S0 5      US	   S
9S.UD6$ UR                  S5      (       aE  SUS   0nUR                  S5      (       a  US   US'   UR                  S5      (       a  US   US'   U$ [        S5      e)aT  With the auth_response being redirected back,
validate it against auth_code_flow, and then obtain tokens.

Internally, it implements PKCE to mitigate the auth code interception attack.

:param dict auth_code_flow:
    The same dict returned by :func:`~initiate_auth_code_flow()`.
:param dict auth_response:
    A dict based on query string received from auth server.

:param scope:
    You don't usually need to use scope parameter here.
    Some Identity Provider allows you to provide
    a subset of what you specified during :func:`~initiate_auth_code_flow`.
:type scope: collections.Iterable[str]

:return:
    * A dict containing "access_token" and/or "id_token", among others,
      depends on what scope was used.
      (See https://tools.ietf.org/html/rfc6749#section-5.1)
    * A dict containing "error", optionally "error_description", "error_uri".
      (It is either `this <https://tools.ietf.org/html/rfc6749#section-4.1.2.1>`_
      or `that <https://tools.ietf.org/html/rfc6749#section-5.2>`_
    * Most client-side data error would result in ValueError exception.
      So the usage pattern could be without any protocol details::

        def authorize():  # A controller in a web app
            try:
                result = client.obtain_token_by_auth_code_flow(
                    session.get("flow", {}), auth_resp)
                if "error" in result:
                    return render_template("error.html", result)
                store_tokens()
            except ValueError:  # Usually caused by CSRF
                pass  # Simply ignore them
            return redirect(url_for("index"))
r   z!state missing from auth_code_flowzstate mismatch: {} vs {}rH   z$scope must be None or a subset of %sr   r   rb   r   )r   )r   rH   rb   r
   error_description	error_uriz3auth_response must contain either "code" or "error")rx   r   rL   r1   rf   r   #_obtain_token_by_authorization_coderz   )r)   auth_code_flowauth_responserH   rM   r
   s         r   obtain_token_by_auth_code_flow%Client.obtain_token_by_auth_code_flow  s   V .$//J}d4S4SSS!!'**
 @AAg&-*;*;G*DD7>>""7+]->->w-GI J JSZ#n&8&8"&E"FF69K9KG9TTV VV$$;;f%+//? :~11': JJvr*"0"A   W%% mG45E  !455-:;N-O)*  --%2;%?k"LNOOr   c           	         U(       a  U R                   " U4SU0UD6$ [        U=(       d    S5      nUR                  (       d  [        S5      eUR                  c  SOUR                  n [        US9 nUR                  S:w  a  UOj[        UR                  SR                  UR                  UR                  5       5      UR                  UR                  UR                  UR                  45      nU R                  R                  S	R                  U5      5        U R                   " U4SU0UD6sSSS5        $ ! , (       d  f       g= f! [          a    [        S
U-  5      ef = f)a  A native app can use this method to obtain token via a local browser.

Internally, it implements PKCE to mitigate the auth code interception attack.

:param scope: A list of scopes that you would like to obtain token for.
:type scope: collections.Iterable[str]

:param extra_scope_to_consent:
    Some IdP allows you to include more scopes for end user to consent.
    The access token returned by this method will NOT include those scopes,
    but the refresh token would record those extra consent,
    so that your future :func:`~obtain_token_by_refresh_token()` call
    would be able to obtain token for those additional scopes, silently.
:type scope: collections.Iterable[str]

:param string redirect_uri:
    The redirect_uri to be sent via auth request to Identity Provider (IdP),
    to indicate where an auth response would come back to.
    Such as ``http://127.0.0.1:0`` (default) or ``http://localhost:1234``.

    If port 0 is specified, this method will choose a system-allocated port,
    then the actual redirect_uri will contain that port.
    To use this behavior, your IdP would need to accept such dynamic port.

    Per HTTP convention, if port number is absent, it would mean port 80,
    although you probably want to specify port 0 in this context.

:param dict auth_params:
    These parameters will be sent to authorization_endpoint.

:param int timeout: In seconds. None means wait indefinitely.

: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: Same as :func:`~obtain_token_by_auth_code_flow()`
r   zhttp://127.0.0.1:0z$redirect_uri should contain hostnameNP   )portr   r]   zUsing {} as redirect_uriz,Can't listen on port %s. You may try port 0.)_obtain_token_by_browserr   hostnamer1   r   _AuthCodeReceiverr   schemerf   get_portpathrN   queryfragmentr:   debugPermissionError)r)   r   auth_code_receiverrM   _redirect_urilisten_portreceiveruris           r   obtain_token_by_browserClient.obtain_token_by_browser?  sd   ^ 00"I1=IAGI I !!E1EF%%CDD$$,B-2D2D 		N"4&3&8&8A&=l:!((NN=#9#98;L;L;NO!&&!((!''!**O D !!"<"C"CC"HI44:+.:28: 544  	N>LN N	Ns+   )	E	 2B<D8.	E	 8
EE	 E	 	E"c                     U R                   " SU[        U5      [        U5      -  S.U	=(       d    0 D6nUR                  US   US   UUUUU
US9nUc  [        S5      eU R                  " X4SU0UD6$ )Nr   rH   r   r   )r   r   r0   welcome_templatesuccess_templateerror_templateauth_uri_callbackbrowser_namez&User did not complete the flow in timerH   r   )r   r   get_auth_responser   r   )r)   r   rH   extra_scope_to_consentr   r0   r   r   r   auth_paramsr   r   rM   r   r   s                  r   r   Client._obtain_token_by_browser  s    $ ++ #%U#j1G&HH#  b# +<<*%w---)/% = 	  01YZZ228',8068 	8r   c                     [         R                  " S[        5        [        U [        5      (       d  [        U 5      n U R                  S5      U:w  a  [        S5      eU $ )zParse the authorization response being redirected back.

:param params: A string or dict of the query string
:param state: REQUIRED if the state parameter was present in the client
    authorization request. This function will compare it with response.
,Use obtain_token_by_auth_code_flow() insteadr   zstate mismatch)r%   r&   r'   rx   r   r   rL   r1   )rN   r   s     r   parse_auth_responseClient.parse_auth_response  sP     	:<N	P&$''f%F::g%'-..r   c                 b    [         R                  " S[        5        U R                  " U4X#S.UD6$ )a<  Get a token via authorization code. a.k.a. Authorization Code Grant.

This is typically used by a server-side app (Confidential Client),
but it can also be used by a device-side native app (Public Client).
See more detail at https://tools.ietf.org/html/rfc6749#section-4.1.3

You are encouraged to use its higher level method
:func:`~obtain_token_by_auth_code_flow` instead.

:param code: The authorization code received from authorization server.
:param redirect_uri:
    Required, if the "redirect_uri" parameter was included in the
    authorization request, and their values MUST be identical.
:param scope:
    It is both unnecessary and harmless to use scope here, per RFC 6749.
    We suggest to use the same scope already used in auth request uri,
    so that this library can link the obtained tokens with their scope.
r  r   )r%   r&   r'   r   )r)   r   r   rH   rM   s        r   "obtain_token_by_authorization_code)Client.obtain_token_by_authorization_code  sA    ( 	:<N	P77D+D<BD 	Dr   c                     UR                  S0 5      nUR                  XS9  U(       a  X5S'   U R                  (       d  U R                  US'   U R                  " SSU0UD6$ )Nrb   )r   r   rH   r3   )authorization_code)rz   rJ   r4   r3   rt   )r)   r   r   rH   rM   rb   s         r   r   *Client._obtain_token_by_authorization_code  s\    zz&"%9!M!! !%D!!LTLVLLr   c                 n    UR                  S0 5      nUR                  XUS9  U R                  " SSU0UD6$ )zBThe Resource Owner Password Credentials Grant, used by legacy app.rb   )usernamepasswordrH   )r  rz   rJ   rt   )r)   r  r  rH   rM   rb   s         r   !obtain_token_by_username_password(Client.obtain_token_by_username_password  s=     zz&"%XF!!B4B6BBr   c                 l    UR                  S0 5      nUR                  US9  U R                  " SSU0UD6$ )a  Obtain token for this client (rather than for an end user),
a.k.a. the Client Credentials Grant, used by Backend Applications.

We don't name it obtain_token_by_client_credentials(...) because those
credentials are typically already provided in class constructor, not here.
You can still explicitly provide an optional client_secret parameter,
or you can provide such extra parameters as `default_body` during the
class initialization.
rb   r   )client_credentialsr  )r)   rH   rM   rb   s       r   obtain_token_for_clientClient.obtain_token_for_client  s;     zz&"%% !!LTLVLLr   c                     g rV   r   )events    r   rY   r         dr   c                     g rV   r   
token_items    r   rY   r     r  r   c                     g rV   r   )r  new_rts     r   rY   r     s    dr   c                 T   > [         [        U ]
  " X40 UD6  X0l        X@l        XPl        g rV   )superr   rD   on_obtaining_tokenson_removing_rton_updating_rt)r)   rB   r3   r"  r#  r$  rM   	__class__s          r   rD   Client.__init__  s,     	fd$%9OO#6 ,,r   c           
        > UR                  5       n[        [        U ]  " XU/UQ70 UD6n	SU	;  a  U	R                  5       n
SnX:X  a  X;   a  U(       d  U
R	                  US 5        SU
;   a  U
S   R                  5       nOUR                  S5      nU=(       d    U R                  " U R                  UU R                  S   UXUS.5        U	$ )Nr
   rw   rH   r`   )r3   rH   r`   rT   responserN   rb   )
copyr!  r   rt   rz   splitrL   r"  r3   r2   )r)   rT   rN   rb   also_save_rtr"  argsrM   rp   rs   _respRTrH   r%  s                r   rt   Client._obtain_token  s    
 		VT08(,8068$IIKE BBK 		"d#%g,,. 		'* <D$<$<<!^^"&"4"45E"F(!U?  r   c                     U S   $ )Nrw   r   r  s    r   rY   r   $  s	    O)Dr   c                 *  > [         [        U ]
  " [        U[        5      (       d  U" U5      OU4UUSL S.UD6nUR                  S5      S:X  a  U=(       d    U R                  " U5        SnUSLa#  X;   a  U=(       d    U R                  " XU   5        U$ )a  This is an overload which will trigger token storage callbacks.

:param token_item:
    A refresh token (RT) item, in flexible format. It can be a string,
    or a whatever data structure containing RT string and its metadata,
    in such case the `rt_getter` callable must be able to
    extract the RT string out from the token item data structure.

    Either way, this token_item will be passed into other callbacks as-is.

:param scope: If omitted, is treated as equal to the scope originally
    granted by the resource owner,
    according to https://tools.ietf.org/html/rfc6749#section-6
:param rt_getter: A callable to translate the token_item to a raw RT string
:param on_removing_rt: If absent, fall back to the one defined in initialization

:param on_updating_rt:
    Default to None, it will fall back to the one defined in initialization.
    This is the most common case.

    As a special case, you can pass in a False,
    then this function will NOT trigger on_updating_rt() for RT UPDATE,
    instead it will allow the RT to be added by on_obtaining_tokens().
    This behavior is useful when you are migrating RTs from elsewhere
    into a token storage managed by this library.
F)rH   r+  r
   invalid_grantrw   )r!  r   r{   rx   ry   rL   r#  r$  )
r)   r  rH   	rt_getterr#  r$  rM   rs   r.  r%  s
            r   r{   $Client.obtain_token_by_refresh_token#  s    @ VT@!*l;; j!AK '50	
  88G/2t222J?&2:2t222JRIr   c                     U R                   R                  US 5      nUR                  S0 5      nUR                  X5" U5      S9  U R                  " U4SU0UD6$ )a  This method implements Assertion Framework for OAuth2 (RFC 7521).
See details at https://tools.ietf.org/html/rfc7521#section-4.1

:param assertion:
    The assertion bytes can be a raw SAML2 assertion, or a JWT assertion.
:param grant_type:
    It is typically either the value of :attr:`GRANT_TYPE_SAML2`,
    or :attr:`GRANT_TYPE_JWT`, the only two profiles defined in RFC 7521.
:param scope: Optional. It must be a subset of previously granted scopes.
c                     U $ rV   r   rW   s    r   rY   2Client.obtain_token_by_assertion.<locals>.<lambda>]  r[   r   rb   )rH   r   )grant_assertion_encodersrL   rz   rJ   rt   )r)   r   rT   rH   rM   rq   rb   s          r   obtain_token_by_assertion Client.obtain_token_by_assertionP  s\     //33JLzz&"%%79+=>!!*B4B6BBr   )r"  r#  r$  rV   )NNN)NN)
NNNNNNNNNN)NNFN)!r   r   r   r   __doc__r   r   GRANT_TYPE_SAML2GRANT_TYPE_JWTr   r    r8  r   r   r   r   r   r   r   r   r   r   r  r	  r   r  r  rD   rt   r{   r9  r   __classcell__)r%  s   @r   r   r   %  s=   
 E$
K $J FBN 0*2R2RS8, P$P AE
K AE, 26	BP 	QPl #	GNX #'!!"#8J    26D4 26
M -1CM  !32:		- 15 $B ?CD+\ 04C Cr   r   )r   )$r;  rl   urllib.parser   r   r   r   r   ImportErrorurllibr8   r%   r   r   sysr?   r   r   r   authcoder	   r   r   socketr
   version_infostr
basestringry   RuntimeErrorr   objectr   r   r   r   r   r   r   <module>rJ     s    O -RR     
     ;0
 ))!,1v
~	\ 	l l^,

{CZ {C}  -77,,-"0/s   B B$ B! B!$B.