首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Google回复Review (androidpublisher)错误401

Google回复Review (androidpublisher)错误401
EN

Stack Overflow用户
提问于 2021-11-22 17:31:23
回答 1查看 758关注 0票数 0

我正在尝试从我构建的Swift应用程序连接到谷歌的Reply to Reviews API,这是https://www.googleapis.com/auth/androidpublisher范围的一部分,以便获得一个特定应用程序评论的列表。我创建了一个服务帐户,并用它创建了一个JWT令牌,然后尝试向API发出一个GET请求,但我得到了一个错误:

代码语言:javascript
复制
{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "CREDENTIALS_MISSING",
        "domain": "googleapis.com",
        "metadata": {
          "service": "androidpublisher.googleapis.com",
          "method": "google.play.publishingapi.v3.ReviewsService.List"
        }
      }
    ]
  }
}

这是请求url:

代码语言:javascript
复制
https://www.googleapis.com/androidpublisher/v3/applications/<APP_PACKAGE>/reviews?access_token=<JWT-TOKEN>

这是我的请求代码:

代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    
    let auth = Authentication()
    let jwt = auth.generateJWT()
    
    self.retriveReviews(packageIdentifier: "<APP_PACKAGE>", auth: jwt!)
}


func retriveReviews(packageIdentifier: String, auth: String) {
    let url = URL(string: "https://www.googleapis.com/androidpublisher/v3/applications/\(packageIdentifier)/reviews?access_token=\(auth)")
    print("Request URL: \(url)")
    var request = URLRequest(url: url!)
    request.httpMethod = "GET"
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else { return }
        print(String(data: data, encoding: .utf8)!)
    }

    task.resume()
}

JWT令牌:

代码语言:javascript
复制
import JWTKit
import UIKit

class Authentication: NSObject {

    func generateJWT() -> String? {
            struct Header: JWTPayload {
                enum CodingKeys: String, CodingKey {
                    case alg = "alg"
                    case type = "typ"
                }
                
            var alg = "RS256"
            var type: String = "JWT"
            
            func verify(using signer: JWTSigner) throws {
                //            print(self.expireTime > Date().timeIntervalSince1970)
                fatalError()
            }
        }
        
        struct Payload: JWTPayload {
            enum CodingKeys: String, CodingKey {
                case email = "iss"
                case scope = "scope"
                case aud = "aud"
                case createdAt = "iat"
                case expireTime = "exp"
            }
            
            var email: String = "XXXXX@XXXXXX.iam.gserviceaccount.com"
            var scope: String = "https://www.googleapis.com/auth/androidpublisher"
            var aud: String = "https://oauth2.googleapis.com/token"
            var createdAt: Double = Date().timeIntervalSince1970
            var expireTime: Double = Date().advanced(by: 1000).timeIntervalSince1970
            
            
            func verify(using signer: JWTSigner) throws {
                print(self.expireTime > Date().timeIntervalSince1970)
                fatalError()
            }
        }
        
        do {
            if let certificatePath = Bundle.main.path(forResource: "k_created", ofType: "pem") {
                let certificateUrl = URL(fileURLWithPath: certificatePath)
                let certififcateData = try Data(contentsOf: certificateUrl)
                let signers = JWTSigners()
                let key = try RSAKey.private(pem: certififcateData)
                signers.use(.rs256(key: key))
                
                //                MARK: HEADER NOT USED
                let header = Header()
                let payload = Payload()
                let jwt = try signers.sign(payload)
                //                let jwt = try signers.sign(payload)
                print("JWT: \(jwt)")
                return jwt
            } else {
                return nil
            }
        } catch {
            print(error)
            return nil
        }
    }
}

我做错了什么?还是我错过了一步?

EN

回答 1

Stack Overflow用户

发布于 2021-11-22 17:59:01

您似乎试图以查询参数的形式将访问令牌内联发送。您需要将其作为授权头发送。

代码语言:javascript
复制
curl \
  'https://androidpublisher.googleapis.com/androidpublisher/v3/applications/[PACKAGENAME]/reviews' \
  --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
  --header 'Accept: application/json' \
  --compressed

问题是你在做你应该做的access_token=\(auth)

代码语言:javascript
复制
request.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")

授权需要在头中,如上面所示,并且它需要是一个有效的访问令牌。

是否运行了针对验证端点创建的JWT,以确保其甚至有效。如果您的代码有效,您将是我10年来第一个在不使用客户端libray的情况下从服务帐户凭据中创建访问令牌的人。干得好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70070031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档