a
    !fYE                    @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZ ddlmZ 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	Zd	Zzdd
lmZ dZejduZW n ey   Y n0 eeZdZdZeZdZdZ dZ!dZ"dZ#dZ$de" d Z%dZ&e'dddgZ(dZ)e*ddZ+ze,e*ddZ-W n e.yp   dZ-Y n0 dZ/d e*d!d" Z0d#Z1d$Z2e1e2iZ3ejj4Z5ej6Z6ej7Z7ej8Z8G d%d& d&e9Z:G d'd( d(e;Z<G d)d* d*e<Z=G d+d, d,e<Z>G d-d. d.e>Z?G d/d0 d0e<Z@G d1d2 d2e<ZAG d3d4 d4e<ZBG d5d6 d6e<ZCG d7d8 d8e<ZDG d9d: d:e<ZEG d;d< d<e<ZFG d=d> d>e<eGZHd?d@ ZIG dAdB dBe9ZJG dCdD dDe9ZKG dEdF dFe9ZLG dGdH dHeJZMG dIdJ dJeMZNdKdL ZOdMdN ZPdOdP ZQG dQdR dReMZRdSdT ZSddUdVZTdWdX ZUdYdZ ZVd[d\ ZWd]d^ ZXd_d` ZYdadb ZZdcdd Z[G dedf dfeRZ\dgdh Z]e^didefdjdkZ_dldm Z`dndo Zae^dpdqddejbejcejdejeejfd	df
drdsZge^dddtduZhG dvdw dwe'dwdxZidydz ZjG d{d| d|eKZke^didd}d~ZldS )zPAn OAuth 2.0 client.

Tools for interacting with OAuth 2.0 protected resources.
    N)http_client)urllib)_helpers)_pkce)clientsecrets)	transportF)cryptTz%Y-%m-%dT%H:%M:%SZz*https://www.googleapis.com/oauth2/v1/certszurn:ietf:wg:oauth:2.0:oobauthorized_userservice_accountGOOGLE_APPLICATION_CREDENTIALSZgcloudZCLOUDSDK_CONFIGzThe Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable z must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.z$application_default_credentials.jsonAccessTokenInfoaccess_token
expires_inUNKNOWNNO_GCE_CHECKFalseGCE_METADATA_TIMEOUT   SERVER_SOFTWAREzhttp://ZGCE_METADATA_IPz169.254.169.254zmetadata-flavorZGooglec                   @   s   e Zd ZdZdZdS )SETTINGSz/Settings namespace for globally defined values.N)__name__
__module____qualname____doc__env_name r   r   T/var/www/html/python-backend/venv/lib/python3.9/site-packages/oauth2client/client.pyr      s   r   c                   @   s   e Zd ZdZdS )ErrorzBase error for this module.Nr   r   r   r   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdS )FlowExchangeErrorzDError trying to exchange an authorization grant for an access token.Nr   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdS )AccessTokenRefreshErrorz0Error trying to refresh an expired access token.Nr   r   r   r   r   r       s   r    c                       s    e Zd ZdZ fddZ  ZS )HttpAccessTokenRefreshErrorzCError (with HTTP status) trying to refresh an expired access token.c                    s    t t| j|  |d| _d S )Nstatus)superr!   __init__getr"   )selfargskwargs	__class__r   r   r$      s    z$HttpAccessTokenRefreshError.__init__)r   r   r   r   r$   __classcell__r   r   r)   r   r!      s   r!   c                   @   s   e Zd ZdZdS )TokenRevokeErrorzError trying to revoke a token.Nr   r   r   r   r   r,      s   r,   c                   @   s   e Zd ZdZdS )UnknownClientSecretsFlowErrorzEThe client secrets file called for an unknown type of OAuth 2.0 flow.Nr   r   r   r   r   r-      s   r-   c                   @   s   e Zd ZdZdS )AccessTokenCredentialsErrorz:Having only the access_token means no refresh is possible.Nr   r   r   r   r   r.      s   r.   c                   @   s   e Zd ZdZdS )VerifyJwtTokenErrorz/Could not retrieve certificates for validation.Nr   r   r   r   r   r/      s   r/   c                   @   s   e Zd ZdZdS )NonAsciiHeaderErrorz.Header names and values must be ASCII strings.Nr   r   r   r   r   r0      s   r0   c                   @   s   e Zd ZdZdS )"ApplicationDefaultCredentialsErrorz5Error retrieving the Application Default Credentials.Nr   r   r   r   r   r1      s   r1   c                   @   s   e Zd ZdZdS )OAuth2DeviceCodeErrorz'Error trying to retrieve a device code.Nr   r   r   r   r   r2      s   r2   c                   @   s   e Zd ZdZdS )CryptoUnavailableErrorz@Raised when a crypto library is required, but none is available.Nr   r   r   r   r   r3      s   r3   c                 C   s"   | rt | tjr| tS d S d S )N)
isinstancedatetimestrftimeEXPIRY_FORMAT)Zexpiryr   r   r   _parse_expiry   s    
r8   c                   @   sd   e Zd ZdZedgZdd Zdd Zdd Zd	d
 Z	dddZ
dd Zedd Zedd ZdS )Credentialsa-  Base class for all Credentials objects.

    Subclasses must define an authorize() method that applies the credentials
    to an HTTP transport.

    Subclasses must also specify a classmethod named 'from_json' that takes a
    JSON string as input and returns an instantiated Credentials object.
    storec                 C   s   t dS )a  Take an httplib2.Http instance (or equivalent) and authorizes it.

        Authorizes it for the set of credentials, usually by replacing
        http.request() with a method that adds in the appropriate headers and
        then delegates to the original Http.request() method.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.
        NNotImplementedErrorr&   httpr   r   r   	authorize   s    zCredentials.authorizec                 C   s   t dS zForces a refresh of the access_token.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.
        Nr;   r=   r   r   r   refresh   s    zCredentials.refreshc                 C   s   t dS zRevokes a refresh_token and makes the credentials void.

        Args:
            http: httplib2.Http, an http object to be used to make the revoke
                  request.
        Nr;   r=   r   r   r   revoke   s    zCredentials.revokec                 C   s   t dS )Add the authorization to the headers.

        Args:
            headers: dict, the headers to add the Authorization header to.
        Nr;   r&   headersr   r   r   apply   s    zCredentials.applyNc                 C   s   | j }|du rt| j}n
t|}|D ]}||v r*||= q*t|d|d< |j|d< |j|d< | D ]6\}}t|t	r|
d||< t|trlt|||< qlt|S )a  Utility function that creates JSON repr. of a Credentials object.

        Args:
            strip: array, An array of names of members to exclude from the
                   JSON.
            to_serialize: dict, (Optional) The properties for this object
                          that will be serialized. This allows callers to
                          modify before serializing.

        Returns:
            string, a JSON representation of this instance, suitable to pass to
            from_json().
        Ntoken_expiry_class_modulezutf-8)r*   copy__dict__r8   r%   r   r   itemsr4   bytesdecodesetlistjsondumps)r&   stripZto_serializeZ	curr_typememberkeyvalr   r   r   _to_json   s$    




