Skip to content
Shawn Yang edited this page Jul 27, 2024 · 12 revisions

Server authentication beyond certificate pinning

Certificate pinning is commonly used to authenticate servers and to prevent man-in-the-middle (MiTM) attacks in the client-server communications. Given its maintenance complexity, other security measures, such as Certificate Transparency (CT) and Online Certificate Status Protocol (OCSP) Stapling, are actively studied by researchers and engineers. But CT and OCSP also have security and performance issues, see one of the discussions of CT here. This project proposes a digital signature method to authenticate servers, another way to verify server certificate with reduced maintenance complexity and little performance impact.

Two options are proposed to perform server authentication and prevent MiTM attack without using a hardcoded server certificate inside a client. Instead of verifying the public key (or pin) of a certificate directly during TLS handshaking, the proposed method requires a server to sign a shared secret between a client and a server, and lets the client verify the digital signature using the server public key.

1. Using Server authentication code

In the Readme.md, a method is described how to perform server authentication after a server certificate is updated or revoked, and how to prevent the client and server communication from MiTM attack. The key idea is that a client creates a unique secret server authentication code for a server, sends it to the server after the first-round certificate pinning finishes successfully. For subsequent client-server communications, the server signs the server authentication code, and the client verifies this signature using the server public key obtained in the TLS handshaking. The signature is transferred to the client using a custom TLS extension or through a server api.

2. Using SSO refresh token

SSO authentication is widely used to authenticate a user through an authentication server and grant the user access privileges to multiple service providers (or resource servers). After an authentication server authenticates an user, the client will receive a user SSO access token and a SSO refresh token. The user SSO access token is sent to resource servers when the client wants to access the resources. The SSO refresh token is never exchanged between a client and resource servers. This feature makes the SSO refresh token a perfect shared secret. The data flow to use it to authenticate the server is similar to using the server authentication code, with one additional step: after a resource server receives the nonce from the client, it will forward this nonce to the authentication server and let it calculate the hash of the user's SSO refresh token and the nonce, and this hash is signed using the updated server certificate and sent to the client to verify. The data flow is shown in the diagram below: Diagram shows how SSO refresh token is used to authenticate a resource server from a client

Note that this approach requires the authentication server to provide an API to calculate the hash of a user's SSO refresh token and a nonce for the resource servers. For enterprise SSO solutions, this simple API can be implemented fairly straightforward. For those using social medias, such as Facebook, it is still feasible to get it implemented even though more coordination works among different parties are expected.

Summary

A solution is proposed to authenticate servers by verifying the digital signature of shared secrets between clients and servers. A shared secret can be a random server authentication code generated by a client or a SSO refresh token. After a server with an updated certificate is authenticated, the updated server certificate can be promoted as trusted and used as a pin for all communications after. Therefore, this solution can update the trusted server certificate (or pin) held by a client dynamically without releasing new versions of a client application, and reduces the complexity and cost of certificate pinning significantly.