In TLS 1.3, what must a client advertise before a server may request a certificate after the handshake has finished?
answer
- consent is given up front
- advertised in the ClientHello
- the context pairs answer with request
- not a second handshake
- post_handshake_auth(49) is the extension
basics
~10 sThe post_handshake_auth(49) extension in its ClientHello. Without it the server must not send a late CertificateRequest, and a client that receives one anyway aborts the connection with a fatal alert.
solid answer
~40 sThe client must have sent the `post_handshake_auth(49)` extension in its `ClientHello`, stating in advance that it is willing to be challenged later. The server may then send a `CertificateRequest` at any point after the handshake, carrying a non-empty `certificate_request_context`; the client answers with `Certificate`, `CertificateVerify` and `Finished` echoing that same context, which is what allows several challenges to be outstanding and matched to their answers. A client that never advertised the extension and receives a late request aborts with a fatal alert. This is not renegotiation: TLS 1.3 removed renegotiation entirely, so the TLS 1.2 habit of renegotiating mid-connection to ask for a certificate has no direct equivalent.
code
pseudocode · 15 lines// at connection setup
ClientHello {
extensions: post_handshake_auth(49) // client consents to being asked later
}
// ... handshake completes, application data flows ...
// minutes later, over the same connection
server -> client: CertificateRequest { certificate_request_context: 0x7A2B }
client -> server: Certificate { certificate_request_context: 0x7A2B,
certificate_list: [leaf, intermediates] }
client -> server: CertificateVerify // signs the transcript, as in the handshake
client -> server: Finished
// a client that never sent post_handshake_auth(49):
// on CertificateRequest -> fatal alert, connection closedgo deeper
Know the headline: a TLS 1.3 server can ask for a client certificate after the handshake, but only if the client said up front that it was willing to be asked.
Explain the exchange: post_handshake_auth(49) in the ClientHello, a later CertificateRequest with a non-empty context, and an answer echoing that context so requests and replies pair up.
Show where it earns its place and where it does not. A long-lived dedicated link can be challenged when a privileged command arrives; a connection multiplexing concurrent exchanges cannot attribute the challenge to one of them.
Judge whether late authentication belongs at the transport layer at all. Making identity a property of the connection rather than of an operation constrains how work is multiplexed, and that constraint outlives the feature.
## The opt-in comes first Post-handshake authentication is the mechanism for asking a peer to authenticate after the connection is already carrying application data. The asking is not unilateral. The client must have included `post_handshake_auth(49)` in its `ClientHello`, which is a statement of willingness made before anything else happened. A server that receives no such extension must not send a late `CertificateRequest`, and a client that never sent it and receives one anyway treats it as a protocol violation and aborts the connection with a fatal alert. This ordering is deliberate. It means a client always knows, from the moment it opens the connection, whether it can be interrupted later, and no implementation has to handle a surprise request it was never built for. ## The exchange 1. The client sends `post_handshake_auth(49)` in its `ClientHello`, at connection setup. 2. The handshake completes normally, and application data flows. 3. At some later point the server sends `CertificateRequest` with a **non-empty** `certificate_request_context`. 4. The client replies with `Certificate` carrying that same context, then `CertificateVerify`, then `Finished`. The context is what makes the exchange workable. Several requests can be outstanding at once, and each answer names the request it belongs to, so the server never has to guess which challenge a reply satisfies. In the main handshake the context is empty, because there is only one request and no ambiguity to resolve. Everything else follows the rules of the ordinary case: the client that has nothing acceptable sends an empty `certificate_list`, and the `CertificateVerify` signature covers the transcript, so the proof is bound to this connection and not reusable elsewhere. ## Why it is not renegotiation TLS 1.2 achieved the same effect by renegotiating: running a second handshake inside the established connection, this time asking for a certificate. **TLS 1.3 removed renegotiation entirely.** There is no second handshake to run, and the key-refresh job that renegotiation also served is handled by `KeyUpdate` instead. So post-handshake authentication is not renegotiation under a new name. The differences are structural: - it is a few messages inside the existing connection, not a fresh handshake; - it requires prior consent from the client, which renegotiation did not; - it changes nothing about the negotiated parameters, only the peer's authenticated state; - it can be requested repeatedly, each request distinguished by its own context. ## Where it fits poorly The mechanism has a real limitation worth naming, because it is the reason many deployments never use it. Post-handshake authentication operates on the **connection**. On a protocol that multiplexes many concurrent exchanges over one connection, nothing ties the challenge to whichever exchange provoked it, and nothing stops other exchanges continuing while the answer is in flight. A service that wanted to say *this particular operation needs a stronger identity* cannot express that; it can only say *this connection should now be authenticated*. On a crane control link the fit is better, because the connection is long-lived, dedicated and carries one stream of control traffic. A plausible use is a link that comes up for telemetry with no client certificate and is challenged only when a command that moves equipment arrives, so the strong identity is demanded at the moment it matters rather than kept open all day. ## What to check when it does not work | symptom | most likely cause | |---|---| | the client aborts as soon as the late request arrives | the client never sent `post_handshake_auth(49)` | | the server never sends a late request at all | the extension was not offered, so the server is barred from asking | | an answer arrives and the server cannot pair it | the request context was empty or was not echoed | | the answer carries an empty `certificate_list` | the client has nothing matching the request's constraints | The compact summary: the client consents at `ClientHello` time, the server challenges later with a context, the answer echoes the context, and none of it is renegotiation, because renegotiation no longer exists.
- Why must the certificate_request_context be non-empty for a post-handshake request?Because more than one challenge can be outstanding. The context is echoed in the client's `Certificate` message, so each answer names the request it belongs to. In the main handshake there is exactly one request and no pairing problem, which is why the context is empty there.
- Does post-handshake authentication change the connection's keys or negotiated parameters?No. It adds messages inside the established connection and changes only what the server knows about the peer's identity. Refreshing traffic keys is a separate mechanism, `KeyUpdate`, and version, group and cipher were all settled in the original handshake and are not revisited.
- Why is the mechanism awkward on a connection that multiplexes concurrent exchanges?Because it authenticates the connection, not an exchange. Nothing links the challenge to whichever request triggered it, and other exchanges keep running while the answer is in flight, so a service cannot use it to demand a stronger identity for one specific operation.
saying these in an interview costs you the question
- Calls post-handshake authentication a renegotiation
- Thinks a TLS 1.3 server may challenge any client at any time
- Says the context may be left empty for a post-handshake request
- Believes the mechanism renegotiates the cipher or the version
- Assumes TLS 1.2 has the same mechanism under another name