Skip to content

Commit 2bbada5

Browse files
committed
Remove httplib2 parts from service_account module.
Towards googleapis#554.
1 parent 11482ad commit 2bbada5

File tree

3 files changed

+50
-37
lines changed

3 files changed

+50
-37
lines changed

oauth2client/service_account.py

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,17 @@
2020
import json
2121
import time
2222

23-
import httplib2
24-
2523
from oauth2client import crypt
2624
from oauth2client import GOOGLE_REVOKE_URI
2725
from oauth2client import GOOGLE_TOKEN_URI
26+
from oauth2client import transport
2827
from oauth2client import util
2928
from oauth2client._helpers import _from_bytes
3029
from oauth2client.client import _UTCNOW
3130
from oauth2client.client import AccessTokenInfo
3231
from oauth2client.client import AssertionCredentials
3332
from oauth2client.client import EXPIRY_FORMAT
3433
from oauth2client.client import SERVICE_ACCOUNT
35-
from oauth2client.transport import _apply_user_agent
36-
from oauth2client.transport import _initialize_headers
37-
from oauth2client.transport import clean_headers
3834

3935

4036
_PASSWORD_DEFAULT = 'notasecret'
@@ -604,37 +600,7 @@ def authorize(self, http):
604600
h = httplib2.Http()
605601
h = credentials.authorize(h)
606602
"""
607-
request_orig = http.request
608-
request_auth = super(
609-
_JWTAccessCredentials, self).authorize(http).request
610-
611-
# The closure that will replace 'httplib2.Http.request'.
612-
def new_request(uri, method='GET', body=None, headers=None,
613-
redirections=httplib2.DEFAULT_MAX_REDIRECTS,
614-
connection_type=None):
615-
if 'aud' in self._kwargs:
616-
# Preemptively refresh token, this is not done for OAuth2
617-
if self.access_token is None or self.access_token_expired:
618-
self.refresh(None)
619-
return request_auth(uri, method, body,
620-
headers, redirections,
621-
connection_type)
622-
else:
623-
# If we don't have an 'aud' (audience) claim,
624-
# create a 1-time token with the uri root as the audience
625-
headers = _initialize_headers(headers)
626-
_apply_user_agent(headers, self.user_agent)
627-
uri_root = uri.split('?', 1)[0]
628-
token, unused_expiry = self._create_token({'aud': uri_root})
629-
630-
headers['Authorization'] = 'Bearer ' + token
631-
return request_orig(uri, method, body,
632-
clean_headers(headers),
633-
redirections, connection_type)
634-
635-
# Replace the request method with our own closure.
636-
http.request = new_request
637-
603+
transport.wrap_http_for_jwt_access(self, http)
638604
return http
639605

640606
def get_access_token(self, http=None, additional_claims=None):

oauth2client/transport.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,51 @@ def new_request(uri, method='GET', body=None, headers=None,
195195
setattr(http.request, 'credentials', credentials)
196196

197197

198+
def wrap_http_for_jwt_access(credentials, http):
199+
"""Prepares an HTTP object's request method for JWT access.
200+
201+
Wraps HTTP requests with logic to catch auth failures (typically
202+
identified via a 401 status code). In the event of failure, tries
203+
to refresh the token used and then retry the original request.
204+
205+
Args:
206+
credentials: _JWTAccessCredentials, the credentials used to identify
207+
a service account that uses JWT access tokens.
208+
http: httplib2.Http, an http object to be used to make
209+
auth requests.
210+
"""
211+
orig_request_method = http.request
212+
wrap_http_for_auth(credentials, http)
213+
# The new value of ``http.request`` set by ``wrap_http_for_auth``.
214+
authenticated_request_method = http.request
215+
216+
# The closure that will replace 'httplib2.Http.request'.
217+
def new_request(uri, method='GET', body=None, headers=None,
218+
redirections=httplib2.DEFAULT_MAX_REDIRECTS,
219+
connection_type=None):
220+
if 'aud' in credentials._kwargs:
221+
# Preemptively refresh token, this is not done for OAuth2
222+
if (credentials.access_token is None or
223+
credentials.access_token_expired):
224+
credentials.refresh(None)
225+
return authenticated_request_method(uri, method, body,
226+
headers, redirections,
227+
connection_type)
228+
else:
229+
# If we don't have an 'aud' (audience) claim,
230+
# create a 1-time token with the uri root as the audience
231+
headers = _initialize_headers(headers)
232+
_apply_user_agent(headers, credentials.user_agent)
233+
uri_root = uri.split('?', 1)[0]
234+
token, unused_expiry = credentials._create_token({'aud': uri_root})
235+
236+
headers['Authorization'] = 'Bearer ' + token
237+
return orig_request_method(uri, method, body,
238+
clean_headers(headers),
239+
redirections, connection_type)
240+
241+
# Replace the request method with our own closure.
242+
http.request = new_request
243+
244+
198245
_CACHED_HTTP = httplib2.Http(MemoryCache())

tests/test_service_account.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ def mock_request(uri, method='GET', body=None, headers=None,
527527
self.assertEqual(payload['exp'], T1_EXPIRY)
528528
self.assertEqual(uri, self.url)
529529
self.assertEqual(bearer, b'Bearer')
530-
return (httplib2.Response({'status': '200'}), b'')
530+
return httplib2.Response({'status': '200'}), b''
531531

532532
h = httplib2.Http()
533533
h.request = mock_request

0 commit comments

Comments
 (0)