Summary
NewSessionTicketgives a client an opaque PSK identity for a future handshake. Acceptance cryptographically connects a new TLS connection to the handshake that issued the ticket; it does not recreate the old transport connection or certify that mutable application state remains current.- Ticket lifetime, age obfuscation, nonce, KDF hash, SNI, PSK mode and binder each answer a bounded protocol question. None alone proves current authorization, same backend, same tenant route, accepted 0-RTT or permission to reuse an earlier application decision.
- Defensible resumption requires a versioned state contract, a bounded ticket-key and service acceptance domain, independent 0-RTT policy, explicit revalidation of mutable authority, observable fallback and an emergency path to retire one ticket-key epoch without disabling unrelated TLS service.
The shortcut that restored too much
The incident began after a regional failover. A client presented a ticket issued six hours earlier. The accepting node decrypted it, found the associated state and completed a resumed TLS 1.3 handshake. The user account encoded by the application around the original connection had since lost a privileged role.
Nothing in the wire transcript said “restore that role.” The ticket proved that the client possessed a PSK tied to the earlier handshake and that the current ClientHello carried a valid binder. The application had made a separate decision: treat successfully resumed transport state as current authorization.
That shortcut collapsed two clocks. Cryptographic resumption remained valid under the ticket policy. Application authority had expired under a different policy. The failure was not that TLS accepted a forged ticket. It was that the surrounding system let ticket acceptance speak beyond its protocol mandate.
A ticket labels a new key
The current TLS 1.3 specification replaces older session-ID and TLS 1.2 ticket designs with a common PSK exchange. After the client Finished, a server may send NewSessionTicket. The message associates an opaque ticket value with a PSK derived from the resumption secret and a per-ticket ticket_nonce.
The ticket value is not required to reveal its structure. It can be a database lookup key, leaving state on the server, or a self-encrypted and self-authenticated package carried by the client. In both designs, the wire value functions as a PSK identity. It is not the old traffic key and it does not resume old record sequence numbers.
Several tickets may come from one connection. They support parallel connections and racing across interfaces. Because each message carries a distinct nonce, each derives a different PSK. “Same original connection” therefore does not mean “same resumption secret exposed as the same reusable credential.” The issuance ledger needs a ticket or key-epoch correlation, not one undifferentiated session flag.
Lifetime is an upper bound, not a promise
ticket_lifetime is measured from issuance and cannot exceed seven days. A value of zero tells the client to discard the ticket. The client may delete it earlier, and the server may consider it valid for less time than advertised.
This asymmetry matters. The field bounds how long a compliant client may attempt use. It does not grant a right to successful resumption for the whole interval. A server can rotate a key, delete a database entry, narrow an acceptance domain, revoke application state or require a full handshake.
ticket_age_add hides the plain ticket age from a passive observer by adding a fresh random value modulo 2³². When the client offers the ticket, the server subtracts that value and compares the result with elapsed time. This is useful freshness evidence, not an active anti-replay token. A copied ticket carries the same obfuscated arithmetic.
If age falls outside tolerance, TLS distinguishes two decisions. The server should continue the handshake while rejecting 0-RTT and should not assume the ClientHello is fresh. It can still accept ordinary resumption. Age validation therefore cannot be reduced to one “ticket valid” Boolean.
The binder proves a chain, not every claim inside it
The client offers one or more PSK identities and matching binders. A binder authenticates the current ClientHello with the associated PSK and transitively binds it to the handshake that produced the resumption secret. The server selects one compatible identity.
That proof is strong and narrow. It establishes continuity of secret possession and handshake history. It does not timestamp a user decision, prove that an account remains enabled, show that a device still satisfies posture policy or make an old risk score current.
For a resumed PSK-authenticated handshake, the server does not send Certificate or CertificateVerify again. The earlier authenticated context is doing cryptographic work. Applications that attach mutable claims to it must say which claims can survive without a new source check.
OpenSSL makes the version boundary visible after post-handshake client authentication: a server can issue new tickets associated with the updated client identity. The new ticket does not retroactively upgrade older ones. If an operator cannot distinguish the two populations, revocation and audit have already lost the relevant order.
Service identity is current-handshake input
The client sends the current SNI in the resumption ClientHello. TLS requires the client to resume only where that name is valid for the certificate from the original session and normally recommends the same SNI. If an implementation reports SNI to its application, it must report the value from the new ClientHello, not the historical one.
This prevents the word “session” from erasing the requested service. RFC 9525 likewise treats reference identity as a current application concern; SNI and ALPN help identify the service and protocol being requested.
A shared ticket key across names, tenants or regions is therefore an authority decision. It may improve failover and resumption rate. It can also widen which node can interpret state and which service boundary can accept it. BoringSSL exposes cross-name resumption as an explicit policy surface rather than an automatic consequence of a decryptable ticket.
The KDF hash is another hard boundary. A ticket may resume only with a cipher suite using the same KDF hash as the original connection. Compatibility is not a request to preserve every earlier parameter. The new ClientHello, current service routing and application profile still control the new connection.
Resumption is not early execution
A NewSessionTicket may carry an early_data extension with a byte limit. That gives the client permission to offer 0-RTT under that ticket. It does not require the server to accept the early data, and it does not make the covered application operation safe.
Three events must remain separate in telemetry: ticket decryption or lookup, PSK selection for the handshake, and 0-RTT acceptance. A server can reject early data because age is doubtful, anti-replay memory is unavailable or application parameters changed, then finish an ordinary resumed connection.
HTTP 425 governs a later boundary. It lets an origin refuse to act on a request whose early-data provenance makes replay consequential. That existing application control does not define the authority of the ticket itself. This report still applies to a 1-RTT resumption deployment that has 0-RTT disabled everywhere.
QUIC supplies another composition test. Its 0-RTT path depends on remembered transport and application parameters as well as TLS state. A valid TLS ticket cannot declare old QUIC limits or HTTP/3 SETTINGS compatible. Each layer owns its continuity check.
Storage design selects the acceptance domain
A database-backed ticket can be deleted on use, bounded to one authority store and audited as a consumable identity. It also makes resumption depend on database availability and cross-node consistency. A self-contained ticket can survive node loss without per-ticket lookup, but every holder of the wrapping key may be able to accept its carried state until that key is retired.
The tradeoff is not “stateful secure, stateless insecure.” It is a choice of failure and authority domains. Database lag may create false rejection or repeated acceptance. A broadly replicated wrapping key may turn a local state decision into a regional one. Long overlap between key epochs may preserve availability while extending the time in which old state remains interpretable.
OpenSSL exposes ticket decrypt status, the key name and optional application data to callbacks. It can issue zero, one or several TLS 1.3 tickets and can suppress them. GnuTLS exposes ticket enablement, key material and additional issuance. BoringSSL’s server path generates fresh age offsets, limits ticket count and gates early data separately.
These controls prove that policy can be implemented. They do not prove which key epoch a process loaded, whether all nodes rotated together, what application claims were encoded or whether the accepting service revalidated them.
What may cross the boundary
Stable cryptographic facts are candidates for carriage: PSK identity, KDF hash, selected resumption mode and a bounded reference to the authenticated handshake. Mutable business facts need their own rule.
An application can put a user ID and authorization-version number in authenticated ticket state, then retrieve current authorization before granting access. It can carry a tenant route with an expiry and reject it after topology changes. It can record a post-handshake client-certificate state and issue a new ticket generation when that state changes.
The dangerous design carries the answer instead of the evidence: “administrator=true,” “device trusted,” “subscription active,” “revocation clear.” Encryption and authentication prevent undetected modification. They do not prevent an authentic statement from becoming stale.
The same distinction applies to EAP-TLS. Its profile uses one or more tickets to enable authentication resumption and respects the seven-day ceiling. The profile must still decide when credentials, network access or policy changes invalidate the shortcut. TLS supplies the carrier; the deployment owns current authorization.
Evidence that can survive failover
Record a privacy-safe ticket correlation or ticket-key name, issuing node and region, issue time, advertised and effective expiry, key epoch, storage model, PSK KDF hash and PSK mode. On offer, record client-reported age, decrypt or lookup result, selected identity index, current SNI and ALPN, ordinary resumption result and full-handshake fallback.
Record 0-RTT separately: offered, cryptographically eligible, rejected or accepted, byte limit, anti-replay state and application decision. Never let resumed=true imply early_data_accepted=true.
For application state, preserve schema version, authorization version, revocation check, tenant-route version and the source that made each current decision. A redacted correlation can join the issue and acceptance records without publishing the ticket or PSK.
Negative tests should cover an expired ticket, a server-shortened lifetime, an unknown key name, failed authentication, a deleted database row, retired wrapping keys, cross-region replay, SNI and ALPN changes, an incompatible KDF hash and a revoked user whose ticket remains cryptographically decryptable.
The recovery test is as important as rejection. A rejected ticket should fall back to a full handshake when policy permits. An emergency control should retire one ticket-key epoch or one application-state version without disabling unrelated TLS connections. After rollback, new tickets must carry the new version and old tickets must fail for a recorded reason.
Sources
- https://www.rfc-editor.org/rfc/rfc9846.html
- https://www.rfc-editor.org/rfc/rfc9325.html
- https://www.rfc-editor.org/rfc/rfc9190.html
- https://www.rfc-editor.org/rfc/rfc9001.html
- https://www.rfc-editor.org/rfc/rfc8470.html
- https://www.rfc-editor.org/rfc/rfc9525.html
- https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
- https://docs.openssl.org/master/man3/SSL_CTX_set_num_tickets/
- https://docs.openssl.org/master/man3/SSL_CTX_set_session_ticket_cb/
- https://docs.openssl.org/master/man3/SSL_CTX_set_options/
- https://www.gnutls.org/manual/html_node/Session-tickets.html
- https://www.gnutls.org/manual/html_node/Session-resumption.html
- https://boringssl.googlesource.com/boringssl/+/refs/heads/main/ssl/tls13_server.cc
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