zCredentials._to_jsonc                 C   s   |  | jS )zCreating a JSON representation of an instance of Credentials.

        Returns:
            string, a JSON representation of this instance, suitable to pass to
            from_json().
        )rX   NON_SERIALIZED_MEMBERSr&   r   r   r   to_json  s    zCredentials.to_jsonc                 C   s   t |}t|}|d }zt|}W n& tyN   |dd}t|}Y n0 t||ddd d}t||d }|	|S )	aX  Utility class method to instantiate a Credentials subclass from JSON.

        Expects the JSON string to have been produced by to_json().

        Args:
            json_data: string or bytes, JSON from to_json().

        Returns:
            An instance of the subclass of Credentials that was serialized with
            to_json().
        rJ   z.googleapiclient .N)fromlistrI   )
r   _from_bytesrR   loads
__import__ImportErrorreplacesplitgetattr	from_json)cls	json_dataZjson_data_as_unicodedatamodule_nameZ
module_objZklsr   r   r   new_from_json  s    

zCredentials.new_from_jsonc                 C   s   t  S )a(  Instantiate a Credentials object from a JSON description of it.

        The JSON should have been produced by calling .to_json() on the object.

        Args:
            unused_data: dict, A deserialized JSON object.

        Returns:
            An instance of a Credentials subclass.
        )r9   )rh   unused_datar   r   r   rg   <  s    zCredentials.from_json)N)r   r   r   r   	frozensetrY   r?   rA   rC   rG   rX   r[   classmethodrl   rg   r   r   r   r   r9      s   	
		
#	
r9   c                   @   s   e Zd ZdZdS )Flowz Base class for all Flow objects.Nr   r   r   r   r   rp   K  s   rp   c                   @   sZ   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd ZdS )StoragezBase class for all Storage objects.

    Store and retrieve a single credential. This class supports locking
    such that multiple processes and threads can operate on a single
    store.
    Nc                 C   s
   || _ dS )zCreate a Storage instance.

        Args:
            lock: An optional threading.Lock-like object. Must implement at
                  least acquire() and release(). Does not need to be
                  re-entrant.
        N)_lock)r&   lockr   r   r   r$   W  s    zStorage.__init__c                 C   s   | j dur| j   dS )zaAcquires any lock necessary to access this Storage.

        This lock is not reentrant.
        N)rr   acquirerZ   r   r   r   acquire_locka  s    
zStorage.acquire_lockc                 C   s   | j dur| j   dS )zRelease the Storage lock.

        Trying to release a lock that isn't held will result in a
        RuntimeError in the case of a threading.Lock or multiprocessing.Lock.
        N)rr   releaserZ   r   r   r   release_locki  s    
zStorage.release_lockc                 C   s   t dS )zRetrieve credential.

        The Storage lock must be held when this is called.

        Returns:
            oauth2client.client.Credentials
        Nr;   rZ   r   r   r   
locked_getr  s    zStorage.locked_getc                 C   s   t dS zWrite a credential.

        The Storage lock must be held when this is called.

        Args:
            credentials: Credentials, the credentials to store.
        Nr;   r&   credentialsr   r   r   
locked_put|  s    zStorage.locked_putc                 C   s   t dS )zYDelete a credential.

        The Storage lock must be held when this is called.
        Nr;   rZ   r   r   r   locked_delete  s    zStorage.locked_deletec                 C   s*   |    z|  W |   S |   0 dS )zRetrieve credential.

        The Storage lock must *not* be held when this is called.

        Returns:
            oauth2client.client.Credentials
        N)ru   rx   rw   rZ   r   r   r   r%     s    zStorage.getc                 C   s.   |    z| | W |   n
|   0 dS ry   )ru   r|   rw   rz   r   r   r   put  s    zStorage.putc                 C   s*   |    z|  W |   S |   0 dS )zDelete credential.

        Frees any resources associated with storing the credential.
        The Storage lock must *not* be held when this is called.

        Returns:
            None
        N)ru   r}   rw   rZ   r   r   r   delete  s    	zStorage.delete)N)r   r   r   r   r$   ru   rw   rx   r|   r}   r%   r~   r   r   r   r   r   rq   P  s   

	

rq   c                   @   s   e Zd ZdZedd2ddZdd Zdd	 Zd
d Z	dd Z
dd Zdd Zedd Zedd Zd3ddZdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 ZdS )4OAuth2Credentialsa  Credentials object for OAuth 2.0.

    Credentials can be applied to an httplib2.Http object using the authorize()
    method, which then adds the OAuth 2.0 access token to each request.

    OAuth2Credentials objects may be safely pickled and unpickled.
       Nc                 C   sl   || _ || _|| _|| _d| _|| _|| _|| _|| _|	| _	|| _
|
| _tt|pTg | _|| _d| _dS )a,  Create an instance of OAuth2Credentials.

        This constructor is not usually called by the user, instead
        OAuth2Credentials objects are instantiated by the OAuth2WebServerFlow.

        Args:
            access_token: string, access token.
            client_id: string, client identifier.
            client_secret: string, client secret.
            refresh_token: string, refresh token.
            token_expiry: datetime, when the access_token expires.
            token_uri: string, URI of token endpoint.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to None; a
                        token can't be revoked if this is None.
            id_token: object, The identity of the resource owner.
            token_response: dict, the decoded response to the token request.
                            None if a token hasn't been requested yet. Stored
                            because some providers (e.g. wordpress.com) include
                            extra fields that clients may want.
            scopes: list, authorized scopes for these credentials.
            token_info_uri: string, the URI for the token info endpoint.
                            Defaults to None; scopes can not be refreshed if
                            this is None.
            id_token_jwt: string, the encoded and signed identity JWT. The
                          decoded version of this is stored in id_token.

        Notes:
            store: callable, A callable that when passed a Credential
                   will store the credential back to where it came from.
                   This is needed to store the latest access_token if it
                   has expired and been refreshed.
        NF)r   	client_idclient_secretrefresh_tokenr:   rH   	token_uri
user_agent
revoke_uriid_tokenid_token_jwttoken_responserP   r   string_to_scopesscopestoken_info_uriinvalid)r&   r   r   r   r   rH   r   r   r   r   r   r   r   r   r   r   r   r$     s    'zOAuth2Credentials.__init__c                 C   s   t | | |S )a  Authorize an httplib2.Http instance with these credentials.

        The modified http.request method will add authentication headers to
        each request and will refresh access_tokens when a 401 is received on a
        request. In addition the http.request method has a credentials
        property, http.request.credentials, which is the Credentials object
        that authorized it.

        Args:
            http: An instance of ``httplib2.Http`` or something that acts
                  like it.

        Returns:
            A modified instance of http that was passed in.

        Example::

            h = httplib2.Http()
            h = credentials.authorize(h)

        You can't create a new OAuth subclass of httplib2.Authentication
        because it never gets passed the absolute URI, which is needed for
        signing. So instead we have to overload 'request' with a closure
        that adds in the Authorization header and then calls the original
        version of 'request()'.
        )r   Zwrap_http_for_authr=   r   r   r   r?     s    zOAuth2Credentials.authorizec                 C   s   |  | dS r@   )_refreshr=   r   r   r   rA     s    zOAuth2Credentials.refreshc                 C   s   |  | dS rB   )_revoker=   r   r   r   rC   #  s    zOAuth2Credentials.revokec                 C   s   d| j  |d< dS )rD   zBearer AuthorizationN)r   rE   r   r   r   rG   ,  s    zOAuth2Credentials.applyc                 C   s   t |}t|| jS )ak  Verify that the credentials are authorized for the given scopes.

        Returns True if the credentials authorized scopes contain all of the
        scopes given.

        Args:
            scopes: list or string, the scopes to check.

        Notes:
            There are cases where the credentials are unaware of which scopes
            are authorized. Notably, credentials obtained and stored before
            this code was added will not have scopes, AccessTokenCredentials do
            not have scopes. In both cases, you can use refresh_scopes() to
            obtain the canonical set of scopes.
        )r   r   rP   issubsetr   r&   r   r   r   r   
