
    +                         d Z ddlmZ ddlmZ ddl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 dZdZdZdZdZdZdZd ZddZ	 ddZd Zd Zd Z	 ddZy)a  A module that provides functions for handling rapt authentication.

Reauth is a process of obtaining additional authentication (such as password,
security token, etc.) while refreshing OAuth 2.0 credentials for a user.

Credentials that use the Reauth flow must have the reauth scope,
``https://www.googleapis.com/auth/accounts.reauth``.

This module provides a high-level function for executing the Reauth process,
:func:`refresh_access_token`, and lower-level helpers for doing the individual
steps of the reauth process.

Those steps are:

1. Obtaining a list of challenges from the reauth server.
2. Running through each challenge and sending the result back to the reauth
   server.
3. Refreshing the access token using the returned rapt token.
    )absolute_import)division)print_functionN)
challenges)errors)_helpers)_reauth_client)http_client)rangez/https://www.googleapis.com/auth/accounts.reauthinvalid_grantinvalid_raptrapt_requiredAUTHENTICATEDCHALLENGE_REQUIREDCHALLENGE_PENDINGc                    | d   D ]  }|d   dk7  rt         j                  j                  |d   d      }|s\t        j                  dj                  |d   dj                  t        t         j                  j                                                 |j                  s't        j                  dj                  |d               |j                  |      }|s yt        j                  || d	   |d
   ||      c S  y)aL  Get the next challenge from msg and run it.

    Args:
        msg: Reauth API response body (either from the initial request to
            https://reauth.googleapis.com/v2/sessions:start or from sending the
            previous challenge response to
            https://reauth.googleapis.com/v2/sessions/id:continue)
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        access_token: reauth access token

    Returns: rapt token.
    Raises:
        errors.ReauthError if reauth failed
    r   statusREADYchallengeTypeNz4Unsupported challenge type {0}. Supported types: {1},z%Challenge {0} is not locally eligible	sessionIdchallengeId)r   AVAILABLE_CHALLENGESgetr   ReauthFailErrorformatjoinlistkeysis_locally_eligibleobtain_challenge_inputr	   send_challenge_result)msghttp_requestaccess_token	challengecclient_inputs         Hplatform/gsutil/third_party/google-reauth-python/google_reauth/reauth.py_run_next_challenger*   =   s     &	X')++///*D2((F	/2j&E&E&J&J&L!MNP 
 $$((7	/235 5 //	:33m$ 	' '2     c                    d}t        d|      D ]  }|s=t        j                  | t        t        j
                  j                               ||      }|d   t        k(  r|d   c S |d   t        k(  s3|d   t        k(  s't        j                  dj                  |d               t        j                         st        j                         t!        || |      } t        j"                         )a  Given an http request method and reauth access token, get rapt token.

    Args:
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        access_token: reauth access token
        requested_scopes: scopes required by the client application
        rounds_num: max number of attempts to get a rapt after the next
            challenge, before failing the reauth. This defines total number of
            challenges + number of additional retries if the chalenge input
            wasn't accepted.

    Returns: rapt token.
    Raises:
        errors.ReauthError if reauth failed
    Nr   r   encodedProofOfReauthTokenzChallenge status {0})r   r	   get_challengesr   r   r   r   _AUTHENTICATED_CHALLENGE_REQUIRED_CHALLENGE_PENDINGr   ReauthAPIErrorr   r   is_interactiveReauthUnattendedErrorr*   r   )r$   r%   requested_scopes
rounds_numr#   _s         r)   _obtain_raptr8   i   s    " C1j! //Z4499;< 	"C x=N*233H!44H!33''&--c(m<> > &&(..00!#|\B) ". 
 
 
""r+   c           
         t         j                  j                  d       t        j                  | ||||t
        ddi      \  }}	 t        j                  |      }|j                  t        j                   k7  r)t        j                  t#        |      |j                        d|vrt        j                  d      t%        | |d   |      }|S # t        t        f$ r. t        j                  dj                  t        |                  w xY w)	aN  Given an http request method and refresh_token, get rapt token.

    Args:
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        client_id: client id to get access token for reauth scope.
        client_secret: client secret for the client_id
        refresh_token: refresh token to refresh access token
        token_uri: uri to refresh access token
        scopes: scopes required by the client application

    Returns: rapt token.
    Raises:
        errors.ReauthError if reauth failed
    zReauthentication required.
