首页 > 解决方案 > 使用自签名证书时 Flutter OAuth 请求失败

问题描述

我有一台支持 oauth2.0 并授予授权码的服务器。服务器使用我手动安装在我的 android 设备上的自签名证书。我正在使用标准 oauth2 库https://pub.dev/packages/oauth2来执行 oauth 流程。现在一切正常,直到这一步

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

客户端必须使用授权期间获取的代码发出发布请求以获取访问令牌。(参见https://pub.dev/packages/oauth2#authorization-code-grant的示例)在这里我得到一个

HandshakeException: Handshake error in client (OS Error: 
E/flutter (11483):  CERTIFICATE_VERIFY_FAILED: self signed certificate in certificate

现在我已经知道如何使用 HttpClient 对象允许我的证书或完全绕过证书检查。问题是,HttpClient 是 http.dart 下的 dart._http 库的一部分,但 oauth2.dart 使用的 Client 对象来自 client.dart 下的 http 库。尽管它们似乎都是 http 客户端并支持 post 方法,但只有前者支持自定义 SecurityContext。而且显然我无法将其中一个放入另一个中。我有一个两部分的问题:

  1. 有没有人对这个 OAuth2.0 库有类似的经验,或者知道我是否可以让它与我的自签名证书一起使用?
  2. 我的最新想法是创建一个扩展 http.BaseClient 的自定义客户端类。因为我注意到 OAuth2.0 只使用来自客户端对象的 post 方法,所以我正在考虑重写此方法并使用 HttpClient 对象来执行 post 请求。但是,来自 HttpClient 的 post 方法只需要一个 Uri,而来自 BaseClient 的 post 方法需要 url、标头、正文和编码。知道如何根据 HttpClient 的请求进行设置吗?

我也研究了 oauth2_client 但它甚至不支持自定义 http 客户端和 oauth_dio 但它只实现客户端凭据授予,而我的服务器只支持授权代码授予。

标签: flutterdartoauth-2.0ssl-certificateself-signed-certificate

解决方案


完成之前的一些答案后,我发现可以http.Client在构造函数中传递一个命名参数oauth2.AuthorizationCodeGrant

所以我做了一个钩子badCertificateCallback,我可以在某些特定情况下实施一些规则来忽略证书验证(比如从开发环境中的模拟器调用 10.0.2.2)。我认为它可以尽可能地查看一些X509Certificate属性来做出决定。

  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());

后来虽然此调用用于引发证书检查异常,但它现在正在接受我的开发自签名证书。

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

所需进口:

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;

推荐阅读