has_scopes4  s    
zOAuth2Credentials.has_scopesc                 C   s   |  | | jS )aJ  Retrieves the canonical list of scopes for this access token.

        Gets the scopes from the OAuth2 provider.

        Args:
            http: httplib2.Http, an http object to be used to make the refresh
                  request.

        Returns:
            A set of strings containing the canonical list of scopes.
        )_retrieve_scopesr   r=   r   r   r   retrieve_scopesG  s    
z!OAuth2Credentials.retrieve_scopesc                 C   s   t t|}|dr`t|d tjs`ztj|d t|d< W n t	y^   d|d< Y n0 | |d |d |d |d |d |d |d |d	d|d
d|dd|dd|dd|ddd}|d |_
|S )a*  Instantiate a Credentials object from a JSON description of it.

        The JSON should have been produced by calling .to_json() on the object.

        Args:
            json_data: string or bytes, JSON to deserialize.

        Returns:
            An instance of a Credentials subclass.
        rH   Nr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rR   ra   r   r`   r%   r4   r5   strptimer7   
ValueErrorr   rh   ri   rj   retvalr   r   r   rg   V  s6    







zOAuth2Credentials.from_jsonc                 C   s<   | j r
dS | jsdS t }|| jkr8td|| j dS dS )zTrue if the credential is expired or invalid.

        If the token_expiry isn't set, we assume the token doesn't expire.
        TFz2access_token is expired. Now: %s, token_expiry: %s)r   rH   _UTCNOWloggerinfo)r&   nowr   r   r   access_token_expired{  s    
z&OAuth2Credentials.access_token_expiredc                 C   s4   | j r| jr"|st }| | t| j |  dS )zReturn the access token and its expiration information.

        If the token does not exist, get one.
        If the token expired, refresh it.
        )r   r   )r   r   r   get_http_objectrA   r   _expires_inr=   r   r   r   get_access_token  s    
z"OAuth2Credentials.get_access_tokenc                 C   s
   || _ dS )av  Set the Storage for the credential.

        Args:
            store: Storage, an implementation of Storage object.
                   This is needed to store the latest access_token if it
                   has expired and been refreshed. This implementation uses
                   locking to check for updates before updating the
                   access_token.
        N)r:   )r&   r:   r   r   r   	set_store  s    
zOAuth2Credentials.set_storec                 C   s8   | j r4t }| j |kr0| j | }|jd |j S dS dS )a~  Return the number of seconds until this token expires.

        If token_expiry is in the past, this method will return 0, meaning the
        token has already expired.

        If token_expiry is None, this method will return None. Note that
        returning 0 in such a case would not be fair: the token may still be
        valid; we just don't know anything about it.
        iQ r   N)rH   r   daysseconds)r&   r   Z
time_deltar   r   r   r     s    


zOAuth2Credentials._expires_inc                 C   s   | j |  dS )z-Update this Credential from another instance.N)rL   update__getstate__)r&   otherr   r   r   _updateFromCredential  s    z'OAuth2Credentials._updateFromCredentialc                 C   s   t  | j}|d= |S )z5Trim the state down to something that can be pickled.r:   )rK   rL   )r&   dr   r   r   r     s    zOAuth2Credentials.__getstate__c                 C   s   | j | d| _dS )z8Reconstitute the state of the object from being pickled.N)rL   r   r:   )r&   stater   r   r   __setstate__  s    zOAuth2Credentials.__setstate__c                 C   s    t jd| j| j| jd}|S )z;Generate the body that will be used in the refresh request.r   )
grant_typer   r   r   )r   parse	urlencoder   r   r   )r&   bodyr   r   r   _generate_refresh_request_body  s    z0OAuth2Credentials._generate_refresh_request_bodyc                 C   s    ddi}| j dur| j |d< |S )z>Generate the headers that will be used in the refresh request.content-type!application/x-www-form-urlencodedN
user-agent)r   rE   r   r   r   !_generate_refresh_request_headers  s
    

z3OAuth2Credentials._generate_refresh_request_headersc                 C   s   | j s| | nl| j   zT| j  }|rZ|jsZ|j| jkrZ|jsZtd | 	| n
| | W | j 
  n| j 
  0 dS )ay  Refreshes the access_token.

        This method first checks by reading the Storage object if available.
        If a refresh is still needed, it holds the Storage lock until the
        refresh is completed.

        Args:
            http: an object to be used to make HTTP requests.

        Raises:
            HttpAccessTokenRefreshError: When the refresh fails.
        z&Updated access_token read from StorageN)r:   _do_refresh_requestru   rx   r   r   r   r   r   r   rw   )r&   r>   Znew_credr   r   r   r     s    




zOAuth2Credentials._refreshc           	   	   C   s  |   }|  }td tj|| jd||d\}}t|}|j	t
jkrt|}|| _|d | _|d| j| _d|v rtjt|d d}|t  | _nd| _d	|v rt|d	 | _|d	 | _nd| _d| _d
| _| jr| j|  ntd| d|j	}zXt|}d|v rZ|d }d|v r<|d|d  7 }d| _| jdurZ| j|  W n ttfyt   Y n0 t ||j	ddS )zRefresh the access_token using the refresh_token.

        Args:
            http: an object to be used to make HTTP requests.

        Raises:
            HttpAccessTokenRefreshError: When the refresh fails.
        zRefreshing access_tokenPOSTmethodr   rF   r   r   r   r   Nr   F#Failed to retrieve access token: %sInvalid response {0}.errorerror_description: T)r"   )!r   r   r   r   r   requestr   r   r`   r"   r   OKrR   ra   r   r   r%   r   r5   	timedeltaintr   rH   _extract_id_tokenr   r   r   r:   r|   format	TypeErrorr   r!   )	r&   r>   r   rF   respcontentr   delta	error_msgr   r   r   r     sN    	







z%OAuth2Credentials._do_refresh_requestc                 C   s   |  || jp| j dS )zRevokes this credential and deletes the stored copy (if it exists).

        Args:
            http: an object to be used to make HTTP requests.
        N)
_do_revoker   r   r=   r   r   r   r   5  s    zOAuth2Credentials._revokec           
   	   C   s   t d d|i}t| j|}t||\}}|jtj	kr^t
