Certificate verify failed SSLError

Calling a google calendar API results in `certificate verify failure`.

## Expected Result

A successful API response, since the API endpoint is running fine

## Actual Result

```
C:\Workspace\Techroom\venvs\lazyhour\lazyhour\Scripts\python.exe C:/Workspace/Techroom/lazyhour-server/main.py
 * Serving Flask app "main" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 279-826-945
 * Running on http://localhost:5000/ (Press CTRL+C to quit)
C:\Workspace\Techroom\lazyhour-server\util\service_account.json
127.0.0.1 - - [22/May/2018 15:22:56] "GET /calendar/list HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_cors\extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_restful\__init__.py", line 273, in error_router
    return original_handler(e)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_cors\extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_restful\__init__.py", line 273, in error_router
    return original_handler(e)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\_compat.py", line 34, in reraise
    raise value.with_traceback(tb)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_restful\__init__.py", line 480, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask\views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_restful\__init__.py", line 595, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\flask_httpauth.py", line 93, in decorated
    return f(*args, **kwargs)
  File "C:\Workspace\Techroom\lazyhour-server\main.py", line 45, in get
    return calendar_service.get_calendar_list()
  File "C:\Workspace\Techroom\lazyhour-server\util\calendar_service.py", line 25, in get_calendar_list
    response = self.authed_session.get(self.service_base_url)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\requests\sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\auth\transport\requests.py", line 198, in request
    self._auth_request, method, url, request_headers)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\auth\credentials.py", line 121, in before_request
    self.refresh(request)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\oauth2\service_account.py", line 322, in refresh
    request, self._token_uri, assertion)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\oauth2\_client.py", line 145, in jwt_grant
    response_data = _token_endpoint_request(request, token_uri, body)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\oauth2\_client.py", line 106, in _token_endpoint_request
    method='POST', url=token_uri, headers=headers, body=body)
  File "C:\Workspace\Techroom\venvs\lazyhour\lazyhour\lib\site-packages\google\auth\transport\requests.py", line 124, in __call__
    six.raise_from(new_exc, caught_exc)
  File "<string>", line 3, in raise_from
    # Permission is hereby granted, free of charge, to any person obtaining a copy
google.auth.exceptions.TransportError: HTTPSConnectionPool(host='accounts.google.com', port=443): Max retries exceeded with url: /o/oauth2/token (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)'),))

```

## Reproduction Steps

```
from .auth_service import get_credentials
from google.auth.transport.requests import AuthorizedSession
import json
# Calendar service


class CalendarService:
    def __init__(self, calendar_id=''):
        self.credentials = get_credentials()
        self.authed_session = AuthorizedSession(self.credentials)
        self.service_base_url = 'https://www.googleapis.com/calendar/v3/users/me/calendarList'
        self.calendar_id = calendar_id

    def get_service_url(self):
        return('{base_url}/{calendar_id}'.format(
            base_url=self.service_base_url,
            calendar_id=self.calendar_id))

    def get_calendar(self):
        response = self.authed_session.get(self.get_service_url())
        calendar = response.json()
        return calendar

    def get_calendar_list(self):
        response = self.authed_session.get(self.service_base_url)
        calendar_list = response.json()
        return calendar_list
```

## System Information

The output of pip freeze is:
```
aniso8601==3.0.0
cachetools==2.1.0
certifi==2018.4.16
chardet==3.0.4
click==6.7
Flask==1.0.2
Flask-Cors==3.0.4
Flask-HTTPAuth==3.2.3
Flask-RESTful==0.3.6
google-auth==1.4.1
idna==2.6
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
pyasn1==0.4.2
pyasn1-modules==0.2.1
pytz==2018.4
requests==2.18.4
rsa==3.4.2
six==1.11.0
urllib3==1.22
Werkzeug==0.14.1
```
Python 3.6
Windows 10

This command is only available on Requests v2.16.4 and greater. Otherwise,
please provide some basic information about your system (Python version,
operating system, &c).


I changed the default value for `verify` argument in `sessions.py` file. and the error is gone Here is the method that defines the `request`:
```
    def request(self, method, url,
            params=None, data=None, headers=None, cookies=None, files=None,
            auth=None, timeout=None, allow_redirects=True, proxies=None,
            hooks=None, stream=None, verify=False, cert=None, json=None):
        """Constructs a :class:`Request <Request>`, prepares it and sends it.
        Returns :class:`Response <Response>` object.

        :param method: method for the new :class:`Request` object.
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary or bytes to be sent in the query
            string for the :class:`Request`.
        :param data: (optional) Dictionary, bytes, or file-like object to send
            in the body of the :class:`Request`.
        :param json: (optional) json to send in the body of the
            :class:`Request`.
        :param headers: (optional) Dictionary of HTTP Headers to send with the
            :class:`Request`.
        :param cookies: (optional) Dict or CookieJar object to send with the
            :class:`Request`.
        :param files: (optional) Dictionary of ``'filename': file-like-objects``
            for multipart encoding upload.
        :param auth: (optional) Auth tuple or callable to enable
            Basic/Digest/Custom HTTP Auth.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple
        :param allow_redirects: (optional) Set to True by default.
        :type allow_redirects: bool
        :param proxies: (optional) Dictionary mapping protocol or protocol and
            hostname to the URL of the proxy.
        :param stream: (optional) whether to immediately download the response
            content. Defaults to ``False``.
        :param verify: (optional) Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use. Defaults to ``True``.
        :param cert: (optional) if String, path to ssl client cert file (.pem).
            If Tuple, ('cert', 'key') pair.
        :rtype: requests.Response
        """
        # Create the Request.
        req = Request(
            method=method.upper(),
            url=url,
            headers=headers,
            files=files,
            data=data or {},
            json=json,
            params=params or {},
            auth=auth,
            cookies=cookies,
            hooks=hooks,
        )
        prep = self.prepare_request(req)

        proxies = proxies or {}

        settings = self.merge_environment_settings(
            prep.url, proxies, stream, verify, cert
        )

        # Send the request.
        send_kwargs = {
            'timeout': timeout,
            'allow_redirects': allow_redirects,
        }
        send_kwargs.update(settings)
        resp = self.send(prep, **send_kwargs)

        return resp
```

