Test request-based signing

This commit is contained in:
Jamie Bliss 2024-01-11 23:07:37 -05:00
parent 28bf2540fc
commit e4b2ec5d0d
No known key found for this signature in database
2 changed files with 55 additions and 3 deletions

View file

@ -199,7 +199,9 @@ class HttpSignature:
raise ValueError("URI does not contain a scheme")
# Create the core header field set
date_string = http_date()
request.headers["(request-target)"] = f"{request.method} {request.url.path}"
request.headers[
"(request-target)"
] = f"{request.method.lower()} {request.url.path}"
request.headers["Host"] = request.url.host
request.headers["Date"] = date_string
# If we have a body, add a digest and content type
@ -208,9 +210,9 @@ class HttpSignature:
request.headers["Digest"] = cls.calculate_digest(body_bytes)
# Sign the headers
signing_headers = {
signing_headers = [
key for key in request.headers.keys() if key.lower() != "user-agent"
}
]
signed_string = "\n".join(
f"{name.lower()}: {value}"
for name, value in request.headers.items()

View file

@ -1,3 +1,6 @@
import json
import httpx
import pytest
from django.test.client import RequestFactory
from pytest_httpx import HTTPXMock
@ -99,6 +102,53 @@ def test_sign_http(httpx_mock: HTTPXMock, keypair):
HttpSignature.verify_request(fake_request, keypair["public_key"])
def test_sign_request(keypair):
"""
Tests signing HTTP requests by round-tripping them through our verifier
"""
# Create document
document = {
"id": "https://example.com/test-create",
"type": "Create",
"actor": "https://example.com/test-actor",
"object": {
"id": "https://example.com/test-object",
"type": "Note",
},
}
# Normally, Client.post() handles all this encoding. But that doesn't apply
# to raw Request objects.
request = httpx.Request(
"POST",
"https://example.com/test-actor",
headers={
"Content-Type": "application/json",
},
content=json.dumps(document).encode("utf-8"),
)
# Send the signed request to the mock library
HttpSignature.sign_request(
request=request,
private_key=keypair["private_key"],
key_id=keypair["public_key_id"],
)
# Retrieve it and construct a fake request object
fake_request = RequestFactory().post(
path="/test-actor",
data=request.content,
**{
(
"content_type"
if name.lower() == "content-type"
else f"HTTP_{name.upper()}"
): value
for name, value in request.headers.items()
},
)
# Verify that
HttpSignature.verify_request(fake_request, keypair["public_key"])
def test_verify_http(keypair):
"""
Tests verifying HTTP requests against a known good example