j|}tj||d|d\}}|jtjkrrd| _nPd|j}z$tt|}	d|	v r|	d }W n ttfy   Y n0 t|| jr| j  dS )	a  Revokes this credential and deletes the stored copy (if it exists).

        Args:
            http: an object to be used to make HTTP requests.
            token: A string used as the token to be revoked. Can be either an
                   access_token or refresh_token.

        Raises:
            TokenRevokeError: If the revoke request does not return with a
                              200 OK.
        zRevoking tokentokenr   )r   r   Tr   r   N)r   r   r   update_query_paramsr   r   r   r"   r   METHOD_NOT_ALLOWEDr   r   r   r   r   r   rR   ra   r`   r   r   r,   r:   r   )
r&   r>   r   query_paramsZtoken_revoke_urir   r   r   r   r   r   r   r   r   =  s.    

zOAuth2Credentials._do_revokec                 C   s   |  || j dS )zRetrieves the list of authorized scopes from the OAuth2 provider.

        Args:
            http: an object to be used to make HTTP requests.
        N)_do_retrieve_scopesr   r=   r   r   r   r   a  s    z"OAuth2Credentials._retrieve_scopesc           	   	   C   s   t d |dd}t| j|}t||\}}t|}|jt	j
krlt|}tt|dd| _nJd|j}zt|}d|v r|d }W n ttfy   Y n0 t|dS )a|  Retrieves the list of authorized scopes from the OAuth2 provider.

        Args:
            http: an object to be used to make HTTP requests.
            token: A string used as the token to identify the credentials to
                   the provider.

        Raises:
            Error: When refresh fails, indicating the the access token is
                   invalid.
        zRefreshing scopesscope)r   fieldsr\   r   r   N)r   r   r   r   r   r   r   r`   r"   r   r   rR   ra   rP   r   r%   r   r   r   r   r   )	r&   r>   r   r   r   r   r   r   r   r   r   r   r   i  s$    




z%OAuth2Credentials._do_retrieve_scopes)NNNNNN)N)r   r   r   r   r   
positionalr$   r?   rA   rC   rG   r   r   ro   rg   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s<      9		
$


8$r   c                       s>   e Zd ZdZd fdd	Zedd Zdd Zd	d
 Z  Z	S )AccessTokenCredentialsa  Credentials object for OAuth 2.0.

    Credentials can be applied to an httplib2.Http object using the
    authorize() method, which then signs each request from that object
    with the OAuth 2.0 access token. This set of credentials is for the
    use case where you have acquired an OAuth 2.0 access_token from
    another place such as a JavaScript client or another web
    application, and wish to use it from Python. Because only the
    access_token is present it can not be refreshed and will in time
    expire.

    AccessTokenCredentials objects may be safely pickled and unpickled.

    Usage::

        credentials = AccessTokenCredentials('<an access token>',
            'my-user-agent/1.0')
        http = httplib2.Http()
        http = credentials.authorize(http)

    Raises:
        AccessTokenCredentialsExpired: raised when the access_token expires or
                                       is revoked.
    Nc              
      s$   t t| j|ddddd||d dS )a  Create an instance of OAuth2Credentials

        This is one of the few types if Credentials that you should contrust,
        Credentials objects are usually instantiated by a Flow.

        Args:
            access_token: string, access token.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to None; a
                        token can't be revoked if this is None.
        Nr   )r#   r   r$   )r&   r   r   r   r)   r   r   r$     s    
zAccessTokenCredentials.__init__c                 C   s&   t t|}t|d |d }|S )Nr   r   )rR   ra   r   r`   r   r   r   r   r   rg     s    z AccessTokenCredentials.from_jsonc                 C   s   t ddS )zRefreshes the access token.

        Args:
            http: unused HTTP object.

        Raises:
            AccessTokenCredentialsError: always
        z>The access_token is expired or invalid and can't be refreshed.N)r.   r=   r   r   r   r     s    	zAccessTokenCredentials._refreshc                 C   s   |  || j dS zRevokes the access_token and deletes the store if available.

        Args:
            http: an object to be used to make HTTP requests.
        Nr   r   r=   r   r   r   r     s    zAccessTokenCredentials._revoke)N)
r   r   r   r   r$   ro   rg   r   r   r+   r   r   r)   r   r     s   
r   c                  C   sb   t jtd} z0t j| ttd\}}|jtjko:|	t
tkW S  tjy\   td Y dS 0 dS )zDetermine if the current environment is Compute Engine.

    Returns:
        Boolean indicating whether or not the current environment is Google
        Compute Engine.
    )timeout)rF   z1Timeout attempting to reach GCE metadata service.FN)r   r   r   r   _GCE_METADATA_URI_GCE_HEADERSr"   r   r   r%   _METADATA_FLAVOR_HEADER_DESIRED_METADATA_FLAVORsocketr   r   r   )r>   response_r   r   r   _detect_gce_environment  s    

r   c                  C   sn   t jdurt jdv S zddl} W n ty2   Y n80 tjtd}|drVdt _dS |drjd	t _dS d
S )zDetects if the code is running in the App Engine environment.

    Returns:
        True if running in the GAE environment, False otherwise.
    N)GAE_PRODUCTION	GAE_LOCALr   r\   zGoogle App Engine/r   TzDevelopment/r   F)	r   r   Zgoogle.appenginerc   osenvironr%   _SERVER_SOFTWARE
startswith)ZgoogleZserver_softwarer   r   r   _in_gae_environment  s    



r   c                   C   s0   t jdurt jdkS tdkr,t r,dt _dS dS )zDetect if the code is running in the Compute Engine environment.

    Returns:
        True if running in the GCE environment, False otherwise.
    NZGCE_PRODUCTIONTrueTF)r   r   r   r   r   r   r   r   _in_gce_environment	  s    

r   c                       s   e Zd ZdZedgejB Zejf fdd	Z	dd Z
dd Zed	d
 Zedd Zedd Zedd Zedd Zedd Zedd Zedd Z  ZS )GoogleCredentialsa|  Application Default Credentials for use in calling Google APIs.

    The Application Default Credentials are being constructed as a function of
    the environment where the code is being run.
    More details can be found on this page:
    https://developers.google.com/accounts/docs/application-default-credentials

    Here is an example of how to use the Application Default Credentials for a
    service that requires authentication::

        from googleapiclient.discovery import build
        from oauth2client.client import GoogleCredentials

        credentials = GoogleCredentials.get_application_default()
        service = build('compute', 'v1', credentials=credentials)

        PROJECT = 'bamboo-machine-422'
        ZONE = 'us-central1-a'
        request = service.instances().list(project=PROJECT, zone=ZONE)
        response = request.execute()

        print(response)
    Z_private_keyc	           	   
      s$   t t| j||||||||d dS )a  Create an instance of GoogleCredentials.

        This constructor is not usually called by the user, instead
        GoogleCredentials objects are instantiated by
        GoogleCredentials.from_stream() or
        GoogleCredentials.get_application_default().

        Args:
            access_token: string, access token.
            client_id: string, client identifier.
            client_secret: string, client secret.
            refresh_token: string, refresh token.
            token_expiry: datetime, when the access_token expires.
            token_uri: string, URI of token endpoint.
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            revoke_uri: string, URI for revoke endpoint. Defaults to
                        oauth2client.GOOGLE_REVOKE_URI; a token can't be
                        revoked if this is None.
        r   N)r#   r   r$   )	r&   r   r   r   r   rH   r   r   r   r)   r   r   r$   6  s    
