Scenario:
You are developing a Python app that needs to perform OAuth and talking to Google APIs. And you also want to intercept HTTP traffic to gain more understanding or debug your app, but faced the following terrible terrible messages:
Traceback (most recent call last):
File "alt_google_sample.py", line 17, in <module>
creds = tools.run_flow(flow, store, http=my_http)
File "C:\python38\lib\site-packages\oauth2client\_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\python38\lib\site-packages\oauth2client\tools.py", line 243, in run_flow
credential = flow.step2_exchange(code, http=http)
File "C:\python38\lib\site-packages\oauth2client\_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\python38\lib\site-packages\oauth2client\client.py", line 2053, in step2_exchange
resp, content = transport.request(
File "C:\python38\lib\site-packages\oauth2client\transport.py", line 280, in request
return http_callable(uri, method=method, body=body, headers=headers,
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1982, in request
(response, content) = self._request(
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1650, in _request
(response, content) = self._conn_request(
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1557, in _conn_request
conn.connect()
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1326, in connect
self.sock = self._context.wrap_socket(sock, server_hostname=self.host)
File "C:\python38\lib\ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "C:\python38\lib\ssl.py", line 1040, in _create
self.do_handshake()
File "C:\python38\lib\ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1108)
>:(
What's the issue?
If you're doing man-in-the-middle (MITM) for HTTP requests/responses, your TLS/SSL verification will certainly fail. Unfortunately, 'verify=False' does not work as the Google API client library uses httplib2 instead. However, all is not lost.
Remediation:
Solution #2: Use self-signed certificate
Extract your intercepting software (e.g. Burpsuite) certificate, convert it to PEM format and then use the following code:
For full code, please visit:
https://github.com/breaktoprotect/Useful-Code-Snippets/blob/master/googleapiclient_disable_ssl_verify.py
Screenshots of results - Yay - interception successful!
File "alt_google_sample.py", line 17, in <module>
creds = tools.run_flow(flow, store, http=my_http)
File "C:\python38\lib\site-packages\oauth2client\_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\python38\lib\site-packages\oauth2client\tools.py", line 243, in run_flow
credential = flow.step2_exchange(code, http=http)
File "C:\python38\lib\site-packages\oauth2client\_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\python38\lib\site-packages\oauth2client\client.py", line 2053, in step2_exchange
resp, content = transport.request(
File "C:\python38\lib\site-packages\oauth2client\transport.py", line 280, in request
return http_callable(uri, method=method, body=body, headers=headers,
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1982, in request
(response, content) = self._request(
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1650, in _request
(response, content) = self._conn_request(
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1557, in _conn_request
conn.connect()
File "C:\python38\lib\site-packages\httplib2\__init__.py", line 1326, in connect
self.sock = self._context.wrap_socket(sock, server_hostname=self.host)
File "C:\python38\lib\ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "C:\python38\lib\ssl.py", line 1040, in _create
self.do_handshake()
File "C:\python38\lib\ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1108)
>:(
What's the issue?
If you're doing man-in-the-middle (MITM) for HTTP requests/responses, your TLS/SSL verification will certainly fail. Unfortunately, 'verify=False' does not work as the Google API client library uses httplib2 instead. However, all is not lost.
Remediation:
Import httplib2, instantiate a Http() object and use 'disable_ssl_certificate_validation=True' as the argument.
If you are using the Google Tutorial's sample code, this won't exactly work. :(
Instead, I used the code by https://github.com/butteredwaffles from https://medium.com/@butteredwaffles/working-with-google-calendar-api-8121d5048597 and modified the Http() object.
Solution #1: Disable the SSL verification altogether during testing.
...
my_http = httplib2.Http(disable_ssl_certificate_validation=True)
SCOPES = "https://www.googleapis.com/auth/calendar.readonly"
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store, http=my_http)
service = build('calendar', 'v3', http=creds.authorize(my_http))
...
Solution #2: Use self-signed certificate
Extract your intercepting software (e.g. Burpsuite) certificate, convert it to PEM format and then use the following code:
...
my_http = httplib2.Http(ca_certs='./burp.pem')
SCOPES = "https://www.googleapis.com/auth/calendar.readonly"
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store, http=my_http)
service = build('calendar', 'v3', http=creds.authorize(my_http))
...
For full code, please visit:
https://github.com/breaktoprotect/Useful-Code-Snippets/blob/master/googleapiclient_disable_ssl_verify.py
Screenshots of results - Yay - interception successful!