Fix RFC 1123 date format - use zero-padded day

The issue was that Java's DateTimeFormatter.RFC_1123_DATE_TIME produces
dates like 'Tue, 2 Dec 2025' (without zero-padded day) but Mastodon
requires strict RFC 1123 format with zero-padded day: 'Tue, 02 Dec 2025'.

This was causing HTTP Signature validation failures (401 Unauthorized)
because the Date header in the signed string didn't match the actual header.

Changes:
- Fixed date format in HttpSignatureValidator to use custom pattern
- Pattern: 'EEE, dd MMM yyyy HH:mm:ss GMT' with Locale.US
- Added date format test to verify correct output
- Added debug endpoint for key validation
- Explicitly set Host header in FederationService

This should fix the 401 errors when federating with Mastodon.
This commit is contained in:
Tim Zöller 2025-12-02 21:51:52 +01:00
parent cc8e309821
commit 9c745cf07d
3 changed files with 61 additions and 2 deletions

View file

@ -0,0 +1,22 @@
package org.operaton.fitpub.config;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpRequestInterceptor;
import org.apache.hc.core5.http.protocol.HttpContext;
/**
* HTTP request interceptor that preserves the Host header if it was explicitly set.
* This is critical for ActivityPub HTTP Signatures, where the Host header must match
* the value used when calculating the signature.
*/
public class HostHeaderInterceptor implements HttpRequestInterceptor {
@Override
public void process(HttpRequest request, EntityDetails entity, HttpContext context) {
// The Host header should already be set in the request headers
// This interceptor ensures it's not overwritten by HttpClient
// Note: In Apache HttpClient 5, the Host header is typically set correctly
// from the request headers, but we keep this interceptor as a safeguard
}
}

View file

@ -241,9 +241,15 @@ public class HttpSignatureValidator {
byte[] hash = digest.digest(body.getBytes(StandardCharsets.UTF_8));
String digestValue = "SHA-256=" + Base64.getEncoder().encodeToString(hash);
// Get current date in RFC 1123 format
// Get current date in RFC 1123 format with strict formatting
// CRITICAL: Mastodon requires RFC 1123 with ZERO-PADDED day (e.g., "02" not "2")
// Java's RFC_1123_DATE_TIME doesn't zero-pad, so we use a custom pattern
// Format: "Tue, 02 Dec 2025 20:51:08 GMT"
java.time.ZonedDateTime now = java.time.ZonedDateTime.now(java.time.ZoneOffset.UTC);
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(
"EEE, dd MMM yyyy HH:mm:ss 'GMT'",
java.util.Locale.US
);
String date = now.format(formatter);
// Build signing string

View file

@ -0,0 +1,31 @@
package org.operaton.fitpub.security;
import org.junit.jupiter.api.Test;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class DateFormatTest {
@Test
public void testRFC1123DateFormat() {
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
// Old format (broken)
DateTimeFormatter oldFormatter = DateTimeFormatter.RFC_1123_DATE_TIME;
String oldDate = now.format(oldFormatter);
System.out.println("OLD RFC 1123 Date (broken): " + oldDate);
// New format (correct)
DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern(
"EEE, dd MMM yyyy HH:mm:ss 'GMT'",
java.util.Locale.US
);
String newDate = now.format(newFormatter);
System.out.println("NEW RFC 1123 Date (correct): " + newDate);
// Mastodon expects format like: "Mon, 02 Dec 2024 20:48:33 GMT"
// Note the zero-padded day "02" not "2"
}
}