zGoogleCredentials.__init__c                 C   s   dS )zWhether this Credentials object is scopeless.

        create_scoped(scopes) method needs to be called in order to create
        a Credentials object for API calls.
        Fr   rZ   r   r   r   create_scoped_requiredQ  s    z(GoogleCredentials.create_scoped_requiredc                 C   s   | S )zfCreate a Credentials object for the given scopes.

        The Credentials type is preserved.
        r   r   r   r   r   create_scopedY  s    zGoogleCredentials.create_scopedc                 C   s   ddl m} tt|}|d dkr@|d dkr@|j|S |d dkrd|d dkrd|j|S t	|
d}| |d	 |d
 |d |d ||d |d |
dd d}|d |_|S )Nr   r
   rJ   zoauth2client.service_accountrI   ServiceAccountCredentials_JWTAccessCredentialsrH   r   r   r   r   r   r   r   r   r   )oauth2clientr
   rR   ra   r   r`   r   rg   r   r8   r%   r   )rh   ri   r
   rj   rH   Zgoogle_credentialsr   r   r   rg   `  s.    


	
zGoogleCredentials.from_jsonc                 C   s   d| j | j| jdS )z>Get the fields and values identifying the current credentials.r	   )typer   r   r   r   r   r   rZ   r   r   r   serialization_data}  s
    z$GoogleCredentials.serialization_datac                   C   s   t  s
dS t S )as  Attempts to get implicit credentials in Google App Engine env.

        If the current environment is not detected as App Engine, returns None,
        indicating no Google App Engine credentials can be detected from the
        current environment.

        Returns:
            None, if not in GAE, else an appengine.AppAssertionCredentials
            object.
        N)r   '_get_application_default_credential_GAEr   r   r   r   _implicit_credentials_from_gae  s    z0GoogleCredentials._implicit_credentials_from_gaec                   C   s   t  s
dS t S )al  Attempts to get implicit credentials in Google Compute Engine env.

        If the current environment is not detected as Compute Engine, returns
        None, indicating no Google Compute Engine credentials can be detected
        from the current environment.

        Returns:
            None, if not in GCE, else a gce.AppAssertionCredentials object.
        N)r   '_get_application_default_credential_GCEr   r   r   r   _implicit_credentials_from_gce  s    z0GoogleCredentials._implicit_credentials_from_gcec               
   C   s   t  } | s(t } tj| r"d}q4d} ndt d }| s<dS tt_z
t	| W S  t
tfy } zt| || W Y d}~n
d}~0 0 dS )as  Attempts to get implicit credentials from local credential files.

        First checks if the environment variable GOOGLE_APPLICATION_CREDENTIALS
        is set with a filename and then falls back to a configuration file (the
        "well known" file) associated with the 'gcloud' command line tool.

        Returns:
            Credentials object associated with the
            GOOGLE_APPLICATION_CREDENTIALS file or the "well known" file if
            either exist. If neither file is define, returns None, indicating
            no credentials from a file can detected from the current
            environment.
        zB (produced automatically when running "gcloud auth login" command)Nz (pointed to by z environment variable))_get_environment_variable_file_get_well_known_filer   pathisfiler   DEFAULT_ENV_NAMEr   r   -_get_application_default_credential_from_filer1   r   !_raise_exception_for_reading_json)Zcredentials_filename
extra_helpr   r   r   r    _implicit_credentials_from_files  s(    z2GoogleCredentials._implicit_credentials_from_filesc                 C   s<   | j | j| jg}|D ]}| }|dur|  S qttdS )aM  Gets credentials implicitly from the environment.

        Checks environment in order of precedence:
        - Environment variable GOOGLE_APPLICATION_CREDENTIALS pointing to
          a file with stored credentials information.
        - Stored "well known" file associated with `gcloud` command line tool.
        - Google App Engine (production and testing)
        - Google Compute Engine production environment.

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        N)r  r   r   r1   ADC_HELP_MSG)rh   Zenviron_checkerscheckerr{   r   r   r   _get_implicit_credentials  s    
z+GoogleCredentials._get_implicit_credentialsc                   C   s   t  S )zGet the Application Default Credentials for the current environment.

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        )r   r  r   r   r   r   get_application_default  s    z)GoogleCredentials.get_application_defaultc              
   C   sb   | rVt j| rVz
t| W S  ttfyR } zd}t| || W Y d}~q^d}~0 0 ntddS )a  Create a Credentials object by reading information from a file.

        It returns an object of type GoogleCredentials.

        Args:
            credential_filename: the path to the file from where the
                                 credentials are to be read

        Raises:
            ApplicationDefaultCredentialsError: raised when the credentials
                                                fail to be retrieved.
        z4 (provided as parameter to the from_stream() method)NzHThe parameter passed to the from_stream() method should point to a file.)r   r   r   r   r1   r   r   )Zcredential_filenamer   r  r   r   r   from_stream  s    zGoogleCredentials.from_stream)r   r   r   r   rn   r   rY   r   GOOGLE_REVOKE_URIr$   r   r   ro   rg   r   r   staticmethodr   r   r  r  r  r  r+   r   r   r)   r   r     s2   

	


(

	r   c                 C   sn   t  }t|tjtjB d}t|d$}tj||dddd W d   n1 sT0    Y  t	
||  dS )zSaves a file with read-write permissions on for the owner.

    Args:
        filename: String. Absolute path to file.
        json_contents: JSON serializable object to be saved.
    i  wT   ),r   )	sort_keysindent
separatorsN)tempfilemktempr   openO_WRONLYO_CREATfdopenrR   dumpshutilmove)filenameZjson_contentsZtemp_filenameZ	file_descZfile_handler   r   r   _save_private_file  s    
$r  c                 C   sH   |du rt  }tj|}tj|s4td|| j}t|| dS )a  Save the provided GoogleCredentials to the well known file.

    Args:
        credentials: the credentials to be saved to the well known file;
                     it should be an instance of GoogleCredentials
        well_known_file: the name of the file where the credentials are to be
                         saved; this parameter is supposed to be used for
                         testing only
    Nz$Config directory does not exist: {0})	r   r   r   dirnameisdirOSErrorr   r   r  )r{   Zwell_known_fileZ
config_dirZcredentials_datar   r   r   save_to_well_known_file&  s    r  c                  C   s>   t jtd } | r:t j| r"| S td|  d t d d S )NzFile z (pointed by z& environment variable) does not exist!)r   r   r%   r   r   r   r1   )Z'application_default_credential_filenamer   r   r   r   ?  s    r   c                  C   s   t t} | du rt jdkrhzt jt jd t} W q tyd   t j	dd}t j|dt} Y q0 nt jt j
ddt} t j| tS )	z@Get the well known file produced by command 'gcloud auth login'.NntAPPDATAZSystemDrivezC:\~z.config)r   getenv_CLOUDSDK_CONFIG_ENV_VARnamer   joinr   _CLOUDSDK_CONFIG_DIRECTORYKeyErrorr%   
expanduser_WELL_KNOWN_CREDENTIALS_FILE)Zdefault_config_dirdriver   r   r   r   N  s"    


