It's actually more similar in TLS 1.3 than earlier versions. In earlier versions a client uses a very different method to prove its identity then the server does.
In TLS 1.3 they're completely symmetrical. First they show their certificate and then they sign the entire transcript of the session handshake using their private key and send that signature. The peer can use the public key from the certificate and their own copy of the transcript to verify the signature.
If your peer doesn't offer an acceptable cert you abort. If they show you a signature that doesn't verify you abort. This could be because they're an imposter who doesn't have the private key, or it could be that a MitM has changed the handshake, which will mean the transcripts don't match. Either way you haven't got a secure connection.
The TLS 1.3 server gets to be more specific about the cert it wants from a client. Where before it just says "Here's a list of CA roots I trust" now it can specify other filters such as here are some OIDs I want to see in the Certificate Policy.
That’s a great write up. Another important change is that renegotiation to add client cents is no longer supported. Old HTTPS could work like this:
C->S: handshake, no client cert
C->S: GET /
C<-S: here you go
C->S: POST /launch?target=Moscow
C<-S: server-initiated-renegotiation
C->S: everything from *this* byte on is covered by
C->s: client cert
C<-S: okay, launched
That is, the entangling of HTTP & TLS made some assumptions about the authentication parts being there for controlling read access, not about authenticating writes. Whoops. Nearly nobody using client cents wanted that behavior. Now there are much simpler mechanisms with many fewer bizarre side effects proposed at https://tools.ietf.org/id/draft-ietf-httpbis-http2-secondary...