diff --git a/changelog.d/12774.misc b/changelog.d/12774.misc
new file mode 100644
index 0000000000000000000000000000000000000000..8651f2e0e0624cb9568954c9b88d1f83a23be063
--- /dev/null
+++ b/changelog.d/12774.misc
@@ -0,0 +1 @@
+Make handling of federation Authorization header (more) compliant with RFC7230.
diff --git a/synapse/federation/transport/server/_base.py b/synapse/federation/transport/server/_base.py
index 103861644a706944c6d222dc98b205759984183d..84100a5a5257326b6239e965580401e9abbe454a 100644
--- a/synapse/federation/transport/server/_base.py
+++ b/synapse/federation/transport/server/_base.py
@@ -169,14 +169,16 @@ def _parse_auth_header(header_bytes: bytes) -> Tuple[str, str, str, Optional[str
     """
     try:
         header_str = header_bytes.decode("utf-8")
-        params = header_str.split(" ")[1].split(",")
+        params = re.split(" +", header_str)[1].split(",")
         param_dict: Dict[str, str] = {
-            k: v for k, v in [param.split("=", maxsplit=1) for param in params]
+            k.lower(): v for k, v in [param.split("=", maxsplit=1) for param in params]
         }
 
         def strip_quotes(value: str) -> str:
             if value.startswith('"'):
-                return value[1:-1]
+                return re.sub(
+                    "\\\\(.)", lambda matchobj: matchobj.group(1), value[1:-1]
+                )
             else:
                 return value
 
diff --git a/synapse/http/matrixfederationclient.py b/synapse/http/matrixfederationclient.py
index 725b5c33b8c52fe150673f52cbe937df7bc0495c..0b9475debdb15469d8d89dc55553665c62660661 100644
--- a/synapse/http/matrixfederationclient.py
+++ b/synapse/http/matrixfederationclient.py
@@ -747,7 +747,7 @@ class MatrixFederationHttpClient:
         for key, sig in request["signatures"][self.server_name].items():
             auth_headers.append(
                 (
-                    'X-Matrix origin=%s,key="%s",sig="%s",destination="%s"'
+                    'X-Matrix origin="%s",key="%s",sig="%s",destination="%s"'
                     % (
                         self.server_name,
                         key,
diff --git a/tests/federation/transport/server/test__base.py b/tests/federation/transport/server/test__base.py
index ac3695a8ccab505aa75af30cb47db6c9bc2bb84f..e63885c1c9d8e5dc4d3fdc824c2ca01af930d136 100644
--- a/tests/federation/transport/server/test__base.py
+++ b/tests/federation/transport/server/test__base.py
@@ -17,7 +17,7 @@ from typing import Dict, List, Tuple
 
 from synapse.api.errors import Codes
 from synapse.federation.transport.server import BaseFederationServlet
-from synapse.federation.transport.server._base import Authenticator
+from synapse.federation.transport.server._base import Authenticator, _parse_auth_header
 from synapse.http.server import JsonResource, cancellable
 from synapse.server import HomeServer
 from synapse.types import JsonDict
@@ -112,3 +112,30 @@ class BaseFederationServletCancellationTests(
             expect_cancellation=False,
             expected_body={"result": True},
         )
+
+
+class BaseFederationAuthorizationTests(unittest.TestCase):
+    def test_authorization_header(self) -> None:
+        """Tests that the Authorization header is parsed correctly."""
+
+        # test a "normal" Authorization header
+        self.assertEqual(
+            _parse_auth_header(
+                b'X-Matrix origin=foo,key="ed25519:1",sig="sig",destination="bar"'
+            ),
+            ("foo", "ed25519:1", "sig", "bar"),
+        )
+        # test an Authorization with extra spaces, upper-case names, and escaped
+        # characters
+        self.assertEqual(
+            _parse_auth_header(
+                b'X-Matrix  ORIGIN=foo,KEY="ed25\\519:1",SIG="sig",destination="bar"'
+            ),
+            ("foo", "ed25519:1", "sig", "bar"),
+        )
+        self.assertEqual(
+            _parse_auth_header(
+                b'X-Matrix origin=foo,key="ed25519:1",sig="sig",destination="bar",extra_field=ignored'
+            ),
+            ("foo", "ed25519:1", "sig", "bar"),
+        )