How to send a HTTP request with client certificate + private key + password/secret in Python 3

When we need to create a HTTP client that communicates with a HTTP server through certificate-based authentication, we will typically have to download a certificate, in .pem format, from the server.

After we had downloaded the .pem file, the HTTP client will use the private key and certificate to authenticate itself with the HTTP server. Sometimes, the HTTP client will need to decrypt the private key with a password/secret first.

So with a .pem file and a password/secret, how can you create a HTTP client in Python 3 to send a HTTP request to the HTTP server?

In case you need it, this post shows how to send a HTTP request with client certificate + private key + password/secret in Python 3.

Creating the sample Python 3 code that send a HTTP Post request to a HTTP endpoint with client certificate + private key + password/secret

Let's assume that there is an HTTP endpoint at https://example.com/a/http/url that authenticates clients with client certificates and receives HTTP Post requests.

In addition to that, the .pem file is named as a_certificate_file.pem and the certificate secret is your_certificate_secret.

Given these points, you can create a Python 3 file in the same folder as the .pem file with the following content to send a HTTP Post request to that HTTP endpoint:

import http.client
import json
import ssl

# Defining certificate related stuff and host of endpoint
certificate_file = 'a_certificate_file.pem'
certificate_secret= 'your_certificate_secret'
host = 'example.com'

# Defining parts of the HTTP request
request_url='/a/http/url' 
request_headers = {
    'Content-Type': 'application/json'
}
request_body_dict={
    'Temperature': 38,
    'Humidity': 80
}

# Define the client certificate settings for https connection
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile=certificate_file, password=certificate_secret)

# Create a connection to submit HTTP requests
connection = http.client.HTTPSConnection(host, port=443, context=context)

# Use connection to submit a HTTP POST request
connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict))

# Print the HTTP response from the IOT service endpoint
response = connection.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)

Understanding the sample Python 3 code that send a HTTP Post request to a HTTP endpoint with client certificate + private key + password/secret

First of all, we indicate that we wish to use some functionalities from http.client, json and ssl modules:

import http.client
import json
import ssl

After that, we define some variables for certificate related stuff, host of endpoint and parts of the HTTP request:

# Defining certificate related stuff and host of endpoint
certificate_file = 'a_certificate_file.pem'
certificate_secret= 'your_certificate_secret'
host = 'example.com'

# Defining parts of the HTTP request
request_url='/a/http/url' 
request_headers = {
    'Content-Type': 'application/json'
}
request_body_dict={
    'Temperature': 38,
    'Humidity': 80
}

Once we had defined the variables, we create a ssl.SSLContext object and load the certificate chain with what we have from the server:

# Define the client certificate settings for https connection
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile=certificate_file, password=certificate_secret)

Given that we have the SSL context, we then create a http.client.HTTPSConnection object for sending HTTP requests to the server:

# Create a connection to submit HTTP requests
connection = http.client.HTTPSConnection(host, port=443, context=context)

At this point of time, we can then use the http.client.HTTPSConnection object to send a HTTP request to the server endpoint:

# Use connection to submit a HTTP POST request
connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict))

Finally, we simply print some parts of the HTTP response that the server returns back to our client:

# Print the HTTP response from the IOT service endpoint
response = connection.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.