Google 文档 API 无法通过 Google 服务帐户进行身份验证 - “不允许范围为空或缺失。”

问题描述 投票:0回答:1

我的 Swift 应用程序需要使用 Google 文档 API 读取 Google 文档,并使用 Google 服务帐户进行身份验证。该应用程序首先请求 OAuth2 访问令牌,以用于调用 Google Drive API。 Google 为某些语言提供了执行此功能的库,但不包含 Swift 的库。因此应用程序必须通过其他方式请求并接收访问令牌。

应用程序使用 SwiftJWT 生成签名的 JWT 声明,发送到 /www.googleapis.com/oauth2/v4/token,并期望返回访问令牌。然而,调用的错误消息是 -

**error = "invalid_scope";"error_description" = "不允许为空或缺少范围。"; **

所使用的服务账户名为 @<...>.iam.gserviceaccount.com,并在项目中具有 IAM 角色“所有者”和“查看者”。因此,它应该有权使用 Google Documents API。 (但是,在将角色分配给服务帐户时,我没有看到任何专门提及文档/Google Documents API 范围的角色)

签名的 JWT 请求中使用的私钥是根据附加到此 Google 服务帐户的密钥生成的。

我已经尝试了很多方法来解决这个问题,但仍然不够。任何见解都会非常有帮助。预先感谢您的评论...

导入 SwiftJWT 进口阿拉莫火

func getAuthToken() {
    let header = Header(kid: "<myiD>")
    
    let claims = ClaimsStandardJWT(
        iss: "<my_server_account>@<my_project>.iam.gserviceaccount.com",
        aud: ["https://oauth2.googleapis.com/token"],
        exp: Date().addingTimeInterval(3600),
        iat: Date()
     )
    
    var jwt = JWT(header: header, claims: claims)

    let privateKey =  """
    -----BEGIN PRIVATE KEY-----
    <my_private_key>
    -----END PRIVATE KEY-----
    """

    guard let privateKeyData = privateKey.data(using: .utf8) else {
        // Handle the case where the conversion fails
        print("Failed to convert string to data")
        return
    }
    var signedJWT = ""
    do {
        signedJWT = try jwt.sign(using: .rs256(privateKey: privateKeyData))
    } catch  {
        print("Failed to sign JWT: \(error)")
    }
        
    //==================== Exchange the JWT token for a Google OAuth2 access token: ====
        
    let headers: HTTPHeaders = ["Content-Type": "application/x-www-form-urlencoded"]
    let params: Parameters = [
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": signedJWT,
        "scope": "https://www.googleapis.com/auth/documents.readonly"
    ]
    
    AF.request("https://oauth2.googleapis.com/token",
               method: .post,
               parameters: params,
               encoding: URLEncoding.httpBody,
               headers: headers).responseJSON { response in
        print (response.result)
        switch response.result {
        <------------------------------------------------ Error message is returned here
        case .success(let value):
            let json = value as? [String: Any]
            if let json = json {
                let accessToken = json["access_token"] as? String
                if let accessToken = accessToken {
                    fetchGoogleDocContent(with: accessToken)
                }
            }
        case .failure(let error):
            print("Error getting access token: \(error)")
        }
}

发布到 https://oauth2.googleapis.com/token 应该返回访问令牌,但报告

错误=“无效范围”; "error_description" = "不允许为空或缺少范围。";

swift google-sheets oauth-2.0 jwt
1个回答
0
投票

我想通了。您需要在声明中传递范围,而不是在请求正文中传递范围。但是,SwiftJWT 没有提供这样的结构,因此我们可以自己对其进行子类化。这对我有用:

struct GoogleAPIClaims: Claims {
    var iss: String
    var sub: String
    var scope: String
    var aud: String
    var exp: Date
    var iat: Date
}
© www.soinside.com 2019 - 2024. All rights reserved.