FastAPI client certificate authentication dependencies for trusted proxy mTLS setups
Project description
FastAPI Client Cert Auth
FastAPI dependencies for authenticating service-to-service routes with client certificate identity forwarded by a trusted TLS terminator.
This package does not perform the TLS handshake inside FastAPI. A reverse proxy, load balancer, ingress controller, or ASGI server must verify the client certificate first. The package then parses the forwarded certificate header, matches it against your own certificate store, checks client IP allowlists, and exposes the authenticated client in request context.
Installation
pip install fastapi-client-cert-auth
Basic Usage
from fastapi import Depends, FastAPI
from fastapi_client_cert_auth import Certificate, get_mtls_dependency
app = FastAPI()
async def get_certificate() -> Certificate:
return Certificate(
cn='bundle-service',
white_listed_ips='10.20.0.0/16,127.0.0.1/32',
)
@app.get('/protected', dependencies=[Depends(get_mtls_dependency(get_certificate))])
async def protected() -> dict[str, str]:
return {'status': 'ok'}
In a real application, get_certificate() should usually depend on
get_certificate_from_header_dependency() and look up the parsed certificate in
your database by common name, serial number, fingerprint, or another policy.
Proxy Contract
The default certificate header is:
X-MTLS-CERT
The value must contain a URL-encoded PEM certificate. With Nginx this is usually
forwarded from $ssl_client_escaped_cert.
Recommended Nginx shape:
location /protected {
proxy_pass http://127.0.0.1:8080;
ssl_verify_client on;
ssl_client_certificate /etc/nginx/client-ca.crt;
proxy_set_header X-MTLS-CERT $ssl_client_escaped_cert;
proxy_set_header X-MTLS-VERIFY $ssl_client_verify;
proxy_set_header X-Real-IP $remote_addr;
}
Only trust these headers from infrastructure you control. Do not expose the FastAPI application directly to the public network while accepting client certificate identity from headers.
The client IP used for per-certificate allowlists is taken from X-Real-IP
first, falling back to the rightmost entry of X-Forwarded-For. Configure your
proxy to set X-Real-IP from the connection peer (as in the snippet above) so a
client cannot spoof its source address through a forged X-Forwarded-For
header. When X-MTLS-VERIFY is present it must carry a success value
(SUCCESS, OK, 1, or TRUE, case-insensitive); a present-but-failed value
is rejected even without require_verify_header=True.
Certificate Header Dependency
import sqlalchemy as sa
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from fastapi import Depends, HTTPException
from fastapi_client_cert_auth import (
Certificate,
get_certificate_from_header_dependency,
)
get_certificate_from_header = get_certificate_from_header_dependency(
require_verify_header=True,
)
async def current_certificate(
certificate: x509.Certificate = Depends(get_certificate_from_header),
) -> Certificate:
cn = certificate.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value
fingerprint = certificate.fingerprint(hashes.SHA256()).hex()
# Replace this with your database lookup.
if cn != 'bundle-service':
raise HTTPException(403, detail='Access denied')
return Certificate(cn=cn, finger=fingerprint, active=True)
x509 Helpers
The package includes small x509 utilities for local development and internal CA workflows:
from datetime import UTC, datetime, timedelta
from cryptography import x509
from cryptography.x509.oid import NameOID
from fastapi_client_cert_auth import make_ca, make_client_cert
subject = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, 'dev-ca')])
ca_key, ca_cert = make_ca(subject, datetime.now(UTC) + timedelta(days=365))
client_key, client_cert = make_client_cert(
'bundle-service',
(ca_key, ca_cert),
datetime.now(UTC) + timedelta(days=90),
)
Migration From gjn-fastapi-mtls-auth
The closest imports are:
from fastapi_client_cert_auth import (
Certificate,
get_certificate_from_header_dependency,
get_client_ip_dependency,
get_mtls_dependency,
)
The old misspelled module name dependancy is available as a compatibility
shim, but new code should import from fastapi_client_cert_auth.dependencies.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_client_cert_auth-0.1.0.tar.gz.
File metadata
- Download URL: fastapi_client_cert_auth-0.1.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5b8934b0434da354d4c2eef3b9e20226496d8d8ae21e4d17f3b77ecee34de89
|
|
| MD5 |
b7bd557987b625d1d6efe7b2d3278896
|
|
| BLAKE2b-256 |
ba3044fbe085345f41c3b9fe9654ed13ccbf237b01f9ad590d6cb2658cd0e407
|
Provenance
The following attestation bundles were made for fastapi_client_cert_auth-0.1.0.tar.gz:
Publisher:
publish.yml on ivolnistov/fastapi-client-cert-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_client_cert_auth-0.1.0.tar.gz -
Subject digest:
b5b8934b0434da354d4c2eef3b9e20226496d8d8ae21e4d17f3b77ecee34de89 - Sigstore transparency entry: 2058265841
- Sigstore integration time:
-
Permalink:
ivolnistov/fastapi-client-cert-auth@67a234f13cb08d5cb3623df8f6a3260ae7dacbd5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ivolnistov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67a234f13cb08d5cb3623df8f6a3260ae7dacbd5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file fastapi_client_cert_auth-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fastapi_client_cert_auth-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8b85b1345cca0dd4189b15d27c612df89f9cd7009f0e9060baf5b2d6e1eff33
|
|
| MD5 |
4446dcfb67719ce7b51e5fb6efc5e58b
|
|
| BLAKE2b-256 |
4e4c09457ef118d9fea8b898b843b991138270ab41d3137a746a816104d44677
|
Provenance
The following attestation bundles were made for fastapi_client_cert_auth-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ivolnistov/fastapi-client-cert-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_client_cert_auth-0.1.0-py3-none-any.whl -
Subject digest:
a8b85b1345cca0dd4189b15d27c612df89f9cd7009f0e9060baf5b2d6e1eff33 - Sigstore transparency entry: 2058266193
- Sigstore integration time:
-
Permalink:
ivolnistov/fastapi-client-cert-auth@67a234f13cb08d5cb3623df8f6a3260ae7dacbd5 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ivolnistov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67a234f13cb08d5cb3623df8f6a3260ae7dacbd5 -
Trigger Event:
release
-
Statement type: