Python Developer
Python Developer

Reputation: 633

"unable to get local issuer certificate" on Windows with Python and Postman after adding the client certificate

I'm a Data Engineer working in Windows 10.

I'm trying to make a simple Post request in Python to retrieve an authentication token to a custom database service.

My code is as straightforward as possible:

import requests
import ssl
import certifi


url = ""
headers = {'Content_Type': 'application/x-www-form-urlencoded'}
payload = {
    'password': '',
    'scope': '',
    'client_id': '',
    'client_secret': '',
    'username': '',
    'grant_type': ''

}

if __name__ == '__main__':
    token_response = requests.request("POST", url, headers=headers, data=payload)
    print(token_response.content)

I have removed the payload values as well as the url values for privacy. When I run the code, I get back enter image description here and enter image description here "Max retries exceeded with url", and "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)".

I am able to sidestep this error by setting verify=False in my Post request, but given that I am handling sensitive data, I cannot do that. I mention that to demonstrate that my credentials do work, and there is clearly something wrong with either the Cinchy certificate, my python setup, or the business network I am working on (VPN? Something else?).

I see from this answer (https://stackoverflow.com/a/67998066/9403186) that it might be that "If you are running under business network, contact the network administrator to apply required configurations at the network level." I am certainly running under a business network, what would the required configurations look like?

Most of the answers out there on this error mention that you need to download the CA certificate of the url (e.g. here Windows: Python SSL certificate verify failed), but I have done that and it is not working. I went to the site, logged in, clicked on the Chrome icon with the lock, and downloaded the certificate as a Base-64 encoded X.509, and added it to my certifi cacert.pem file 'C:\Users\gblinick\AppData\Local\Programs\Python\Python39\lib\site-packages\certifi\cacert.pem' as per https://medium.com/@menakajain/export-download-ssl-certificate-from-server-site-url-bcfc41ea46a2.

Any help here would be greatly appreciated. My hunch is that it has to do with the business network, but I don't know how to check this. Ideas would be fantastic.

Please let me know if I can provide further info.

Thanks so much!

EDIT: The request with Postman also doesn't work, unless I turn off SSL authentication, so clearly it's the same problem and this is not simply an issue with Python. If I make the same request with Powershell, however, it does work:

# [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$Result = Invoke-WebRequest -Uri $Endpoint -UseBasicParsing -Method 'Post' -Body $Body -Headers $Header -ErrorAction Stop # -SslProtocol Tls

This works whether or not I have the first line commented out or not. It seems like Powershell might have some built in SSL or TLS functionality that Python and Powershell do not. That, or the server somehow expects Powershell to connect and not Postman or Python. Note that I have # -SslProtocol Tls commented out because I was using Powershell 5.1 for which the SslProtocol does not exist.

Upvotes: 2

Views: 6290

Answers (1)

Python Developer
Python Developer

Reputation: 633

Ultimately, the answer was super simple: I was downloading the wrong corporate certificate. When downloading the SSL certificate from Chrome, there is a "Certification Path" tab. Mine had 3 certificates in it, I'll call them A, B, and C. B descended from A, and C from B. I made the mistake of downloading C, the lowest level one. When I downloaded A and put it in my cacert.pem file, it worked.

Upvotes: 2

Related Questions