r   c              	   C   s   t | }t|}W d   n1 s(0    Y  |d}|tkrRtg d}n.|tkrhtg d}ntdt d t d ||	 }|rt
| |d tkrtd|d |d	 |d
 dtjddS ddlm} |j|S dS )z4Build the Application Default Credentials from file.Nr   r   )r   Zclient_emailZprivate_key_idZprivate_keyz5'type' field should be defined (and have one of the 'z' or 'z	' values)r   r   r   zPython client library)r   r   r   r   rH   r   r   r   r   )r  rR   loadr%   AUTHORIZED_USERrP   SERVICE_ACCOUNTr1   
differencekeys#_raise_exception_for_missing_fieldsr   r   GOOGLE_TOKEN_URIr
   r   Zfrom_json_keyfile_dict)r  Zfile_objZclient_credentialsZcredentials_typeZrequired_fieldsmissing_fieldsr
   r   r   r   r   f  sF    
(
	r   c                 C   s   t dd|  d S )Nz(The following field(s) must be defined: z, )r1   r&  )r3  r   r   r   r1    s    r1  c                 C   s    t d|  | d t| d S )Nz2An error was encountered while reading json file: r   )r1   str)Zcredential_filer  r   r   r   r   r     s    r   c                  C   s   ddl m}  | g S Nr   AppAssertionCredentials)Zoauth2client.contrib.appenginer7  r6  r   r   r   r     s    r   c                  C   s   ddl m}  |  S r5  )Zoauth2client.contrib.gcer7  r6  r   r   r   r     s    r   c                       sV   e Zd ZdZeddejejf fdd	Z	dd Z
dd	 Zd
d Zdd Z  ZS )AssertionCredentialsa  Abstract Credentials object used for OAuth 2.0 assertion grants.

    This credential does not require a flow to instantiate because it
    represents a two legged flow, and therefore has all of the required
    information to generate and refresh its own access tokens. It must
    be subclassed to generate the appropriate assertion string.

    AssertionCredentials objects may be safely pickled and unpickled.
    r  Nc              
      s*   t t| jddddd|||d || _dS )a  Constructor for AssertionFlowCredentials.

        Args:
            assertion_type: string, assertion type that will be declared to the
                            auth server
            user_agent: string, The HTTP User-Agent to provide for this
                        application.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint.
        Nr   )r#   r8  r$   assertion_type)r&   r9  r   r   r   Zunused_kwargsr)   r   r   r$     s    
	zAssertionCredentials.__init__c                 C   s   |   }tj|dd}|S )Nz+urn:ietf:params:oauth:grant-type:jwt-bearer)	assertionr   )_generate_assertionr   r   r   )r&   r:  r   r   r   r   r     s    z3AssertionCredentials._generate_refresh_request_bodyc                 C   s   t dS )zAGenerate assertion string to be used in the access token request.Nr;   rZ   r   r   r   r;    s    z(AssertionCredentials._generate_assertionc                 C   s   |  || j dS r   r   r=   r   r   r   r     s    zAssertionCredentials._revokec                 C   s   t ddS )zCryptographically sign a blob (of bytes).

        Args:
            blob: bytes, Message to be signed.

        Returns:
            tuple, A pair of the private key ID used to sign the blob and
            the signed contents.
        zThis method is abstract.Nr;   )r&   Zblobr   r   r   	sign_blob  s    
zAssertionCredentials.sign_blob)r   r   r   r   r   r   r   r2  r  r$   r   r;  r   r<  r+   r   r   r)   r   r8    s   

r8  c                   C   s   t stddS )zEnsure we have a crypto library, or throw CryptoUnavailableError.

    The oauth2client.crypt module requires either PyCrypto or PyOpenSSL
    to be available in order to function, but these are optional
    dependencies.
    zNo crypto library availableN)
HAS_CRYPTOr3   r   r   r   r   _require_crypto_or_die  s    r>  r  c                 C   sd   t   |du rt }t||\}}|jtjkrPtt	
|}t| ||S td|jdS )a  Verifies a signed JWT id_token.

    This function requires PyOpenSSL and because of that it does not work on
    App Engine.

    Args:
        id_token: string, A Signed JWT.
        audience: string, The audience 'aud' that the token should be for.
        http: httplib2.Http, instance to use to make the HTTP request. Callers
              should supply an instance that has caching enabled.
        cert_uri: string, URI of the certificates in JSON format to
                  verify the JWT against.

    Returns:
        The deserialized JSON in the JWT.

    Raises:
        oauth2client.crypt.AppIdentityError: if the JWT fails to verify.
        CryptoUnavailableError: if no crypto library is available.
    NzStatus code: {0})r>  r   Zget_cached_httpr   r"   r   r   rR   ra   r   r`   r   Zverify_signed_jwt_with_certsr/   r   )r   Zaudiencer>   Zcert_urir   r   certsr   r   r   verify_id_token  s    r@  c                 C   sV   t | tkr| d}n
| d}t|dkr<td| tt	t
|d S )zExtract the JSON payload from a JWT.

    Does the extraction w/o checking the signature.

    Args:
        id_token: string or bytestring, OAuth 2.0 id_token.

    Returns:
        object, The deserialized JSON payload.
       .r]   r   z&Wrong number of segments in token: {0}   )r   rN   re   lenr/   r   rR   ra   r   r`   Z_urlsafe_b64decode)r   segmentsr   r   r   r     s    
r   c                 C   sX   i }t | } zt| }W n ty8   t | }Y n0 |rTd|v rT|d|d< |S )aM  Parses response of an exchange token request.

    Most providers return JSON but some (e.g. Facebook) return a
    url-encoded string.

    Args:
        content: The body of a response

    Returns:
        Content as a dictionary object. Note that the dict could be empty,
        i.e. {}. That basically indicates a failure.
    expiresr   )r   r`   rR   ra   	ExceptionZparse_unique_urlencodedpop)r   r   r   r   r   _parse_exchange_token_response4  s    
rH     postmessagec                 C   s2   t | |||||||	|
|||d}|j||d}|S )a  Exchanges an authorization code for an OAuth2Credentials object.

    Args:
        client_id: string, client identifier.
        client_secret: string, client secret.
        scope: string or iterable of strings, scope(s) to request.
        code: string, An authorization code, most likely passed down from
              the client
        redirect_uri: string, this is generally set to 'postmessage' to match
                      the redirect_uri that the client specified
        http: httplib2.Http, optional http instance to use to do the fetch
        token_uri: string, URI for token endpoint. For convenience defaults
                   to Google's endpoints but any OAuth 2.0 provider can be
                   used.
        auth_uri: string, URI for authorization endpoint. For convenience
                  defaults to Google's endpoints but any OAuth 2.0 provider
                  can be used.
        revoke_uri: string, URI for revoke endpoint. For convenience
                    defaults to Google's endpoints but any OAuth 2.0 provider
                    can be used.
        device_uri: string, URI for device authorization endpoint. For
                    convenience defaults to Google's endpoints but any OAuth
                    2.0 provider can be used.
        pkce: boolean, default: False, Generate and include a "Proof Key
              for Code Exchange" (PKCE) with your authorization and token
              requests. This adds security for installed applications that
              cannot protect a client_secret. See RFC 7636 for details.
        code_verifier: bytestring or None, default: None, parameter passed
                       as part of the code exchange when pkce=True. If
                       None, a code_verifier will automatically be
                       generated as part of step1_get_authorize_url(). See
                       RFC 7636 for details.

    Returns:
        An OAuth2Credentials object.

    Raises:
        FlowExchangeError if the authorization code cannot be exchanged for an
        access token
    )	redirect_urir   auth_urir   r   