By the way just to save time please do not pass me back to google to resolve this issue, I already submitted an [issue](https://github.com/GoogleCloudPlatform/google-auth-library-python/issues/257) on the `google-auth` github repo, and they have declared you as responsible for the error.

Hi @pmesgari,

It seems like there may be some confusion about what’s going on here. The Python SSL module is rejecting your supplied certificate because it can’t be verified. The comment @theacodes linked in the original ticket has some more info on that.

The traceback you provided uses a large amount of code that isn’t part of Requests that appears to be creating auth objects that may be being handed to Requests. We’ll need a stripped down version of this, with an example of the kind of cert/credentials being provided before we’d be able to start debugging this.

That said, with the current information I don’t believe this is a defect in Requests, but rather bad input. Until we have confirmation there’s actually a bug here, this is something that would likely be better tracked in a [StackOverflow](https://stackoverflow.com) question.

@nateprewitt that is the response I was afraid of, `google-auth-library-python` people are blaming `requests` and you are saying it is the code being handed to Requests. That extra code you are mentioning is generated by `google-auth-library-python`. So how to go about this?

Whoa, definitely not blaming requests! (I'd only be blaming myself anyway,
as I'm the maintainer of urllib3). Google auth doesn't do anything in terms
of overriding request's ssl stuff, we just inject an authorization header.

I linked to this issue to show that this is not an issue that is unique to
google-auth. Lots of users run into this and as the comment above mentions
it is due to an outdated ssl version. Your options are to either update
openssl (which generally means updating Python) or switch to a more
insecure set of CA certificates.

On Tue, May 22, 2018, 2:36 PM Payam <notifications@github.com> wrote:

> @nateprewitt <https://github.com/nateprewitt> that is the response I was
> afraid of google-auth-library-python people are blaming requests and you
> are saying it is the code being handed to Requests. That extra code you are
> mentioning is generated by google-auth-library-python. So how to go about
> this?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/requests/requests/issues/4657#issuecomment-391148712>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAPUc-GgdI6IcwUinBmSgeSp-fq-AWZqks5t1ITcgaJpZM4UJU0F>
> .
>


@pmesgari, I’d start with the code you’ve written and work backwards from there. You may consider using something like `pdb` to see what objects are being handed to the Requests call. Likely the most important piece of information is the SSL certificate being used.

Once you know that, you should be able to create a much simpler repro and we can work from there in a StackOverflow question. Right now responses here are being pushed to 1200 people that are subscribed to this for the purpose on monitoring issues in Requests. Feel free to link the Stackoverflow issue here and I’ll follow up there.

I’d also try this on another machine/on a basic network configuration to verify this isn’t an environmental issues.

@nateprewitt this should be easily reduced by just making a request to "
https://accounts.google.com".

On Tue, May 22, 2018, 2:42 PM Nate Prewitt <notifications@github.com> wrote:

> @pmesgari <https://github.com/pmesgari>, I’d start with the code you’ve
> written and work backwards from there. You may consider using something
> like pdb to see what objects are being handed to the Requests call.
> Likely the most important piece of information is the SSL certificate being
> used.
>
> Once you know that, you should be able to create a much simpler repro and
> we can work from there in a StackOverflow question. Right now responses
> here are being pushed to 1200 people that are subscribed to this for the
> purpose on monitoring issues in Requests. Feel free to link the
> Stackoverflow issue here and I’ll follow up there.
>
> I’d also try this on another machine/on a basic network configuration to
> verify this isn’t an environmental issues.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/requests/requests/issues/4657#issuecomment-391150095>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAPUcz6fwID4js0bMkO75I6zd0m1KAseks5t1IY4gaJpZM4UJU0F>
> .
>


@nateprewitt I have already created the StackOverflow [question](https://stackoverflow.com/questions/50469027/certificate-verify-failed-google-api). I will also try to update openssl and get a smaller repo.

@theacodes yep, that’s likely all we need, I haven’t had a chance to look very deep into what all was being passed around. My guess is this is likely an OpenSSL issue or some other system configuration :)

@pmesgari, thanks! We’ll follow up over there.

@pmesgari An easy way to get a newer openssl on your system is by installing the latest pyOpenSSL which requests will use automagically.