Reputation: 1662
I have a server that supports oauth2.0 with authorization code grant. server uses a self-signed certificate which i have manually installed on my android device. I am using the standard oauth2 library https://pub.dev/packages/oauth2 to perform oauth flow. Now everything works fine until this step
var client = await grant.handleAuthorizationResponse(responseUrl.queryParameters);
Where client has to make a post request using code fetched during authorization to get an access token. (see example from https://pub.dev/packages/oauth2#authorization-code-grant) here I get a
HandshakeException: Handshake error in client (OS Error:
E/flutter (11483): CERTIFICATE_VERIFY_FAILED: self signed certificate in certificate
Now I already know how to allow my certificate or completely bypass certificate check using a HttpClient object. problem is, HttpClient is part of the library dart._http which is under http.dart, but the Client object oauth2.dart uses is from http library under client.dart. even though they both seem to be http clients and support post methods only the former supports a custom SecurityContext. and there's no way apparently I can cast one into the other. I have a two part question:
I've also looked into oauth2_client but it doesn't even support a custom http client and oauth_dio but that one only implements client credentials grant whereas my server only supports authorization code grant.
Upvotes: 2
Views: 2387
Reputation: 21
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;
Upvotes: 1
Reputation: 29316
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:
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:
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:
Upvotes: 1