device_urir   pkcecode_verifierr>   )OAuth2WebServerFlowstep2_exchange)r   r   r   coderK  r>   r   r   rL  r   rM  r   rN  rO  flowr{   r   r   r   credentials_from_codeQ  s    3rU  c           
      C   s&   t | |||||d}|j||d}	|	S )a	  Returns OAuth2Credentials from a clientsecrets file and an auth code.

    Will create the right kind of Flow based on the contents of the
    clientsecrets file or will raise InvalidClientSecretsError for unknown
    types of Flows.

    Args:
        filename: string, File name of clientsecrets.
        scope: string or iterable of strings, scope(s) to request.
        code: string, An authorization code, most likely passed down from
              the client
        message: string, A friendly string to display to the user if the
                 clientsecrets file is missing or invalid. If message is
                 provided then sys.exit will be called in the case of an error.
                 If message in not provided then
                 clientsecrets.InvalidClientSecretsError will be raised.
        redirect_uri: string, this is generally set to 'postmessage' to match
                      the redirect_uri that the client specified
        http: httplib2.Http, optional http instance to use to do the fetch
        cache: An optional cache service client that implements get() and set()
               methods. See clientsecrets.loadfile() for details.
        device_uri: string, OAuth 2.0 device authorization endpoint
        pkce: boolean, default: False, Generate and include a "Proof Key
              for Code Exchange" (PKCE) with your authorization and token
              requests. This adds security for installed applications that
              cannot protect a client_secret. See RFC 7636 for details.
        code_verifier: bytestring or None, default: None, parameter passed
                       as part of the code exchange when pkce=True. If
                       None, a code_verifier will automatically be
                       generated as part of step1_get_authorize_url(). See
                       RFC 7636 for details.

    Returns:
        An OAuth2Credentials object.

    Raises:
        FlowExchangeError: if the authorization code cannot be exchanged for an
                           access token
        UnknownClientSecretsFlowError: if the file describes an unknown kind
                                       of Flow.
        clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
                                                 invalid.
    )messagecacherK  rM  rP  )flow_from_clientsecretsrR  )
r  r   rS  rV  rK  r>   rW  rM  rT  r{   r   r   r   'credentials_from_clientsecrets_and_code  s    2rY  c                   @   s   e Zd ZdZedd ZdS )DeviceFlowInfoz5Intermediate information the OAuth2 for devices flow.c                 C   s   |d |d d}| d| d}|du r4td||d< || ddd	 d
|v rxt tjt|d
 d |d< | f i |S )zCreate a DeviceFlowInfo from a server response.

        The response should be a dict containing entries as described here:

        http://tools.ietf.org/html/draft-ietf-oauth-v2-05#section-3.7.1
        device_code	user_code)r[  r\  verification_urlZverification_uriNz/No verification_url provided in server responseinterval)r^  user_code_expiryr   r   r_  )r%   r2   r   r   r5   r   r   )rh   r   r(   r]  r   r   r   FromResponse  s*    

zDeviceFlowInfo.FromResponseN)r   r   r   r   ro   r`  r   r   r   r   rZ    s   rZ  )r[  r\  r^  r]  r_  c                 C   sT   ddd}| |  |d}|durPtd |dkrPtd d	|d
< |d= |S )z;Configures redirect URI parameters for OAuth2WebServerFlow.ZofflinerS  )Zaccess_typeZresponse_typeapproval_promptNzmThe approval_prompt parameter for OAuth2WebServerFlow is deprecated. Please use the prompt parameter instead.forcez=approval_prompt="force" has been adjusted to prompt="consent"Zconsentprompt)r   r%   r   warning)r(   paramsra  r   r   r   _oauth2_web_server_flow_params  s     

rf  c                   @   s   e Zd ZdZedddddejejej	dej
ejdddfddZedddd	Zeddd
dZeddddZdS )rQ  zrDoes the Web Server Flow for OAuth 2.0.

    OAuth2WebServerFlow objects may be safely pickled and unpickled.
    rI  NFc                 K   sx   |du rt d|| _|| _t|| _|| _|	| _|| _|| _	|| _
|| _|
| _|| _|| _|| _|| _t|| _dS )a~  Constructor for OAuth2WebServerFlow.

        The kwargs argument is used to set extra query parameters on the
        auth_uri. For example, the access_type and prompt
        query parameters can be set via kwargs.

        Args:
            client_id: string, client identifier.
            client_secret: string client secret.
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
                          for a non-web-based application, or a URI that
                          handles the callback from the authorization server.
            user_agent: string, HTTP User-Agent to provide for this
                        application.
            auth_uri: string, URI for authorization endpoint. For convenience
                      defaults to Google's endpoints but any OAuth 2.0 provider
                      can be used.
            token_uri: string, URI for token endpoint. For convenience
                       defaults to Google's endpoints but any OAuth 2.0
                       provider can be used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.
            login_hint: string, Either an email address or domain. Passing this
                        hint will either pre-fill the email box on the sign-in
                        form or select the proper multi-login session, thereby
                        simplifying the login flow.
            device_uri: string, URI for device authorization endpoint. For
                        convenience defaults to Google's endpoints but any
                        OAuth 2.0 provider can be used.
            authorization_header: string, For use with OAuth 2.0 providers that
                                  require a client to authenticate using a
                                  header value instead of passing client_secret
                                  in the POST body.
            pkce: boolean, default: False, Generate and include a "Proof Key
                  for Code Exchange" (PKCE) with your authorization and token
                  requests. This adds security for installed applications that
                  cannot protect a client_secret. See RFC 7636 for details.
            code_verifier: bytestring or None, default: None, parameter passed
                           as part of the code exchange when pkce=True. If
                           None, a code_verifier will automatically be
                           generated as part of step1_get_authorize_url(). See
                           RFC 7636 for details.
            **kwargs: dict, The keyword arguments are all optional and required
                      parameters for the OAuth calls.
        Nz#The value of scope must not be None)r   r   r   r   Zscopes_to_stringr   rK  
login_hintr   rL  r   r   rM  r   authorization_headerr   rO  rf  re  )r&   r   r   r   rK  r   rL  r   r   rg  rM  r   rh  rN  rO  r(   r   r   r   r$     s"    BzOAuth2WebServerFlow.__init__rB  c                 C   s   |durt d || _| jdu r*td| j| j| jd}|durL||d< | jdur`| j|d< | jr| jsvt | _t	| j}||d< d|d	< |
| j t| j|S )
a  Returns a URI to redirect to the provider.

        Args:
            redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
                          for a non-web-based application, or a URI that
                          handles the callback from the authorization server.
                          This parameter is deprecated, please move to passing
                          the redirect_uri in via the constructor.
            state: string, Opaque state string which is passed through the
                   OAuth2 flow and returned to the client as a query parameter
                   in the callback.

        Returns:
            A URI as a string to redirect the user to begin the authorization
            flow.
        NzThe redirect_uri parameter for OAuth2WebServerFlow.step1_get_authorize_url is deprecated. Please move to passing the redirect_uri in via the constructor.z+The value of redirect_uri must not be None.)r   rK  r   r   rg  code_challengeZS256Zcode_challenge_method)r   rd  rK  r   r   r   rg  r   rO  ri  r   re  r   r   rL  )r&   rK  r   r   	challenger   r   r   step1_get_authorize_urlg  s.    



