From 96cf1fe5ad781dab029070bf94c803b95a35f450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Z=C3=B6ller?= Date: Sat, 29 Nov 2025 22:00:35 +0100 Subject: [PATCH] More fixes --- .../security/HttpSignatureValidator.java | 25 ++++++++++++++++--- .../fitpub/service/FederationService.java | 19 ++++++++------ src/main/resources/application-dev.yml | 7 ++++-- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/operaton/fitpub/security/HttpSignatureValidator.java b/src/main/java/org/operaton/fitpub/security/HttpSignatureValidator.java index 545fa7b..577c139 100644 --- a/src/main/java/org/operaton/fitpub/security/HttpSignatureValidator.java +++ b/src/main/java/org/operaton/fitpub/security/HttpSignatureValidator.java @@ -197,6 +197,23 @@ public class HttpSignatureValidator { return Base64.getEncoder().encodeToString(signature); } + /** + * Container for HTTP signature headers. + */ + public static class SignatureHeaders { + public final String host; + public final String date; + public final String digest; + public final String signature; + + public SignatureHeaders(String host, String date, String digest, String signature) { + this.host = host; + this.date = date; + this.digest = digest; + this.signature = signature; + } + } + /** * Signs an outbound HTTP request for ActivityPub federation. * @@ -205,9 +222,9 @@ public class HttpSignatureValidator { * @param body the request body * @param privateKeyPem the sender's private key * @param keyId the public key ID - * @return the Signature header value + * @return SignatureHeaders containing all headers needed for the signed request */ - public String signRequest(String method, String targetUrl, String body, String privateKeyPem, String keyId) { + public SignatureHeaders signRequest(String method, String targetUrl, String body, String privateKeyPem, String keyId) { try { java.net.URI uri = new java.net.URI(targetUrl); String host = uri.getHost(); @@ -239,11 +256,13 @@ public class HttpSignatureValidator { String signatureBase64 = sign(signingString, privateKeyPem); // Build signature header - return String.format( + String signatureHeader = String.format( "keyId=\"%s\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"%s\"", keyId, signatureBase64 ); + return new SignatureHeaders(host, date, digestValue, signatureHeader); + } catch (Exception e) { log.error("Failed to sign request", e); throw new RuntimeException("Failed to sign request", e); diff --git a/src/main/java/org/operaton/fitpub/service/FederationService.java b/src/main/java/org/operaton/fitpub/service/FederationService.java index b1945e4..54510ea 100644 --- a/src/main/java/org/operaton/fitpub/service/FederationService.java +++ b/src/main/java/org/operaton/fitpub/service/FederationService.java @@ -166,19 +166,24 @@ public class FederationService { try { String activityJson = objectMapper.writeValueAsString(activity); - HttpHeaders headers = new HttpHeaders(); - headers.set("Content-Type", "application/activity+json"); - headers.set("Accept", "application/activity+json"); - - // Add HTTP signature - String signature = signatureValidator.signRequest( + // Generate HTTP signature with all required headers + HttpSignatureValidator.SignatureHeaders signatureHeaders = signatureValidator.signRequest( HttpMethod.POST.name(), inboxUrl, activityJson, sender.getPrivateKey(), baseUrl + "/users/" + sender.getUsername() + "#main-key" ); - headers.set("Signature", signature); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/activity+json"); + headers.set("Accept", "application/activity+json"); + + // Add all signature-related headers + headers.set("Host", signatureHeaders.host); + headers.set("Date", signatureHeaders.date); + headers.set("Digest", signatureHeaders.digest); + headers.set("Signature", signatureHeaders.signature); HttpEntity entity = new HttpEntity<>(activityJson, headers); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index a9866f1..77d82bf 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -2,8 +2,11 @@ # Activated with: mvn spring-boot:run -Dspring-boot.run.profiles=dev spring: - # Development datasource is handled by Testcontainers (see TestcontainersConfiguration) - # No need to configure datasource here - it's automatically configured + datasource: + url: jdbc:postgresql://localhost:5432/fitpub + username: fitpub + password: change_me_in_production + driver-class-name: org.postgresql.Driver jpa: hibernate: