Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #561 from dhermes/service-account-to-transport
Browse files Browse the repository at this point in the history
Remove httplib2 parts from service_account module.
  • Loading branch information
dhermes authored Jul 21, 2016
2 parents 11482ad + 2bbada5 commit d168160
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 37 deletions.
38 changes: 2 additions & 36 deletions oauth2client/service_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,17 @@
import json
import time

import httplib2

from oauth2client import crypt
from oauth2client import GOOGLE_REVOKE_URI
from oauth2client import GOOGLE_TOKEN_URI
from oauth2client import transport
from oauth2client import util
from oauth2client._helpers import _from_bytes
from oauth2client.client import _UTCNOW
from oauth2client.client import AccessTokenInfo
from oauth2client.client import AssertionCredentials
from oauth2client.client import EXPIRY_FORMAT
from oauth2client.client import SERVICE_ACCOUNT
from oauth2client.transport import _apply_user_agent
from oauth2client.transport import _initialize_headers
from oauth2client.transport import clean_headers


_PASSWORD_DEFAULT = 'notasecret'
Expand Down Expand Up @@ -604,37 +600,7 @@ def authorize(self, http):
h = httplib2.Http()
h = credentials.authorize(h)
"""
request_orig = http.request
request_auth = super(
_JWTAccessCredentials, self).authorize(http).request

# The closure that will replace 'httplib2.Http.request'.
def new_request(uri, method='GET', body=None, headers=None,
redirections=httplib2.DEFAULT_MAX_REDIRECTS,
connection_type=None):
if 'aud' in self._kwargs:
# Preemptively refresh token, this is not done for OAuth2
if self.access_token is None or self.access_token_expired:
self.refresh(None)
return request_auth(uri, method, body,
headers, redirections,
connection_type)
else:
# If we don't have an 'aud' (audience) claim,
# create a 1-time token with the uri root as the audience
headers = _initialize_headers(headers)
_apply_user_agent(headers, self.user_agent)
uri_root = uri.split('?', 1)[0]
token, unused_expiry = self._create_token({'aud': uri_root})

headers['Authorization'] = 'Bearer ' + token
return request_orig(uri, method, body,
clean_headers(headers),
redirections, connection_type)

# Replace the request method with our own closure.
http.request = new_request

transport.wrap_http_for_jwt_access(self, http)
return http

def get_access_token(self, http=None, additional_claims=None):
Expand Down
47 changes: 47 additions & 0 deletions oauth2client/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,51 @@ def new_request(uri, method='GET', body=None, headers=None,
setattr(http.request, 'credentials', credentials)


def wrap_http_for_jwt_access(credentials, http):
"""Prepares an HTTP object's request method for JWT access.
Wraps HTTP requests with logic to catch auth failures (typically
identified via a 401 status code). In the event of failure, tries
to refresh the token used and then retry the original request.
Args:
credentials: _JWTAccessCredentials, the credentials used to identify
a service account that uses JWT access tokens.
http: httplib2.Http, an http object to be used to make
auth requests.
"""
orig_request_method = http.request
wrap_http_for_auth(credentials, http)
# The new value of ``http.request`` set by ``wrap_http_for_auth``.
authenticated_request_method = http.request

# The closure that will replace 'httplib2.Http.request'.
def new_request(uri, method='GET', body=None, headers=None,
redirections=httplib2.DEFAULT_MAX_REDIRECTS,
connection_type=None):
if 'aud' in credentials._kwargs:
# Preemptively refresh token, this is not done for OAuth2
if (credentials.access_token is None or
credentials.access_token_expired):
credentials.refresh(None)
return authenticated_request_method(uri, method, body,
headers, redirections,
connection_type)
else:
# If we don't have an 'aud' (audience) claim,
# create a 1-time token with the uri root as the audience
headers = _initialize_headers(headers)
_apply_user_agent(headers, credentials.user_agent)
uri_root = uri.split('?', 1)[0]
token, unused_expiry = credentials._create_token({'aud': uri_root})

headers['Authorization'] = 'Bearer ' + token
return orig_request_method(uri, method, body,
clean_headers(headers),
redirections, connection_type)

# Replace the request method with our own closure.
http.request = new_request


_CACHED_HTTP = httplib2.Http(MemoryCache())
2 changes: 1 addition & 1 deletion tests/test_service_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ def mock_request(uri, method='GET', body=None, headers=None,
self.assertEqual(payload['exp'], T1_EXPIRY)
self.assertEqual(uri, self.url)
self.assertEqual(bearer, b'Bearer')
return (httplib2.Response({'status': '200'}), b'')
return httplib2.Response({'status': '200'}), b''

h = httplib2.Http()
h.request = mock_request
Expand Down

0 comments on commit d168160

Please sign in to comment.