RFC 9440
Client-Cert HTTP Header Field
RFC 9440: Client-Cert HTTP Header Field π
Okay bestie, first the paperwork π This is RFC 9440, titled "Client-Cert HTTP Header Field," and it's dated July 2023 πΈ It's an Informational doc, not a standard, and its ISSN is 2070-1721. The authors are B. Campbell from Ping Identity and M. Bishop, Ed. from Akamai (that "Ed." means editor, so M. Bishop did the heavy lifting π ). The title block doesn't list any RFCs it obsoletes or updates, so it's a fresh, standalone thing β¨
Abstract
This doc describes HTTP extension header fields that let a TLS terminating reverse proxy (TTRP) pass the client certificate info from a mutually authenticated TLS connection along to the origin server, in a common and predictable way π¦
Status of This Memo
Real talk, this is not an Internet Standards Track spec. It's published just for information π§
It's a product of the Internet Engineering Task Force (IETF), so it reflects what the IETF community agreed on π«Ά It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). Not every IESG-approved doc is up for any level of Internet Standard, though. Check Section 2 of RFC 7841 if you want the deets π€
For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc9440 π
Copyright Notice
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved. π
This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. Please read those carefully, because they spell out what you can and can't do with this doc π Any code components you pull out of it have to include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, same as the Revised BSD License says π
Table of Contents
1. Introduction
1.1. Requirements Notation and Conventions
1.2. Terminology and Applicability
2. HTTP Header Fields and Processing Rules
2.1. Encoding
2.2. Client-Cert HTTP Header Field
2.3. Client-Cert-Chain HTTP Header Field
2.4. Processing Rules
3. Deployment Considerations
3.1. Header Field Compression
3.2. Message Header Size
3.3. TLS Session Resumption
4. Security Considerations
5. IANA Considerations
5.1. HTTP Field Name Registrations
6. References
6.1. Normative References
6.2. Informative References
Appendix A. Example
Appendix B. Select Design Considerations
B.1. Field Injection
B.2. The Forwarded HTTP Extension
B.3. The Whole Certificate and Certificate Chain
Acknowledgements
Authors' Addresses
1. Introduction β¨
Okay so a super common way people deploy HTTPS apps is to put the origin HTTP application servers behind a reverse proxy that ends the TLS connections from clients π The proxy faces the Internet and sends each client request to the right origin server inside a private or protected network. Clients can't reach the origin servers directly, so they only ever talk to the proxy π Clients usually can't see the backend details either. They just see responses as if they came straight from the proxy. HTTPS is usually used between the proxy and the origin too, but the TLS connection the client sets up is only between the client and the reverse proxy π
This pattern shows up in a bunch of flavors: n-tier architectures, content delivery networks, application load-balancing services, and ingress controllers π
TLS client certificate authentication isn't super widespread, but when it's used, the origin server often needs info about the client certificate for its app logic π That logic could be access control decisions, audit logging, or binding issued tokens or cookies to a certificate (including validating those bindings). Which details of the certificate matter depends on the app. For all this to work in practice, the reverse proxy has to pass info about the client certificate on to the origin app server π Right now, a common hack is to stuff the certificate (in some encoding) or pieces of it into non-standard fields in the HTTP request sent to the origin. It works, but interop between independently built components can be a total nightmare, or even impossible, depending on choices like field names, which parts of the certificate get exposed, or how the certificate is encoded π A well-known, predictable approach for this super common job could make interop way easier between independent implementations π
This doc's goal is to write down existing practice and pin down the specific details, so things interoperate better with less fuss π¦ It defines two HTTP header fields, "Client-Cert" and "Client-Cert-Chain," that a TLS terminating reverse proxy (TTRP) adds to requests sent to the backend origin servers. The Client-Cert value holds the end-entity client certificate from the mutually authenticated TLS connection between the originating client and the TTRP. Optionally, the Client-Cert-Chain value holds the certificate chain used to validate that end-entity certificate. That way the backend origin server can use the client certificate info in its app logic β¨ There might be extra proxies or hops between the TTRP and the origin (even with mutually authenticated TLS between them), but the Client-Cert field is intentionally limited to one job: showing the origin the certificate the originating client presented to the TTRP π§
1.1. Requirements Notation and Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here π
1.2. Terminology and Applicability
This doc borrows some syntax and parsing terms from Section 3 of [STRUCTURED-FIELDS]: List and Byte Sequence π§©
When the doc says things like "TLS client certificate authentication" or "mutually authenticated TLS," it means this: on top of the usual TLS server authentication with a certificate, the client presents its X.509 certificate [RFC5280] and proves it has the matching private key to the server, either when the TLS connection is being negotiated or when it's resumed π In modern TLS [TLS] [TLS1.2], mutual auth means the client sends the Certificate and CertificateVerify messages during the handshake, and the server verifies the CertificateVerify and Finished messages π
HTTP/2 limits TLS 1.2 renegotiation (Section 9.2.1 of [HTTP/2]) and bans TLS 1.3 post-handshake authentication (Section 9.2.3 of [HTTP/2]). Even so, people sometimes use them to do reactive client certificate auth in HTTP/1.1 [HTTP/1.1], where the server decides whether to ask for a client certificate based on the HTTP request π€ HTTP application data sent on that connection after the client certificate is received and verified is also mutually authenticated, so the mechanisms in this doc apply to it too β With post-handshake authentication, there's also a small chance (not likely in practice) of multiple certificates and certificate chains from the client on one connection. In that case, only the certificate and chain from the last post-handshake authentication get used for the header fields in this doc π
2. HTTP Header Fields and Processing Rules π
This doc defines the headers below, which are explained further in Sections 2.2 and 2.3 respectively. They carry the client certificate info of a mutually authenticated TLS connection, going from the reverse proxy to the origin server π
Client-Cert: The end-entity certificate the client used in the TLS handshake with the reverse proxy.Client-Cert-Chain: The certificate chain used to validate the end-entity certificate the client gave during the TLS handshake with the reverse proxy.
2.1. Encoding
The headers in this doc encode certificates as Byte Sequences (Section 3.3.5 of [STRUCTURED-FIELDS]). The binary data is a DER-encoded [ITU.X690] X.509 certificate [RFC5280]. Basically, the binary DER cert gets base64-encoded (no line breaks, spaces, or any other characters outside the base64 alphabet) and wrapped in colons on both ends πΈ
Heads up, certificates often live in a text format, like the one described in Section 5.1 of [RFC7468], which is already almost a Byte Sequence π If your certs look like that, you just need to swap ---(BEGIN|END) CERTIFICATE--- for : and remove the line breaks to get a valid item β¨
2.2. Client-Cert HTTP Header Field π
In a TLS terminating reverse proxy setup, the proxy makes the TLS client certificate available to the backend app through the Client-Cert HTTP header field π¦ This field holds the end-entity certificate the client used in the TLS handshake.
Client-Cert is a Byte Sequence, with the header value encoded the way Section 2.1 describes π§
The Client-Cert header field is only for HTTP requests and it MUST NOT be used in HTTP responses. It's a singleton header field as defined in Section 5.5 of [HTTP], which MUST NOT have a list of values or occur multiple times in a request. Lowkey strict, but that's how it has to be π₯
Figure 2 in Appendix A has an example of the Client-Cert header field π
To be continued in part 2 π«Ά
2.3. Client-Cert-Chain HTTP Header Field β¨
Okay so picture this: a TLS terminating reverse proxy (TTRP) sits in front of the backend app π
. In that setup, the proxy MAY pass the certificate chain along to the app using the Client-Cert-Chain header field π¦.
Client-Cert-Chain is a List (Section 3.1 of [STRUCTURED-FIELDS]) π. Each item in the List MUST be a Byte Sequence encoded as described in Section 2.1. The order matches the ordering in TLS (as described in Section 4.4.2 of [TLS]) π.
Client-Cert-Chain MUST NOT appear unless Client-Cert is also present π. It also doesn't include the end-entity certificate, because that one's already sitting in Client-Cert. The root certificate MAY be omitted from Client-Cert-Chain, provided that the target origin server is known to possess the omitted trust anchor πΈ.
The Client-Cert-Chain header field is only for HTTP requests and MUST NOT be used in HTTP responses π. It MAY have a list of values or occur multiple times in a request. For header compression purposes, it might be advantageous to split lists into multiple instances π§.
Figure 3 in Appendix A has an example of the Client-Cert-Chain header field π.
2.4. Processing Rules π
Okay this part is the rulebook for a TTRP that has negotiated a mutually authenticated TLS connection, so it can pass the client certificate from that connection along to the backend origin servers π₯. This is a configuration or deployment option, so the rules here only apply to servers that have that option turned on π«Ά.
The TTRP negotiates a mutually authenticated TLS connection with the client, like the ones described in [TLS] or [TLS1.2] β¨. It then validates the client certificate against its own policy and trusted certificate authorities. Every HTTP request on that underlying TLS connection gets dispatched to the origin server with these changes:
- The client certificate goes in the Client-Cert header field of the dispatched request, as described in Section 2.2.
- If it's configured to do so, the validation chain of the client certificate goes in the Client-Cert-Chain header field of the request, as described in Section 2.3.
- Any Client-Cert or Client-Cert-Chain header fields in the original incoming request MUST be removed or overwritten before the request is forwarded π ββοΈ. An incoming request that has a Client-Cert or Client-Cert-Chain header field MAY be rejected with an HTTP 400 response.
Requests to the TTRP made over a TLS connection where client certificate authentication wasn't negotiated MUST be sanitized by removing any and all occurrences of the Client-Cert and Client-Cert-Chain header fields before the request goes to the backend server π§Ό.
Backend origin servers can then look at the Client-Cert header field of the request to figure out whether the connection from the client to the TTRP was mutually authenticated and, if so, which certificate the client presented π΅οΈββοΈ. Access control decisions based on the client certificate (or the lack of one) can be expressed by picking response content accordingly, or with an HTTP 403 response if the certificate is deemed unacceptable for the given context π«. Heads up though: TLS clients that rely on error indications at the TLS layer for an unacceptable certificate won't get those signals π.
When the Client-Cert request header field is used to select a response (for example, the response content is access-controlled), the response MUST either be uncacheable (for example, by sending Cache-Control: no-store) or be designated for selective reuse only for later requests with the same Client-Cert header field value, by sending a "Vary: Client-Cert" response header π. If a TTRP runs into a response with Client-Cert or Client-Cert-Chain in the Vary header field (Section 12.5.5 of [HTTP]), it SHOULD stop the user agent from caching the response by changing the value of the Vary response header field to "*" π
ββοΈ.
Forward proxies and other intermediaries MUST NOT add the Client-Cert or Client-Cert-Chain header fields to requests, or modify an existing Client-Cert or Client-Cert-Chain header field π·. Clients MUST NOT use the Client-Cert or Client-Cert-Chain header field in requests either π ββοΈ.
3. Deployment Considerations π
3.1. Header Field Compression ποΈ
If the connection between the TTRP and origin can do field compression (for example, HPACK [HPACK] or QPACK [QPACK]), and the TTRP multiplexes more than one client's requests into that connection, then the size and variation of Client-Cert and Client-Cert-Chain field values can seriously hurt compression efficiency π. An origin could make up for the lost efficiency by increasing the size of the dynamic table π. If the TTRP decides the origin's dynamic table isn't big enough, it may find it beneficial to always send the field value as a literal instead of putting it into the table π¦.
3.2. Message Header Size π
A server that receives a message header bigger than it's willing to handle can send an HTTP 431 (Request Header Fields Too Large) status code, per Section 5 of [RFC6585] πββοΈ. Because certificate data makes field values pretty big, recipients may need to be configured to allow a larger maximum header size π. An intermediary that generates client certificate header fields on connections that allow advertising the maximum acceptable header size (for example, HTTP/2 [HTTP/2] or HTTP/3 [HTTP/3]) should account for the extra header size of the requests it sends, compared to the requests it receives. It can do that by advertising a value to its clients that's sufficiently smaller, leaving room for the certificate data π§ .
3.3. TLS Session Resumption π
Some TLS implementations don't keep client certificate information when resuming π« . Giving inconsistent values of Client-Cert and Client-Cert-Chain when resuming might lead to errors, so implementations that can't provide these values SHOULD either disable resumption for connections with client certificates, or initially leave out a Client-Cert or Client-Cert-Chain field if it might not be available after resuming π .
4. Security Considerations π
Okay, this section is serious, bestie π€. The header fields described here let a TTRP and a backend or origin server work together as though, from the client's point of view, they're one logical server-side deployment of HTTPS over a mutually authenticated TLS connection π€. But using the header fields outside that intended use case may undermine the protections that TLS client certificate authentication gives you π. So steps like the ones below need to be taken to prevent unintended use, both when sending the header field and when relying on its value π¨.
Producing and consuming the Client-Cert and Client-Cert-Chain header fields SHOULD be configurable options, respectively, in a TTRP and a backend server (or in an individual application in that server). The default configuration for both should be to not use the header fields, so people have to "opt-in" to the functionality πββοΈ.
To prevent field injection, backend servers MUST only accept the Client-Cert and Client-Cert-Chain header fields from a trusted TTRP (or another proxy in a trusted path from the TTRP) π‘οΈ. A TTRP MUST sanitize the incoming request before forwarding it on, by removing or overwriting any existing instances of the fields π§Ή. Otherwise, arbitrary clients can control the field values that the backend server sees and uses π±. It's really important to know that skipping field injection protection doesn't "fail safe" π. The nominal functionality will still work exactly as expected even when malicious actions are possible, so you have to be extra careful about making sure proper field sanitation is in place π«‘.
The communication between a TTRP and a backend server needs to be secured against eavesdropping and modification by unintended parties π.
The configuration options and request sanitization are necessary functionalities of the respective servers π§©. The other requirements can be met in a number of ways, depending on the deployment π. For example, the communication between a TTRP and a backend or origin server might be authenticated in some way, with the Client-Cert and Client-Cert-Chain header fields inserted and consumed only on that connection. Appendix B.3 of [HTTPSIG] gives one example of this using HTTP Message Signatures βοΈ. Alternatively, the network topology might dictate a private network, so the backend application can only accept requests from the TTRP and the proxy can only make requests to that server π°. Other deployments that meet the requirements set forth here are also possible β¨.
5. IANA Considerations π
5.1. HTTP Field Name Registrations π·οΈ
IANA has registered the following entries in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" defined by "HTTP Semantics" [HTTP] π:
+===================+===========+=====================+
| Field Name | Status | Reference |
+===================+===========+=====================+
| Client-Cert | permanent | RFC 9440, Section 2 |
+-------------------+-----------+---------------------+
| Client-Cert-Chain | permanent | RFC 9440, Section 2 |
+-------------------+-----------+---------------------+
Table 1: Hypertext Transfer Protocol (HTTP) Field
Name Registry
6. References π
6.1. Normative References π§Ύ
[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Semantics", STD 97, RFC 9110,
DOI 10.17487/RFC9110, June 2022,
<https://www.rfc-editor.org/info/rfc9110>.
[ITU.X690] ITU-T, "Information technology - ASN.1 encoding rules:
Specification of Basic Encoding Rules (BER), Canonical
Encoding Rules (CER) and Distinguished Encoding Rules
(DER)", ITU-T Recommendation X.690, February 2021,
<https://www.itu.int/rec/T-REC-X.690/en>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
Housley, R., and W. Polk, "Internet X.509 Public Key
Infrastructure Certificate and Certificate Revocation List
(CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
<https://www.rfc-editor.org/info/rfc5280>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[STRUCTURED-FIELDS]
Nottingham, M. and P-H. Kamp, "Structured Field Values for
HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021,
<https://www.rfc-editor.org/info/rfc8941>.
6.2. Informative References π
[HPACK] Peon, R. and H. Ruellan, "HPACK: Header Compression for HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015, <https://www.rfc-editor.org/info/rfc7541>.
[HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.
[HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, DOI 10.17487/RFC9113, June 2022, <https://www.rfc-editor.org/info/rfc9113>.
[HTTP/3] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, June 2022, <https://www.rfc-editor.org/info/rfc9114>.
[HTTPSIG] Backman, A., Ed., Richer, J., Ed., and M. Sporny, "HTTP Message Signatures", Work in Progress, Internet-Draft, draft-ietf-httpbis-message-signatures-17, 2 May 2023, <https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-17>.
[QPACK] Krasic, C., Bishop, M., and A. Frindell, Ed., "QPACK: Field Compression for HTTP/3", RFC 9204, DOI 10.17487/RFC9204, June 2022, <https://www.rfc-editor.org/info/rfc9204>.
[RFC6585] Nottingham, M. and R. Fielding, "Additional HTTP Status Codes", RFC 6585, DOI 10.17487/RFC6585, April 2012, <https://www.rfc-editor.org/info/rfc6585>.
[RFC7239] Petersson, A. and M. Nilsson, "Forwarded HTTP Extension", RFC 7239, DOI 10.17487/RFC7239, June 2014, <https://www.rfc-editor.org/info/rfc7239>.
[RFC7468] Josefsson, S. and S. Leonard, "Textual Encodings of PKIX, PKCS, and CMS Structures", RFC 7468, DOI 10.17487/RFC7468, April 2015, <https://www.rfc-editor.org/info/rfc7468>.
[RFC8705] Campbell, B., Bradley, J., Sakimura, N., and T. Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", RFC 8705, DOI 10.17487/RFC8705, February 2020, <https://www.rfc-editor.org/info/rfc8705>.
[TLS] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.
[TLS1.2] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008, <https://www.rfc-editor.org/info/rfc5246>.
Appendix A. Example π§Ύ
Okay so picture this π: a TLS client presents the client and intermediate certificates from Figure 1 while setting up a mutually authenticated TLS connection with the TTRP. In that hypothetical, the proxy sends the Client-Cert field shown in Figure 2 to the backend. Heads up that the line breaks and extra spaces in the field value in Figures 2 and 3 are just there for display and formatting. They aren't part of the value π
-----BEGIN CERTIFICATE-----
MIIBqDCCAU6gAwIBAgIBBzAKBggqhkjOPQQDAjA6MRswGQYDVQQKDBJMZXQncyBB
dXRoZW50aWNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBDQTAeFw0yMDAx
MTQyMjU1MzNaFw0yMTAxMjMyMjU1MzNaMA0xCzAJBgNVBAMMAkJDMFkwEwYHKoZI
zj0CAQYIKoZIzj0DAQcDQgAE8YnXXfaUgmnMtOXU/IncWalRhebrXmckC8vdgJ1p
5Be5F/3YC8OthxM4+k1M6aEAEFcGzkJiNy6J84y7uzo9M6NyMHAwCQYDVR0TBAIw
ADAfBgNVHSMEGDAWgBRm3WjLa38lbEYCuiCPct0ZaSED2DAOBgNVHQ8BAf8EBAMC
BsAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0RAQH/BBMwEYEPYmRjQGV4YW1w
bGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIBHda/r1vaL6G3VliL4/Di6YK0Q6bMje
SkC3dFCOOB8TAiEAx/kHSB4urmiZ0NX5r5XarmPk0wmuydBVoU4hBVZ1yhk=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB5jCCAYugAwIBAgIBFjAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJVUzEbMBkG
A1UECgwSTGV0J3MgQXV0aGVudGljYXRlMSowKAYDVQQDDCFMZXQncyBBdXRoZW50
aWNhdGUgUm9vdCBBdXRob3JpdHkwHhcNMjAwMTE0MjEzMjMwWhcNMzAwMTExMjEz
MjMwWjA6MRswGQYDVQQKDBJMZXQncyBBdXRoZW50aWNhdGUxGzAZBgNVBAMMEkxB
IEludGVybWVkaWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJf+aA54
RC5pyLAR5yfXVYmNpgd+CGUTDp2KOGhc0gK91zxhHesEYkdXkpS2UN8Kati+yHtW
CV3kkhCngGyv7RqjZjBkMB0GA1UdDgQWBBRm3WjLa38lbEYCuiCPct0ZaSED2DAf
BgNVHSMEGDAWgBTEA2Q6eecKu9g9yb5glbkhhVINGDASBgNVHRMBAf8ECDAGAQH/
AgEAMA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAgNJADBGAiEA5pLvaFwRRkxo
mIAtDIwg9D7gC1xzxBl4r28EzmSO1pcCIQCJUShpSXO9HDIQMUgH69fNDEMHXD3R
RX5gP7kuu2KGMg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICBjCCAaygAwIBAgIJAKS0yiqKtlhoMAoGCCqGSM49BAMCMFYxCzAJBgNVBAYT
AlVTMRswGQYDVQQKDBJMZXQncyBBdXRoZW50aWNhdGUxKjAoBgNVBAMMIUxldCdz
IEF1dGhlbnRpY2F0ZSBSb290IEF1dGhvcml0eTAeFw0yMDAxMTQyMTI1NDVaFw00
MDAxMDkyMTI1NDVaMFYxCzAJBgNVBAYTAlVTMRswGQYDVQQKDBJMZXQncyBBdXRo
ZW50aWNhdGUxKjAoBgNVBAMMIUxldCdzIEF1dGhlbnRpY2F0ZSBSb290IEF1dGhv
cml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFoaHU+Z5bPKmGzlYXtCf+E6
HYj62fORaHDOrt+yyh3H/rTcs7ynFfGn+gyFsrSP3Ez88rajv+U2NfD0o0uZ4Pmj
YzBhMB0GA1UdDgQWBBTEA2Q6eecKu9g9yb5glbkhhVINGDAfBgNVHSMEGDAWgBTE
A2Q6eecKu9g9yb5glbkhhVINGDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
AwIBhjAKBggqhkjOPQQDAgNIADBFAiEAmAeg1ycKHriqHnaD4M/UDBpQRpkmdcRF
YGMg1Qyrkx4CIB4ivz3wQcQkGhcsUZ1SOImd/lq1Q0FLf09rGfLQPWDc
-----END CERTIFICATE-----
Figure 1: Certificate Chain (with Client Certificate First) π
Client-Cert: :MIIBqDCCAU6gAwIBAgIBBzAKBggqhkjOPQQDAjA6MRswGQYDVQQKDBJ
MZXQncyBBdXRoZW50aWNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBDQTAeFw0
yMDAxMTQyMjU1MzNaFw0yMTAxMjMyMjU1MzNaMA0xCzAJBgNVBAMMAkJDMFkwEwYHKoZ
Izj0CAQYIKoZIzj0DAQcDQgAE8YnXXfaUgmnMtOXU/IncWalRhebrXmckC8vdgJ1p5Be
5F/3YC8OthxM4+k1M6aEAEFcGzkJiNy6J84y7uzo9M6NyMHAwCQYDVR0TBAIwADAfBgN
VHSMEGDAWgBRm3WjLa38lbEYCuiCPct0ZaSED2DAOBgNVHQ8BAf8EBAMCBsAwEwYDVR0
lBAwwCgYIKwYBBQUHAwIwHQYDVR0RAQH/BBMwEYEPYmRjQGV4YW1wbGUuY29tMAoGCCq
GSM49BAMCA0gAMEUCIBHda/r1vaL6G3VliL4/Di6YK0Q6bMjeSkC3dFCOOB8TAiEAx/k
HSB4urmiZ0NX5r5XarmPk0wmuydBVoU4hBVZ1yhk=:
Figure 2: Header Field in HTTP Request to Origin Server π¦
If the proxy were also set up to include the certificate chain, it would add the Client-Cert-Chain header field too. Real talk, the example below does show the TTRP inserting the root certificate, but lots of deployments will choose to leave out the trust anchor πΈ
Client-Cert-Chain: :MIIB5jCCAYugAwIBAgIBFjAKBggqhkjOPQQDAjBWMQsw
CQYDVQQGEwJVUzEbMBkGA1UECgwSTGV0J3MgQXV0aGVudGljYXRlMSowKAYDVQQ
DDCFMZXQncyBBdXRoZW50aWNhdGUgUm9vdCBBdXRob3JpdHkwHhcNMjAwMTE0Mj
EzMjMwWhcNMzAwMTExMjEzMjMwWjA6MRswGQYDVQQKDBJMZXQncyBBdXRoZW50a
WNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBDQTBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABJf+aA54RC5pyLAR5yfXVYmNpgd+CGUTDp2KOGhc0gK91zx
hHesEYkdXkpS2UN8Kati+yHtWCV3kkhCngGyv7RqjZjBkMB0GA1UdDgQWBBRm3W
jLa38lbEYCuiCPct0ZaSED2DAfBgNVHSMEGDAWgBTEA2Q6eecKu9g9yb5glbkhh
VINGDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAKBggqhkjO
PQQDAgNJADBGAiEA5pLvaFwRRkxomIAtDIwg9D7gC1xzxBl4r28EzmSO1pcCIQC
JUShpSXO9HDIQMUgH69fNDEMHXD3RRX5gP7kuu2KGMg==:, :MIICBjCCAaygAw
IBAgIJAKS0yiqKtlhoMAoGCCqGSM49BAMCMFYxCzAJBgNVBAYTAlVTMRswGQYDV
QQKDBJMZXQncyBBdXRoZW50aWNhdGUxKjAoBgNVBAMMIUxldCdzIEF1dGhlbnRp
Y2F0ZSBSb290IEF1dGhvcml0eTAeFw0yMDAxMTQyMTI1NDVaFw00MDAxMDkyMTI
1NDVaMFYxCzAJBgNVBAYTAlVTMRswGQYDVQQKDBJMZXQncyBBdXRoZW50aWNhdG
UxKjAoBgNVBAMMIUxldCdzIEF1dGhlbnRpY2F0ZSBSb290IEF1dGhvcml0eTBZM
BMGByqGSM49AgEGCCqGSM49AwEHA0IABFoaHU+Z5bPKmGzlYXtCf+E6HYj62fOR
aHDOrt+yyh3H/rTcs7ynFfGn+gyFsrSP3Ez88rajv+U2NfD0o0uZ4PmjYzBhMB0
GA1UdDgQWBBTEA2Q6eecKu9g9yb5glbkhhVINGDAfBgNVHSMEGDAWgBTEA2Q6ee
cKu9g9yb5glbkhhVINGDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBh
jAKBggqhkjOPQQDAgNIADBFAiEAmAeg1ycKHriqHnaD4M/UDBpQRpkmdcRFYGMg
1Qyrkx4CIB4ivz3wQcQkGhcsUZ1SOImd/lq1Q0FLf09rGfLQPWDc:
Figure 3: Certificate Chain in HTTP Request to Origin Server β¨
Appendix B. Select Design Considerations π
B.1. Field Injection
Big warning, bestie π¨ This doc requires that the TTRP sanitize the incoming request's fields by removing or overwriting any existing Client-Cert and Client-Cert-Chain header fields before it dispatches that request to the backend application. If it doesn't, a client could inject its own values that would look like they came from the TTRP π
Sure, there are loads of other ways to detect and stop field injection, like putting a unique secret value in the field name or value, or using a signature, HMAC, or AEAD. But there's no common, general mechanism for it yet π Client field injection isn't unique to this doc either, so it wouldn't be appropriate for this document to invent a one-off solution just for itself. Since there isn't a generic fix out there, stripping and sanitizing the fields is the de facto way people protect against field injection in practice. It works fine when it's implemented properly, and it's a normative requirement of Section 4 π₯
B.2. The Forwarded HTTP Extension
The Forwarded HTTP header field from [RFC7239] lets proxy components disclose info that would otherwise get lost in the proxying process π¦ The TLS client certificate info this doc cares about could have been sent as an extension parameter on the Forwarded field. But that would have come with some downsides this document really wanted to dodge. The Forwarded syntax can describe a full chain of proxied HTTP requests, whereas the Client-Cert and Client-Cert-Chain header fields here only care about the certificate the originating client presented on its TLS connection to the TTRP. (From that client's point of view, the TTRP looks like the server.) They pass that info along to backend applications. The multi-hop syntax of Forwarded is expressive, but it's also more complicated. That makes processing it more annoying and, more importantly, makes sanitizing its content, which Section 4 requires to prevent field injection, a lot harder and way more error-prone π So this document went with a flatter, more straightforward structure π
B.3. The Whole Certificate and Certificate Chain
Different apps have different needs when it comes to info from the client certificate. Some want the subject and/or issuer distinguished name, subject alternative name(s), serial number, subject public key info, fingerprint, and so on π§ Some apps, like the one described in [RFC8705], use the entire certificate. To make sure it works for those apps too, and to stay broadly useful without cherry-picking certain bits of cert info, this document chose to pass the full, encoded certificate as the value of the Client-Cert field π
Validating the client certificate and chain of the mutually authenticated TLS connection usually happens at the TTRP during the handshake. Since the TTRP handles that validation, the end-entity certificate is often enough for what the origin server needs π For origin server deployments that need the extra info, the separate Client-Cert-Chain field can carry the certificate chain β¨
Okay bestie, we're in the final stretch of RFC 9440 and I'm not gonna lie, these thank-yous are sweet π₯Ήπ«Ά The authors really went out of their way to credit everyone who helped, from the people who just cheered the doc on to the ones who gave real feedback. Lowkey iconic energy from the whole crew β¨
Acknowledgements π
The authors would like to thank the following individuals who have contributed to this document in various ways, ranging from just being generally supportive of bringing forth the document to providing specific feedback or content:
- Evan Anderson
- Annabelle Backman
- Alan Frindell
- Rory Hewitt
- Fredrik Jeansson
- Benjamin Kaduk
- Torsten Lodderstedt
- Kathleen Moriarty
- Mark Nottingham
- Erik Nygren
- Mike Ounsworth
- Lucas Pardue
- Matt Peterson
- Eric Rescorla
- Justin Richer
- Michael Richardson
- Joe Salowey
- Rich Salz
- Mohit Sethi
- Rifaat Shekh-Yusef
- Travis Spencer
- Nick Sullivan
- Willy Tarreau
- Martin Thomson
- Peter Wu
- Hans Zandbelt
Authors' Addresses π
Brian Campbell Ping Identity Email: bcampbell@pingidentity.com
Mike Bishop (editor) π¦ Akamai Email: mbishop@evequefou.be
That's a wrap on RFC 9440!! π Brian and Mike put in the work so the rest of us could actually understand how client certificates get passed through proxies, and that is so slay ππ
π¦ where this page comes from
- ietf: rfc9440 2023-07
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms