如何验证 Assistant SDK 的 gRPC 调用?

How to authenticate a gRPC call for the Assistant SDK?

我正在使用 Swift gRPC 库(奇怪的是它没有在 gRPC 的网站上列出,但有一个 GitHub repo 用于它)来构建 Google 适用于 macOS 的助手 SDK。我已经获得了我的 OAuth2 凭据和令牌,并且正在尝试发出开始对话的初始请求,但是它没有这样做。

我总是得到错误 Google_Assistant_Embedded_V1Alpha1_EmbeddedAssistantClientError error 1.)gRPC.CallError error 1.

我 运行 Wireshark 尝试调试问题,我看到我的计算机 正在 尝试建立连接但最终终止了连接。我认为这可能是由于 TLS 问题,但我不确定是否确实如此或如何解决它。

我注意到服务初始化函数有一个重载,您可以在其中指定证书,但我不知道该放什么(或者是否需要使用该函数)

typealias AssistantService = Google_Assistant_Embedded_V1Alpha1_EmbeddedAssistantService
typealias AssistantCall = Google_Assistant_Embedded_V1Alpha1_EmbeddedAssistantConverseCall
typealias AudioInConfig = Google_Assistant_Embedded_V1alpha1_AudioInConfig
typealias AudioOutConfig = Google_Assistant_Embedded_V1alpha1_AudioOutConfig
typealias ConverseRequest = Google_Assistant_Embedded_V1alpha1_ConverseRequest
typealias ConverseConfig = Google_Assistant_Embedded_V1alpha1_ConverseConfig    

var service: AssistantService?
var currentCall: AssistantCall?

public init() {
    service = AssistantService(address: Constants.ASSISTANT_API_ENDPOINT)
    let token = "Bearer \(UserDefaults.standard.string(forKey: Constants.AUTH_TOKEN_KEY)!)"
    service?.metadata = Metadata(["authorization" : token])
}

func initiateRequest() {
    var request =   ConverseRequest()
    request.config = ConverseConfig()

    var audioInConfig = AudioInConfig()
    audioInConfig.sampleRateHertz = 16000
    audioInConfig.encoding = .linear16
    request.config.audioInConfig = audioInConfig


    var audioOutConfig = AudioOutConfig()
    audioOutConfig.sampleRateHertz = 16000
    audioOutConfig.encoding = .linear16
    audioOutConfig.volumePercentage = 50
    request.config.audioOutConfig = audioOutConfig

    do {
        currentCall = try service?.converse(completion: { result in
            print("Result code \(result.statusCode)")
            print("Result description \(result.description)")
            print("Metadata \(String(describing: result.initialMetadata))")
            print("Status message \(result.statusMessage ?? "Error")")
            print("Obj description \(String(describing: result))")
            print("result \(result)")
        })

        try currentCall?.send(request) { err in
            print("Error in initial request: \(err)")
        }
    } catch {
        print("Initial error \(error)")
    }
}

这是 Wireshark 的样子,如果有帮助的话:

我不知道 Swift,您的 Wireshark 屏幕截图可能掩盖了重要信息,但我相信以下一项或两项可能是问题所在:

  1. Constants.ASSISTANT_API_ENDPOINT需要设置为"embeddedassistant.googleapis.com"。 (不清楚,但我不认为 Wireshark 中显示的目标地址是 API 端点,它应该是。)

  2. Constants.AUTH_TOKEN_KEY 应该是您作为 OAuth2 舞蹈的一部分获得的身份验证令牌。请记住,它会过期(通常在一小时后),您需要重新购买。我不知道 Swift 配置是如何工作的,但在其他情况下,您不需要指定身份验证信息的 "Bearer" 部分,因为您没有专门传递 header .

我必须将 here 找到的 roots.pem 文件添加到我的项目中并按如下方式使用它:

let u = Bundle.main.url(forResource: "roots", withExtension: "pem")!
let certificate = try! String(contentsOf: u)
let token = "Bearer \(UserDefaults.standard.string(forKey: Constants.AUTH_TOKEN_KEY)!)"
service = AssistantService(address: Constants.ASSISTANT_API_ENDPOINT, certificates: certificate, host: nil)
service?.metadata = Metadata(["authorization" : token])

请查看一些支持 Google 应用程序默认凭据的 new examples in the grpc-swift project that call Google Cloud APIs. I've simplified client creation to use TLS by default and to embed a default roots.pem in the library binary. You can see that here along with usage of an auth library

拿了最新的
吊舱 'SwiftGRPC' 吊舱 'SwiftProtobuf' 版本使用 pod 更新并得到修复。

正在安装 BoringSSL 10.0.6(原为 10.0.5,源代码从 https://github.com/cocoapods/specs.git 更改为 https://github.com/CocoaPods/Specs.git) 安装 SwiftGRPC 0.5.1(原为 0.4.3,源代码从 https://github.com/cocoapods/specs.git 更改为 https://github.com/CocoaPods/Specs.git) 安装 gRPC-Core 1.12.0(原为 1.11.0,源代码从 https://github.com/cocoapods/specs.git 更改为 https://github.com/CocoaPods/Specs.git) 安装 Realm 3.7.6(原为 3.7.4,源代码从 https://github.com/cocoapods/specs.git 更改为 https://github.com/CocoaPods/Specs.git) 安装 RealmSwift 3.7.6(原为 3.7.4,源代码从 https://github.com/cocoapods/specs.git 更改为 https://github.com/CocoaPods/Specs.git

然后我只需要用我的证书创建 session/service。

let certPath = Bundle.main.url(forResource: "XYZ", withExtension: "pem")! 让证书=尝试!字符串(内容:certPath) 服务 = Pronounce_PronounceServiceClient(地址:Constants.ServerApi.grpcBaseUrl,证书:证书)