HTTPS
While HTTPS encrypts communication between your app and the server, it relies on certificates issued by trusted authorities to verify the server's identity. Without additional security measures, the app might accept a fraudulent certificate presented by a Man-in-the-Middle MITM attacker. This attacker could then intercept and decrypt sensitive data like login credentials or financial information.
Regular HTTPS relies on trusting external authorities to verify a server's identity. SSL pinning adds an extra layer of security by checking if the server's certificate matches a "fingerprint" stored directly in your app. If they don't match, the app can block the connection, preventing imposters from eavesdropping on your communication.
SSL certificates, like passports, expire to maintain security. Even though your app itself might not change, updating the app with the new certificate ensures a secure connection.
Manual Implementation using http
package
You'll need to:
- Load the trusted certificate (usually in PEM format) from your assets.
- Configure the SecurityContext to trust only the loaded certificate(s).
- Use the SecurityContext with your HTTP client (e.g., HttpClient) to make secure connections.
1. Add ssl_certificate.pem
into pubspec.yaml
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/ssl_certificate.pem
- assets/app-logo.png
2. Create Future to Load Certificate
Future<SecurityContext> get sslClient async {
final sslCert = await rootBundle.load('assets/ssl_certificate.pem');
SecurityContext securityContext = SecurityContext(withTrustedRoots: false);
securityContext.setTrustedCertificatesBytes(sslCert.buffer.asInt8List());
HttpClient client = HttpClient(context: securityContext);
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => false;
IOClient ioClient = IOClient(client);
return ioClient;
}
Here enabling SSL pinning by loading a trusted certificate from the app's assets and configuring the SecurityContext
to only trust that specific certificate. This provides an extra layer of security for network connections by preventing man-in-the-middle attacks with fraudulent certificates.
Important points to consider:
- Make sure the certificate file in your assets is valid and belongs to the server you want to connect to securely.
- Updating the app might be necessary if the server's certificate changes and needs to be replaced in the assets.
Testing SSL Pinning
- Valid Certificate ✅
Your app will be able to establish a secure connection with the server.
- Invalid Certificate ⚠️
Using an invalid or expired certificate poses a security risk. Your app won't be able to establish a secure connection with the server, potentially exposing sensitive data to eavesdroppers.
You might encounter exceptions like HandshakeException
or CertificateNotFoundException
in such scenarios.
By following the implementation steps you can effectively bolster the communication channel between your app and its backend servers.
Remember, SSL pinning is just one piece of the security puzzle.
Always adhere to secure coding practices and stay updated on the latest security threats to maintain a robust defense for your Flutter app.
Happy Coding! 🧑🏻💻
Top comments (3)
isn't this not good way? because the certificate will be attached to apk file. hence, attacker can obtain certificate file from assets and use it.
is there any other way that either i can provide my certificate but it won't be attached in the apk file (no security concern exist)? or is there a way to do it without giving my server certificate to my flutter app? like attaching only hashed public key of server certificate or something like this, so if attacker obtain it, he can't use it.
thanks.
Sorry, I would like to ask, if I want to bind credentials for firebase cloud functions, what should I do?
Credentials for Firebase Cloud Functions are managed on the server-side, not the client-side (Flutter).
Right Approach
Hope this helps!👍