What is certificate pinning and how do you implement it in Flutter?
TL;DR: Certificate pinning rejects connections to servers whose SSL certificate doesn't match an expected fingerprint. It prevents man-in-the-middle attacks. Implement by setting a custom badCertificateCallback or providing trusted certificates to Dio's HttpClientAdapter.
Full Answer
By default, Flutter trusts any certificate signed by a trusted CA. An attacker with a CA-signed certificate can intercept your traffic. Pinning ties your app to a specific certificate or its public key hash.
Implementation Approaches
- ▸Certificate pinning: Bundle the server's .pem file in assets, validate against it
- ▸Public key pinning: Hash the certificate's public key — survives certificate renewal
- ▸dio_certificate_pinning package: Simpler API wrapper around the same approach
Certificate pinning blocks legitimate certificate renewals if you forget to update the app. Use public key pinning instead, and always have a backup pin for certificate rotation.
Code Examples
// Connection rejected if certificate doesn't match // Use rootBundle to load pinned cert from app assets
Common Mistakes
- ✗Pinning in debug builds — breaks Charles Proxy and mitmproxy for development
- ✗Only pinning the leaf certificate — pin the intermediate CA to survive cert renewal
Interview Tip
Show you know the difference between certificate pinning (exact match) and public key pinning (hash match). Public key pinning is recommended for production because certificates rotate but public keys don't.