我的 Swift 应用程序需要使用 Google 文档 API 读取 Google 文档,并使用 Google 服务帐户进行身份验证。该应用程序首先请求 OAuth2 访问令牌,以用于调用 Google Drive API。 Google 为某些语言提供了执行此功能的库,但不包含 Swift 的库。因此应用程序必须通过其他方式请求并接收访问令牌。
应用程序使用 SwiftJWT 生成签名的 JWT 声明,发送到 /www.googleapis.com/oauth2/v4/token,并期望返回访问令牌。然而,调用的错误消息是 -
**error = "invalid_scope";"error_description" = "不允许为空或缺少范围。"; **
所使用的服务账户名为
签名的 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" = "不允许为空或缺少范围。";
我想通了。您需要在声明中传递范围,而不是在请求正文中传递范围。但是,SwiftJWT 没有提供这样的结构,因此我们可以自己对其进行子类化。这对我有用:
struct GoogleAPIClaims: Claims {
var iss: String
var sub: String
var scope: String
var aud: String
var exp: Date
var iat: Date
}