Implementing Mutual TLS Authentication
A step-by-step guide to implementing mutual TLS (mTLS) authentication in FastAPI using OpenSSL and Uvicorn.
Mutual TLS (mTLS) authentication is like a secret handshake between your client and server—both parties show their secret badges (certificates) before they start chatting. This mechanism is widely used in secure API communications, microservices, and zero-trust architectures.
How Mutual TLS Works
- Client Hello
The client initiates a connection with a TLS handshake. - Server Certificate
The server presents its certificate to prove its identity. - Client Certificate Request
The server asks, “Who are you?” by requesting a certificate from the client. - Client Certificate Verification
The client provides its certificate, and the server verifies it—think of it as checking the secret handshake. - Secure Communication
Once both sides are satisfied, encrypted communication begins.
mTLS Handshake Diagram
Below is a Mermaid diagram that visually represents the mTLS handshake process:
sequenceDiagram
participant C as Client
participant S as Server
participant CA as Certificate Authority
C->>S: Client Hello
S->>C: Server Certificate (Issued by CA)
S->>C: Request Client Certificate
C->>S: Client Certificate (Issued by CA)
S->>CA: Verify Client Certificate
Note over C,S: Mutual TLS Authentication Successful
C->>S: Encrypted Request
S->>C: Encrypted Response
Generating Certificates with OpenSSL
Before you implement the mTLS connection in your application, you need to generate certificates. Here’s how to create a Certificate Authority (CA) and then issue certificates for the server and client.
1. Generate CA Certificate
1
2
openssl req -x509 -newkey rsa:4096 -days 365 -nodes \
-keyout ca.key -out ca.crt -subj "/CN=MyCA"
2. Generate Server Certificate
1
2
openssl req -newkey rsa:4096 -nodes -keyout server.key -out server.csr -subj "/CN=server"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
3. Generate Client Certificate
1
2
openssl req -newkey rsa:4096 -nodes -keyout client.key -out client.csr -subj "/CN=client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
Implementing mTLS in Python with FastAPI and Uvicorn
Below is an example of a FastAPI application configured for mTLS using Uvicorn and Python’s ssl
module.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from fastapi import FastAPI
import ssl
app = FastAPI()
@app.get("/")
async def secure_endpoint():
return {"message": "Hello, you have successfully authenticated using mTLS!"}
if __name__ == "__main__":
# Create an SSL context that requires client certificates.
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(certfile="server.crt", keyfile="server.key")
ssl_context.load_verify_locations(cafile="ca.crt")
ssl_context.verify_mode = ssl.CERT_REQUIRED # Enforce client authentication
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, ssl_context=ssl_context)
Testing the mTLS Connection
After setting up your server, test the mTLS configuration using curl
.
Successful Authentication (With Client Certificate)
1
curl --cert client.crt --key client.key --cacert ca.crt https://localhost:8000/
Failed Authentication (Without Client Certificate)
1
curl --cacert ca.crt https://localhost:8000/
Skipping the client certificate should cause the connection to be rejected—just like trying to enter an exclusive club without the proper credentials!
Conclusion
- Mutual TLS ensures both the client and the server prove their identities—a true two-way authentication.
- FastAPI + Uvicorn: This combo easily supports mTLS using Python’s
ssl
module. - OpenSSL: The go-to tool for generating the necessary certificates.
With this setup, every connection is double-checked, making your communications as secure as a VIP event. Happy coding and secure connecting!