z+OAuth2WebServerFlow.step1_get_authorize_urlc           
   
   C   s*  | j du rtdtj| j| jd}ddi}| jdurD| j|d< |du rTt	 }tj
|| j d||d\}}t|}|jtjkrzt|}W n4 ty } ztd	||W Y d}~n
d}~0 0 t|S d
|j}z*t|}	d|	v r|d|	d 7 }W n ty   Y n0 t|dS )zReturns a user code and the verification URL where to enter it

        Returns:
            A user code as a string for the user to authorize the application
            An URL as a string where the user has to enter the code
        Nz)The value of device_uri must not be None.)r   r   r   r   r   r   r   z<Could not parse server response as JSON: "{0}", error: "{1}"r   r   z Error: {0})rM  r   r   r   r   r   r   r   r   r   r   r   r`   r"   r   r   rR   ra   r2   r   rZ  r`  )
r&   r>   r   rF   r   r   Z	flow_infoexcr   Z
error_dictr   r   r   step1_get_device_and_user_codes  sD    







z3OAuth2WebServerFlow.step1_get_device_and_user_codesr  c                 C   sT  |du r|du rt d|dur0|dur0t d|du r@|j}n2t|tjtjfsrd|vrjt|dd|d }| j|| j	d}| j
dur| j
|d< | jr| j|d	< |durd
|d< nd|d< | j|d< tj|}ddi}| jdur| j|d< | jdur| j|d< |du rt }tj|| jd||d\}}t|}	|jtjkrd|	v r|	d }
|	dd}|sxtd d}d|	v rtjt|	d d}|t   }d}d}d|	v rt!|	d }|	d }td t"|
| j| j
||| j| j| j#|||	| j	| j$dS td| d|	v r8t%|	d t%|	dd }nd&t%|j}t|dS ) a  Exchanges a code for OAuth2Credentials.

        Args:
            code: string, a dict-like object, or None. For a non-device
                  flow, this is either the response code as a string, or a
                  dictionary of query parameters to the redirect_uri. For a
                  device flow, this should be None.
            http: httplib2.Http, optional http instance to use when fetching
                  credentials.
            device_flow_info: DeviceFlowInfo, return value from step1 in the
                              case of a device flow.

        Returns:
            An OAuth2Credentials object that can be used to authorize requests.

        Raises:
            FlowExchangeError: if a problem occurred exchanging the code for a
                               refresh_token.
            ValueError: if code and device_flow_info are both provided or both
                        missing.
        Nz%No code or device_flow_info provided.z.Cannot provide both code and device_flow_info.rS  r   z-No code was supplied in the query parameters.)r   rS  r   r   rO  z&http://oauth.net/grant_type/device/1.0r   Zauthorization_coderK  r   r   r   r   r   r   r   r   z_Received token response with no refresh_token. Consider reauthenticating with prompt='consent'.r   r   r   z#Successfully retrieved access tokenr   r   r   r\   zInvalid response: {0}.)'r   r[  r4   sixstring_typesbinary_typer   r%   r   r   r   r   rO  rK  r   r   r   rh  r   r   r   r   r   rH  r"   r   r   r   r   r5   r   r   r   r   r   r   r   r4  r   )r&   rS  r>   Zdevice_flow_infoZ	post_datar   rF   r   r   r   r   r   rH   r   Zextracted_id_tokenr   r   r   r   r   rR    s    
















z"OAuth2WebServerFlow.step2_exchange)NN)N)NNN)r   r   r   r   r   r   r   GOOGLE_AUTH_URIr2  r  GOOGLE_DEVICE_URIGOOGLE_TOKEN_INFO_URIr$   rk  rm  rR  r   r   r   r   rQ    s,   S//rQ  c
              
   C   s   zt j| |d\}
}|
t jt jfv r||d |d |d}|d}d}|D ] }t | durLt | ||< qLt|d |d	 |fi |W S W nN t jy } z4|dur|jrd
	||}t
| n W Y d}~nd}~0 0 td	|
dS )a*  Create a Flow from a clientsecrets file.

    Will create the right kind of Flow based on the contents of the
    clientsecrets file or will raise InvalidClientSecretsError for unknown
    types of Flows.

    Args:
        filename: string, File name of client secrets.
        scope: string or iterable of strings, scope(s) to request.
        redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for
                      a non-web-based application, or a URI that handles the
                      callback from the authorization server.
        message: string, A friendly string to display to the user if the
                 clientsecrets file is missing or invalid. If message is
                 provided then sys.exit will be called in the case of an error.
                 If message in not provided then
                 clientsecrets.InvalidClientSecretsError will be raised.
        cache: An optional cache service client that implements get() and set()
               methods. See clientsecrets.loadfile() for details.
        login_hint: string, Either an email address or domain. Passing this
                    hint will either pre-fill the email box on the sign-in form
                    or select the proper multi-login session, thereby
                    simplifying the login flow.
        device_uri: string, URI for device authorization endpoint. For
                    convenience defaults to Google's endpoints but any
                    OAuth 2.0 provider can be used.

    Returns:
        A Flow object.

    Raises:
        UnknownClientSecretsFlowError: if the file describes an unknown kind of
                                       Flow.
        clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
                                                 invalid.
    )rW  rL  r   )rK  rL  r   rg  r   )r   rM  rN  rO  rc  Nr   r   z)The client secrets were invalid: 
{0}
{1}z)This OAuth 2.0 flow is unsupported: {0!r})r   ZloadfileZTYPE_WEBZTYPE_INSTALLEDr%   localsrQ  ZInvalidClientSecretsErrorr'   r   sysexitr-   )r  r   rK  rV  rW  rg  rM  rN  rO  rc  Zclient_typeZclient_infoZconstructor_kwargsr   optionalparamer   r   r   rX  ,  sD    )

rX  )N)NrJ  NNN)NNNNNNNN)mr   collectionsrK   r5   rR   loggingr   r  r   ru  r  rn  Z	six.movesr   r   r   r   r   r   r   ZHAS_OPENSSLr=  r   ZOpenSSLVerifierrc   	getLoggerr   r   r7   ZID_TOKEN_VERIFICATION_CERTSZID_TOKEN_VERIFICATON_CERTSZOOB_CALLBACK_URNr-  r.  r   r'  r$  r  r*  
namedtupler   r   r#  r   r   r   r   r   r   r   r   r   utcnowr   Zclean_headersZMemoryCacheZREFRESH_STATUS_CODESobjectr   rF  r   r   r    r!   r,   r-   r.   r/   r0   r1   r2   r<   r3   r8   r9   rp   rq   r   r   r   r   r   r   r  r  r   r   r   r1  r   r   r   r8  r>  r   r@  r   rH  r2  rq  r  rr  rs  rU  rY  rZ  rf  rQ  rX  r   r   r   r   <module>   s  
	
 i   SN  
%J"A     8&  !    