how to solve flutter CERTIFICATE_VERIFY_FAILED error while performing a POST request?

Solution 1:

Just for the sake of clarity specially for the newcomers to Flutter/Dart, here is what you need to do in order to enable this option globally in your project:

  1. In your main.dart file, add or import the following class:
 class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext? context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}
  1. In your main function, add the following line after function definition:

HttpOverrides.global = MyHttpOverrides();

This comment was very helpful to pass through this matter, and please note that...

This should be used while in development mode, do NOT do this when you want to release to production, the aim of this answer is to make the development a bit easier for you, for production, you need to fix your certificate issue and use it properly, look at the other answers for this as it might be helpful for your case.

Solution 2:

Edit & Update Feb 2021: When this question was earlier asked there were not enough docs and developers to answer. The following answers may be more helpful than this one: Ma'moon Al-Akash Answer, Pedro Massango's Answer & Ken's Answer

If you have not found the solution in these 3 answers, you can try the solution below.

Originally Answered Jan 2019: The correct(but a bad) way to do it ,as I found out, is to allow all certificates.

HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);

String url ='[email protected]';

Map map = { 
     "email" : "email" , 
     "password" : "password"
};

HttpClientRequest request = await client.postUrl(Uri.parse(url));

request.headers.set('content-type', 'application/json');

request.add(utf8.encode(json.encode(map)));

HttpClientResponse response = await request.close();

String reply = await response.transform(utf8.decoder).join();

print(reply);

Solution 3:

If you are using Dio library, just do this:

Dio dio = new Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
    (HttpClient client) {
  client.badCertificateCallback =
      (X509Certificate cert, String host, int port) => true;
  return client;
};

Solution 4:

  1. Download cert from https://letsencrypt.org/certs/lets-encrypt-r3.pem

  2. Add this file to assets/ca/ Flutter project root directory

  3. Add assets/ca/ assets directory in pubspec.yaml

  4. Add this code on your app initialization:

    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
    
      ByteData data = await PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem');
      SecurityContext.defaultContext.setTrustedCertificatesBytes(data.buffer.asUint8List());
    
      runApp(MyApp());
    }
    

It works with the default chain, so no changes are needed on the server. Android < 7.1.1 clients will still have access in a browser context.