Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Dio HTTPS Certificate Validation Ignoring onBadCertificate - CA Cert Problem?

I've run into a bit of a quandary. I'm writing a client/server application. The frontend is in Flutter and uses the Dio http package, the backend is Java. The backend REST API is secured via TLS certificate.

As many other questions have pointed out, Flutter doesn't seem to have access to the system CA Certificate store on all platforms. This is problematic because I intend to allow for self hosting of the server application, meaning certificates from all different CAs could be utilized server-side, so my HTTP client will need to support all of the CAs that a typical web browser supports.

Dio apparently allows you to set a trusted cert chain, but I'm wondering how best to leverage that.

Has anyone encountered this problem before. What solution did you implement to fix this?

These are the solutions I've thought of so far:

  1. Allow user to "upload" ca cert bundle and store bytes in shared_preferences (difficult for users)
  2. Find another way to validate the certificate e.g. with user entered thumbprint? (less difficult, let all certs fail original validation, then do custom validatation with onBadCertificate against stored thumbprint)
  3. Find a package which offers access to system certificate store
  4. Ship inside the application a majority of big name CA certs and trust them with Dio somehow

The other issue I came here about is that Dio appears to be ignoring my onBadCertificate method. I declared this inside a ConnectionManager, should I not do that?

Here is the code that is being ignored:

var dio = Dio()
  ..options.baseUrl = server
  ..interceptors.add(LogInterceptor())
  ..interceptors.add(CookieManager(cookieJar))
  ..httpClientAdapter = Http2Adapter(
    ConnectionManager(
      idleTimeout: 10000,
      // Ignore bad certificate
      onClientCreate: (_, config) => {
        //config.context?.setTrustedCertificatesBytes(File("/assets/certs/wildcard.pem").readAsBytesSync()),
        config.onBadCertificate = (_) => true, // <-- ignored, should bypass check
      }
    ),
  );

EDIT:

As mentioned in the comments, Flutter was in fact capable of using the system CA Certificate store. As I test other platforms, I'll update if I run into any problems with certificates. But this one is solved!

like image 259
TheFunk Avatar asked Nov 02 '25 01:11

TheFunk


1 Answers

Actual on March 2024:

onHttpClientCreate callback is deprecated. Now you should use createHttpClient and return your own HttpClient instance:

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';

Dio createDio({required String baseUrl, bool trustSelfSigned = false}) {
  // initialize dio
  final dio = Dio()
    ..options.baseUrl = baseUrl;

  // allow self-signed certificate
  (dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () {
    final client = HttpClient();
    client.badCertificateCallback = (cert, host, port) => trustSelfSigned;
    return client;
  };
  
  return dio;
}
like image 160
Lukas Pierce Avatar answered Nov 03 '25 16:11

Lukas Pierce



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!