ó ôBQc@sdZddlZddlZddlZddlmZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mZddlmZyddlZWnEek ryddlmZWnek rddlZnXnXejdƒZe jƒZdZd efd „ƒYZd efd „ƒYZd efd„ƒYZdefd„ƒYZdefd„ƒYZ defd„ƒYZ!defd„ƒYZ"defd„ƒYZ#defd„ƒYZ$defd„ƒYZ%defd„ƒYZ&dS(sAn OAuth2 client library. This library provides a client implementation of the OAuth2 protocol (see http://code.google.com/apis/accounts/docs/OAuth2.html). **** Experimental API **** This module is experimental and is subject to modification or removal without notice. iÿÿÿÿN(tsha1(tcacerts(t fancy_urllib(t simplejsont oauth2_clientt(ed024a78d9327f8669b3b117d9eac9e3c9460e9btErrorcBseZdZRS(s%Base exception for the OAuth2 module.(t__name__t __module__t__doc__(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRGstAccessTokenRefreshErrorcBseZdZRS(s>Error trying to exchange a refresh token into an access token.(RRR (((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR LstAuthorizationCodeExchangeErrorcBseZdZRS(sDError trying to exchange an authorization code into a refresh token.(RRR (((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR Qst TokenCachecBs eZdZd„Zd„ZRS(s"Interface for OAuth2 token caches.cCs t‚dS(N(tNotImplementedError(tselftkeytvalue((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytPutTokenYscCs t‚dS(N(R (RR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytGetToken\s(RRR RR(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR Vs tNoopTokenCachecBs eZdZd„Zd„ZRS(s6A stub implementation of TokenCache that does nothing.cCsdS(N((RRR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRcscCsdS(N(tNone(RR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRfs(RRR RR(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR`s tInMemoryTokenCachecBs)eZdZd„Zd„Zd„ZRS(sAn in-memory token cache. The cache is implemented by a python dict, and inherits the thread-safety properties of dict. cCs#tt|ƒjƒtƒ|_dS(N(tsuperRt__init__tdicttcache(R((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRqscCs!tjd|ƒ||j||jj|dƒ}tjd||dkr3dndƒ|S(Ns-InMemoryTokenCache.GetToken: key=%s%s presents nott(RtgetRRR(RRR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRys (RRR RRR(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRjs  tFileSystemTokenCachecBs5eZdZdd„Zd„Zd„Zd„ZRS(sjAn implementation of a token cache that persists tokens on disk. Each token object in the cache is stored in serialized form in a separate file. The cache file's name can be configured via a path pattern that is parameterized by the key under which a value is cached and optionally the current processes uid as obtained by os.getuid(). Since file names are generally publicly visible in the system, it is important that the cache key does not leak information about the token's value. If client code computes cache keys from token values, a cryptographically strong one-way function must be used. cCsGtt|ƒjƒ||_|sCtjjtjƒdƒ|_ndS(sêCreates a FileSystemTokenCache. Args: path_pattern: Optional string argument to specify the path pattern for cache files. The argument should be a path with format placeholders '%(key)s' and optionally '%(uid)s'. If the argument is omitted, the default pattern /oauth2client-tokencache.%(uid)s.%(key)s is used, where is replaced with the system temp dir as obtained from tempfile.gettempdir(). s(oauth2_client-tokencache.%(uid)s.%(key)sN( RRRt path_patterntostpathtjointtempfilet gettempdir(RR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRŽs   cCs?d}yttjƒƒ}WnnX|ji|d6|d6S(Nt_Rtuid(tstrR tgetuidR(RRR&((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyt CacheFileName s cCs|j|ƒ}tjd||ƒytj|ƒWnnXtjtjBtjB}ttdƒrs|tj O}nttdƒr’|tj O}nytj ||dƒ}Wn-t t fk rÚ}tjd||ƒdSXtj|dƒ}|j|jƒƒ|jƒdS(sSerializes the value to the key's filename. To ensure that written tokens aren't leaked to a different users, we a) unlink an existing cache file, if any (to ensure we don't fall victim to symlink attacks and the like), b) create a new file with O_CREAT | O_EXCL (to ensure nobody is trying to race us) If either of these steps fail, we simply give up (but log a warning). Not caching access tokens is not catastrophic, and failure to create a file can happen for either of the following reasons: - someone is attacking us as above, in which case we want to default to safe operation (not write the token); - another legitimate process is racing us; in this case one of the two will win and write the access token, which is fine; - we don't have permission to remove the old file or write to the specified directory, in which case we can't recover Args: key: the refresh_token hash key to store. value: the access_token value to serialize. s4FileSystemTokenCache.PutToken: key=%s, cache_file=%st O_NOINHERITtO_BINARYi€sAFileSystemTokenCache.PutToken: Failed to create cache file %s: %sNsw+b(R)RRR tunlinktO_RDWRtO_CREATtO_EXCLthasattrR*R+topentOSErrortIOErrortwarningtfdopentwritet Serializetclose(RRRt cache_filetflagstfdtetf((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR©s*    cCsÙd}|j|ƒ}y/t|ƒ}tj|jƒƒ}|jƒWnfttfk r‡}|j t j kr­t j d||ƒq­n&t k r¬}t j d||ƒnXt jd||dkrËdnd|ƒ|S(s<Returns a deserialized access token from the key's filename.s?FileSystemTokenCache.GetToken: Failed to read cache file %s: %ssTFileSystemTokenCache.GetToken: Failed to read cache file %s (possibly corrupted): %ss?FileSystemTokenCache.GetToken: key=%s%s present (cache_file=%s)s notRN(RR)R1t AccessTokent UnSerializetreadR8R3R2terrnotENOENTRR4t ExceptionR(RRRR9R=R<((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRÜs     N(RRR RRR)RR(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR€s    3tOAuth2ProvidercBseZdZd„ZRS(s2Encapsulates information about an OAuth2 provider.cCs||_||_||_dS(sàCreates an OAuth2Provider. Args: label: A string identifying this oauth2 provider, e.g. "Google". authorization_uri: The provider's authorization URI. token_uri: The provider's token endpoint URI. N(tlabeltauthorization_urit token_uri(RRERFRG((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRõs  (RRR R(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRDòst OAuth2ClientcBsVeZdZdddejd„Zd„Zd„Zd„Zdd„Z d„Z RS(sAn OAuth2 client.c Cs ||_||_||_||_||_|p9tƒ|_tjj tjj tjj t j ƒƒdƒ|_|dkrþtƒ}|jt|jƒjƒƒ|jƒ} | tkrÔtdt| fƒ‚ntjtjƒtjƒtjƒƒ}n||_dS(syCreates an OAuth2Client. Args: provider: The OAuth2Provider provider this client will authenticate against. client_id: The OAuth2 client ID of this client. client_secret: The OAuth2 client secret of this client. url_opener: An optinal urllib2.OpenerDirector to use for making HTTP requests to the OAuth2 provider's token endpoint. The provided url_opener *must* be configured to validate server SSL certificates for requests to https connections, and to correctly handle proxying of https requests. If this argument is omitted or None, a suitable opener based on fancy_urllib is used. proxy: An optional string specifying a HTTP proxy to be used, in the form ':'. This option is only effective if the url_opener has been configured with a fancy_urllib.FancyProxyHandler (this is the case for the default url_opener). access_token_cache: An optional instance of a TokenCache. If omitted or None, an InMemoryTokenCache is used. datetime_strategy: datetime module strategy to use. s cacerts.txtsNCA certificates file does not have expected SHA1 sum; expected: %s, actual: %sN(tprovidert client_idt client_secrettdatetime_strategyt_proxyRtaccess_token_cacheR R!R"tdirnametabspathRt__file__t ca_certs_fileRRtupdatetfileR@t hexdigesttCACERTS_FILE_SHA1SUMRturllib2t build_openerRtFancyProxyHandlertFancyRedirectHandlertFancyHTTPSHandlert url_opener( RRIRJRKR\tproxyRNRLtht actual_sha1((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRs*      *      cCs!tj|ƒ}tjd|ƒd}ytj|jjd|ƒ}|j rb|j |j dƒn|j d|j ƒ|j j|ƒ}|jƒ}tjd|ƒWn@tjk ræ}ytj|jƒƒ}WnnX||fSXytj|ƒ}Wntk r}d|fSX|dfS(s Make a requst to this client's provider's token endpoint. Args: request: A dict with the request parameteres. Returns: A tuple (response, error) where, - response is the parsed JSON response received from the token endpoint, or None if no parseable response was received, and - error is None if the request succeeded or an Exception if an error occurred. s_TokenRequest request: %stdatathttptca_certss_TokenRequest response: %sN(turllibt urlencodeRtdebugRRt FancyRequestRIRGRMt set_proxyt set_ssl_infoRRR\R1R@RWt HTTPErrortjsontloadst ValueError(Rtrequesttbodytresponsetresultt resp_bodyR<((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyt _TokenRequest=s.     cCs¼tjƒz |jƒ}tjd|ƒ|jj|ƒ}tjd|ƒ|dksc|j ƒr¥tjdƒ|j |ƒ}tjd|ƒ|jj ||ƒn|SWdtj ƒXdS(s.Given a RefreshToken, obtains a corresponding access token. First, this client's access token cache is checked for an existing, not-yet-expired access token for the provided refresh token. If none is found, the client obtains a fresh access token for the provided refresh token from the OAuth2 provider's token endpoint. Args: refresh_token: The RefreshToken object which to get an access token for. Returns: The cached or freshly obtained AccessToken. Raises: AccessTokenRefreshError if an error occurs. s)GetAccessToken: checking cache for key %ss$GetAccessToken: token from cache: %ss.GetAccessToken: fetching fresh access token...s&GetAccessToken: fresh access token: %sN( ttoken_exchange_locktacquiretCacheKeyRRRNRReRt ShouldRefreshtFetchAccessTokenRtrelease(Rt refresh_tokent cache_keyt access_token((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytGetAccessTokenes   cCs idd6|jd6|jd6|jd6}tjd|ƒ|j|ƒ\}}tjd||ƒ|r©d}|r|drd |d}ntd ||fƒ‚nd |krÈtd |ƒ‚nd}d |kr|jj ƒt j dt |d ƒƒ}nt |d |d|jƒS(sqFetches an access token from the provider's token endpoint. Given a RefreshToken, fetches an access token from this client's OAuth2 provider's token endpoint. Args: refresh_token: The RefreshToken object which to get an access token for. Returns: The fetched AccessToken. Raises: AccessTokenRefreshError: if an error occurs. Ryt grant_typeRJRKsFetchAccessToken request: %ss*FetchAccessToken response (error = %s): %sRterrors; OAuth2 error: %ssHFailed to exchange refresh token into access token; request failed: %s%sR{s@Failed to exchange refresh token into access token; response: %st expires_intsecondsRLN(RJRKRyRReRrR RRLtutcnowtdatetimet timedeltatintR>(RRyRmRoR~t oauth2_errort token_expiry((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRw‡s4          cCsŸidd6|jd6|d6dj|ƒd6}|rD|j|ƒnttj|jjƒƒ}|jttj |dƒƒƒt j |ƒ|dRRsRtt RefreshTokenRNRRuRx( RR‡R‰R‘RmRoR~R…R†R{Rytrefresh_token_string((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytExchangeAuthorizationCodeásL            N( RRR RR‚RRrR|RwR”R˜(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRHs4 ( " / +R>cBs\eZdZejd„Zed„ƒZd„Zdd„Zd„Z d„Z d„Z RS( s$Encapsulates an OAuth2 access token.cCs||_||_||_dS(N(ttokentexpiryRL(RR™RšRL((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR)s  cCsšd„}tj|ƒ}|ds&dSd}||dƒ}|r„y5tjg|jdƒD]}t|ƒ^qZŒ}Wq„dSXnt||dƒ|ƒS(s7Creates an AccessToken object from its serialized form.cSs|j|dgƒdS(Ni(RR(tdR((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytGetValue2sR™Ršt,N(RŽtparse_qsRR‚tsplitR„R>(tqueryRœtkvRšt expiry_tupletn((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR?.s  /cCsŽi|jd6}|jr|j}|j|j|j|j|j|j|jf}dj g|D]}t |ƒ^q_ƒ|d&s   R–cBs)eZdZd„Zd„Zd„ZRS(s%Encapsulates an OAuth2 refresh token.cCs||_||_dS(N(RRy(RRRy((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRis cCs#tƒ}|j|jƒ|jƒS(s%Computes a cache key for this refresh token. The cache key is computed as the SHA1 hash of the token, and as such satisfies the FileSystemTokenCache requirement that cache keys do not leak information about token values. Returns: A hash key for this refresh token. (RRSRyRU(RR^((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyRums cCsd|jj|ƒjS(sÔGets the access token HTTP authorication header value. Returns: The value of an Authorization HTTP header that authenticates requests with an OAuth2 access token based on this refresh token. s Bearer %s(RR|R™(R((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytGetAuthorizationHeader{s(RRR RRuRµ(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pyR–fs  ('R RŽR‚RAthashlibRtloggingR R#t threadingRcRWRtbotoRt third_partyRRjt ImportErrort django.utilsRt getLoggerRtLockRsRVRCRR R tobjectR RRRRDRHR>R–(((s9/tmp/tmp.yUYbTOKr8o/gsutil/oauth2_plugin/oauth2_client.pytsF               rÿ%@