Mutual TLS (mTLS) with FastAPI and Uvicorn

The Challenge:

  • Help others who may want to configure mTLS with FastAPI
  • Clarify some of the lacking documentation (or things people know but may not have explained)
  • Document the approach (here)

The Approach

We Need two CAs:

  • A public CA (trusted) to create a secure channel
  • A validation CA which can issue client certs to be validated
  • A validation CA can be based on a public CA (however issuing client certs may be expensive) and Internal CA Based on Something Like Active Directory or a Self Manage CA.
  • I am going to use a Self Managed CA.

Nuts and Bolts

  • Create a validation_fullachain.pem for your validation CA. Below is my fullchain which has the Cryptoroo Root CA and the FastAPI MTLS Proofs Intermediate.
  • Create a Leaf Certificate Signed by the FastAPI MTLS Proofs Intermediate. Note: usually the Common Name is all that is needed for a MTLS Client Cert but you can add other extensions (e.g. OU, etc). Make sure that you add the Client Authentication Extended key usage.

Testing and Implementing

Phase 1: Ensure TLS/SSL is working

  • Run the command below. This should be the path to your Public CA Certificates.
  • For Let’s Encrypt it is the fullchain.pem and the privkey.pem files. Note: I use windows but linux clients should be /live/{domain}/ as well.
  • Note: I am using port 443 for a specific reason to make the testing consistent.
  • Note: You will need to run this as administrator on windows in order to be able to open the Certbot certificates.
uvicorn main:app — ssl-certfile <fullchain certificate in PEM> — ssl-keyfile <RSA / ECC Private Key>  — port 443
  • Browse to your domain name (mine is and inspect the certificate. If you see Let’s Encrypt and a green padlock you are good to go to the next phase.

Phase 2: For Testing CERT_OPTIONAL Configuration

  • Review the functioning of the CERT_OPTIONAL flag here.
  • Essentially the browser will ask for a certificate but if one is not presented it will allow users through.
  • Note: I can’t seem to be able to get the browser to show my self signed certificate so in the next phase I will use Postman and OpenSSL for verification
uvicorn main:app 
— ssl-certfile <fullchain certificate in PEM> — ssl-keyfile <RSA / ECC Private Key>
ssl-cert-reqs 1 --ssl-ca-certs <fullchain certificates in PEM>
— port 443

Browser Asking for a Certificate.

Clicking Cancel

  • Not sending a certificate still allows you to use the service.

Phase 3: For Testing CERT_REQUIRED Configuration

uvicorn main:app 
— ssl-certfile C:\Certbot\live\\fullchain.pem — ssl-keyfile C:\Certbot\live\\privkey.pem
— ssl-cert-reqs 2 — ssl-ca-certs E:\GITHUB\cryptoroo_ca\complete.crt
— port 443

Postman Call with no Client Cert:

Configuring Postman to Use SSL Certificates for

Refer to here for more details:


Verify that the certificate is in fact passed in:

Testing With OpenSSL:

openssl s_client -connect -cert <path to your mtls cert> -key <path to your mtls key>

We then Should get a command Prompt at the bottom:

Type In the Following to test a GET to the Root (/)

GET / HTTP/1.1


  • mTLS is quite possible and easy to configure with FastAPI
  • Uvicorn provides some tips on how to set this up but it does require knowledge of Python TLS/SSL library
  • There is an assumed knowledge of TLS and which arguments perform which function
  • Testing in Browser is hard as the personal keys don’t show up

To Do:

  • Demo using CURL
  • Fix Browser SSL Certificate Issue
  • Video Demos
  • Demo of how to create a Validation CA




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

5/3 web hacking daily log

Pact AMA Summary March 17

{UPDATE} العاب اطفال بنات كرتون المحقق كونان التعليمية Hack Free Resources Generator

5 Rules Every Ethical Hacker Must Follow!

Steganography is for Lovers

Breaking Down 5 Different Types of Malware Every Small Business Should Know

CyberSecurity For EveryOne

{UPDATE} Cownado! Hack Free Resources Generator

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Andrei Hawke

Andrei Hawke

More from Medium

In this article, we will look at how container systems use UTS namespace to provide hostname…

Kubernetes setup

Install and configure Elastic Stack — II

Run a Spring boot docker image on windows with a MySQL local database connection