2

我有一台支持 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 但它只实现客户端凭据授予,而我的服务器只支持授权代码授予。

4

2 回答 2

1

完成之前的一些答案后,我发现可以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;
于 2021-04-07T16:44:20.257 回答
1

飞镖选项 1

看起来 Dart 有自己的根证书。首选选项是避免编写任何安全代码。根据本指南,在开发环境中,将您的自签名主机的根证书配置为 Dart 信任的。

飞镖选项 2

看起来 Dart 还支持 C# 证书回调模型,其中有一个您可以覆盖的错误证书回调。不确定您是否必须继承 HttpClient 才能实现此目的。

/* 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)

}

移动 OAUTH 建议

我看到您正在尝试一些不同的库来解决您的 SSL 信任问题。所以我想我会指出我在移动 OAuth 库中寻找的符合移动安全标准的内容,这些是关键建议:

  • 使用授权码流 (PKCE)
  • 通过系统浏览器登录
  • 首选 HTTPS 重定向 URL(声称的 HTTPS 方案)

我至少会打算使用上述正确的流程。我总是对新的技术堆栈和他们的 OAuth 库有点警惕,因为他们通常不实施推荐的行为。

从安全角度来看,首选的库可能是Flutter AppAuth。我经常使用带有自签名证书的 AppAuth 库,但 AppAuth 库带来了以下挑战:

  • 在系统浏览器上登录很难做到可靠
  • 可能比您的利益相关者想要支付的工作量要多得多
  • 用户体验方面可能与人们习惯的不同
  • Flutter 桥可能有它自己的问题

我的应用程序授权资源

当您有时间时,可能值得浏览我的博客文章并运行我的 Swift / Kotlin 代码示例,看看您是否认为这些行为对您有用:

于 2020-06-18T18:24:47.790 回答