zContent-Typez!application/x-www-form-urlencoded)r$   	client_idclient_secretrefresh_token	token_uriscopesheadersInvalid response {0}r%   z&Access token missing from the response)r5   )sysstderrwriter	   refresh_grant_REAUTH_SCOPEjsonloads	TypeError
ValueErrorr   ReauthAccessTokenRefreshErrorr   _substr_for_error_messager   r
   OK_get_refresh_error_messager8   )	r$   r:   r;   r<   r=   r>   responsecontent
rapt_tokens	            r)   get_rapt_tokenrQ      s   " JJ34 '44!##!DEGHgO**W%
 +..(22&w/B 	B W$2246 	6 !J
 % z" O22"))*CG*LMO 	OOs   C =D
c                     	 t        j                  |       } | j	                  d      t
        k(  xr2 | j	                  d      t        k(  xs | j	                  d      t        k(  S # t        t        f$ r Y yw xY w)zChecks if the rapt refresh is required.

    Args:
        content: refresh response content

    Returns:
        True if rapt refresh is required.
    Ferrorerror_subtype)rF   rG   rH   rI   r   _REAUTH_NEEDED_ERROR!_REAUTH_NEEDED_ERROR_INVALID_RAPT"_REAUTH_NEEDED_ERROR_RAPT_REQUIREDrO   s    r)   _rapt_refresh_requiredrY      sx    **W% 	G 44 	M	_	%)J	J 
L	_	%)K	KN z" s   A# #A54A5c                 :    d}d| v r| d   }d| v r|d| d   z   z  }|S )zConstructs an error from the http response.

    Args:
        response: http response
        content: parsed response content

    Returns:
        error message to show
    zInvalid response.rS   error_descriptionz:  )rO   	error_msgs     r)   rM   rM      s>     $I'G$	')(; <<<Ir+   c                 2    t        |       dk  r| S | dd dz   S )z6Returns content string to include in the error messaged   r   a   z...)lenrX   s    r)   rK   rK      s#    'lc)7Dwq}u/DDr+   c           	         t        j                  | ||||||      \  }}	|j                  t        j                  k7  r;t        |	      r0t        | |||||      }t        j                  | ||||||      \  }}		 t        j                  |	      }	|j                  t        j                  k7  r)t        j                  t        |	      |j                        |	d   }
|	j!                  dd      }|	j!                  dd      }|	j!                  dd      }||	|
|||fS # t        t        f$ r9 t        j                  dj                  t        |	            |j                        w xY w)	a`  Refresh the access_token using the refresh_token.

    Args:
        http_request: callable to run http requests. Accepts uri, method, body
            and headers. Returns a tuple: (response, content)
        client_id: client id to get access token for reauth scope.
        client_secret: client secret for the client_id
        refresh_token: refresh token to refresh access token
        token_uri: uri to refresh access token
        scopes: scopes required by the client application

    Returns:
        Tuple[str, str, str, Optional[str], Optional[str], Optional[str]]: The
            rapt token, the access token, new refresh token, expiration,
            token id and response content returned by the token endpoint.
    Raises:
        errors.ReauthError if reauth failed
        errors.HttpAccessTokenRefreshError it access token refresh failed
    )r$   r:   r;   r<   r=   raptr?   )r>   r@   r%   r<   N
expires_inid_token)r	   rD   r   r
   rL   rY   rQ   rF   rG   rH   rI   r   HttpAccessTokenRefreshErrorr   rK   rM   r   )r$   r:   r;   r<   r=   rc   r>   r?   rN   rO   r%   rd   re   s                r)   refresh_access_tokenrg      sm   . '44!##Hg +..( #7+!D !/ < <)#++#!!Hg**W% +..(00&w/B 	B >*LKK6M\40J{{:t,H,z8KK z" 00"))*CG*LMOO 	s   9D AE)   )N)NNN)__doc__
__future__r   r   r   rF   rA   google_reauthr   r   r   r	   	six.movesr
   r   rE   rU   rV   rW   r/   r0   r1   r*   r8   rQ   rY   rM   rK   rg   r\   r+   r)   <module>rm      s   ( '  %  
 $   " ( !  B& $2 !%4 " * ( )X*#\ &*1hN&$E 48HLr+   