Flutter OAuth request fails when using self-signed certificate Flutter OAuth request fails when using self-signed certificate dart dart

Flutter OAuth request fails when using self-signed certificate


DART OPTION 1

Looks like Dart has its own root certificates. The preferred option is to avoid writing any security code. Instead in a development environment, configure your self signed host's root certificate as trusted by Dart, according to this guide.

DART OPTION 2

Looks like Dart also supports the C# certificate callback model, where there is a Bad Certificate Callback that you can override. Not sure if you have to subclass HttpClient to achieve this.

/* PSEUDOCODE */bool callback(X509Certificate cert, String host, int port) {  // Don't allow any exceptions in production  if (currentEnvironment == "DEV" && host == "myhost.com") {    return true;  }  // Use system  return base.callback(cert, host, port)}

MOBILE OAUTH RECOMMENDATIONS

I see you are trying a few different libraries to solve your SSL trust problem. So I thought I'd point out what I look for in a mobile OAuth library, in line with mobile security standards, where these are the key recommendations:

  • Use Authorization Code Flow (PKCE)
  • Login via the System Browser
  • Prefer HTTPS redirect URLs (claimed HTTPS schemes)

I would at least aim to use the correct flow as above. I'm always a bit wary of new tech stacks and their OAuth libraries, since they often don't implement the recommended behaviour.

The preferred library from a security viewpoint is probably Flutter AppAuth. I have often used AppAuth libraries with self signed certificates, but the AppAuth library comes with these challenges:

  • Login on a System Browser is tricky to make reliable
  • Could be quite a bit more work than your stakeholders want to pay for
  • User experience aspects may be different to what people are used to
  • The Flutter bridge may come with its own problems

APP AUTH RESOURCES OF MINE

When you get some time it may be worth browsing my blog posts and running my Swift / Kotlin code samples, to see if you think any of this behaviour would be useful to you:


Completing some previous answers, I discovered that it's possible to pass an http.Client as a named argument in the oauth2.AuthorizationCodeGrant constructor.

So I made one that hooks a badCertificateCallback where I can implement some rules to ignore certificate validation under some particular circumstances (like calling 10.0.2.2 from an emulator in a dev environment). I think it could go as far as looking at some X509Certificate attributes to make the decision.

  bool _certificateCheck(X509Certificate cert, String host, int port) =>    host == '10.0.2.2';  http.Client devEmulatorClient() {    var ioClient = new HttpClient()      ..badCertificateCallback = _certificateCheck;    return new IOClient(ioClient);  }  final grant = oauth2.AuthorizationCodeGrant(      _clientId, _authorizationEndpoint, _tokenEndpoint,      httpClient: devEmulatorClient());

And later whereas this call use to throw the certificate check exception, it is now accepting my dev self-signed certificate.

  var client =      await grant.handleAuthorizationResponse(responseUrl.queryParameters);

Required imports:

import 'dart:io';import 'package:http/http.dart' as http;import 'package:http/io_client.dart';import 'package:flutter_web_auth/flutter_web_auth.dart';import 'package:oauth2/oauth2.dart' as oauth2;