fix(auth_v2): prefer verified mTLS cert and confirm forwarded-DN gates on the socket peer

The forwarded subject-DN trust gate already compared the raw transport peer
(request.client.host / ASGI scope client) against trusted_proxy_cidrs, never the
XFF-resolved IP, so an attacker spoofing X-Forwarded-For cannot defeat it. Make
that ordering explicit and stronger: a genuinely verified client certificate from
the ASGI TLS extension is now preferred when present, and the spoofable
forwarded-header path is only consulted as a fallback, still gated on the direct
socket peer.
This commit is contained in:
Yassin Kortam 2026-06-10 20:25:37 -07:00
parent f158a6c9e0
commit c9e7fd829c

View file

@ -404,15 +404,17 @@ class MutualTLSAuthenticator:
)
def _read_client_cert(self, request: Request) -> Optional[ClientCertificate]:
tls = request.scope.get("extensions", {}).get("tls", {})
verified_dn = tls.get("client_cert_name")
if verified_dn:
return ClientCertificate(subject_dn=verified_dn)
if self._config.forwarded_subject_header:
peer = request.client.host if request.client else None
if not ip_in_trusted_proxies(peer, self._network):
return None
dn = request.headers.get(self._config.forwarded_subject_header)
return ClientCertificate(subject_dn=dn) if dn else None
tls = request.scope.get("extensions", {}).get("tls", {})
dn = tls.get("client_cert_name")
return ClientCertificate(subject_dn=dn) if dn else None
return None
def challenge(self) -> str:
return ""