How to use digest authentication in httpBinding

I can't take full credit for this, except for mostly the determination part... between myself and some AI assistance for library syntax (I didn't have any history with the hashlib or constructing digest headers) I put together this headers handshake for digestive using the httpClient and some integrated libraries. The example below is for an Axis camera, but I expect the concept would work for other digest situations. I was able to resolve the resulting data from the function into a perspective image control, so it seems functional. Don't forget to change the username and password.

import base64
import json
import re
import hashlib
import random

#constants
vapixClient = system.net.httpClient() #API Http Client
resolution = '1280x720'
uriRoot = 'http://'
uriImageJpg = '/axis-cgi/jpg/image.cgi?resolution='
username = "#####"
password = "#####"

def GetSnapshotFromCamera(IPAddress):
	
	uri = uriRoot + IPAddress + uriImageJpg + resolution
	#Send unauthenticated request
	response = vapixClient.get(uri, timeout=20000)
	
	if response:
		status = response.getStatusCode()
		auth_header = str(response.getHeaders().get("WWW-Authenticate"))
		
		if "Digest" in auth_header:
			#Parse required values from the auth challenge
			realm = re.search(r'realm="([^"]+)"', auth_header).group(1)
        	nonce = re.search(r'nonce="([^"]+)"', auth_header).group(1)
        	qop = re.search(r'qop="([^"]+)"', auth_header)
        	qop = qop.group(1) if qop else "auth"

            #Create HA1, HA2, and response hash
        	ha1 = hashlib.md5("{}:{}:{}".format(username, realm, password)).hexdigest()
        	ha2 = hashlib.md5("GET:{}".format(uri)).hexdigest()
        	nc = "00000001"  # Nonce count
        	cnonce = str(random.randint(0, 99999999))  # Client nonce
        	response_hash = hashlib.md5("{}:{}:{}:{}:{}:{}".format(ha1, nonce, nc, cnonce, qop, ha2)).hexdigest()

        	#Construct Digest Authorization header
        	auth_header_value = (
            	'Digest username="{}", realm="{}", nonce="{}", uri="{}", '
            	'algorithm=MD5, response="{}", qop={}, nc={}, cnonce="{}"'
        	).format(username, realm, nonce, uri, response_hash, qop, nc, cnonce)

        	#Send the authenticated request
        	headers = {"Authorization": auth_header_value}
        	response = vapixClient.get(uri, headers=headers)
        	status = response.getStatusCode()
        	if status == 200:
				data = response.getBody()
				en64 = "data:image/jpg;base64,"+base64.b64encode(data)
				return en64
3 Likes