make_post_sell/debug_auth_headers.py
Russell Ballestrini 4fbe9fedd4 Apply black code formatting
Formatted Python code using black for:
- crypto_clients.py
- crypto_watcher.py
- test_crypto_watcher.py

Maintains consistent code style across the codebase.
2025-09-23 10:49:26 -04:00

70 lines
No EOL
2.6 KiB
Python

#!/usr/bin/env python3
"""
Debug script to examine the exact WWW-Authenticate header
that Monero wallet RPC sends and how urllib handles it.
"""
import urllib.request
import urllib.error
import json
def examine_auth_challenge():
"""Look at the WWW-Authenticate header from the server"""
print("=== Examining Authentication Challenge ===")
rpc_url = "http://127.0.0.1:18083/json_rpc"
payload = {"jsonrpc": "2.0", "id": 1, "method": "get_height"}
data = json.dumps(payload).encode()
# Make request without auth to get the challenge
req = urllib.request.Request(rpc_url, data=data,
headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req) as resp:
print("Unexpected: No auth required")
return None
except urllib.error.HTTPError as e:
if e.code == 401:
www_auth = e.headers.get('WWW-Authenticate', '')
print(f"WWW-Authenticate header: {www_auth!r}")
# Parse it
if www_auth.startswith('Digest '):
challenge = www_auth[7:].strip()
print(f"Challenge details: {challenge}")
# Parse individual components
import re
pattern = r'(\w+)=(?:"([^"]*)"|([^,\s]+))'
matches = re.findall(pattern, challenge)
print("Parsed components:")
for key, quoted_val, unquoted_val in matches:
val = quoted_val if quoted_val else unquoted_val
print(f" {key} = {val!r}")
return dict((key, quoted_val if quoted_val else unquoted_val)
for key, quoted_val, unquoted_val in matches)
else:
print(f"Not Digest auth: {www_auth}")
return None
else:
print(f"Unexpected error: {e.code} {e.reason}")
return None
if __name__ == "__main__":
challenge = examine_auth_challenge()
if challenge:
print()
print("=== Analysis ===")
print(f"Realm: {challenge.get('realm', 'NOT SET')}")
print(f"Nonce: {challenge.get('nonce', 'NOT SET')}")
print(f"QOP: {challenge.get('qop', 'NOT SET')}")
print(f"Algorithm: {challenge.get('algorithm', 'NOT SET (defaults to MD5)')}")
# Check for any unusual parameters
standard_params = {'realm', 'nonce', 'qop', 'algorithm', 'opaque'}
extra_params = set(challenge.keys()) - standard_params
if extra_params:
print(f"Extra parameters: {extra_params}")