如何使用服务帐户访问 Google Cloud Token Service API?

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

我正在尝试通过服务帐户使用此 API。

https://securetoken.googleapis.com/v1/token?key=[API_KEY]

参考: https://cloud.google.com/identity-platform/docs/use-rest-api#section-refresh-token

问题是,当我尝试使用从我的服务帐户生成的凭据调用它时,我一直遇到

403 FORBIDDEN
错误。

{"error"=>{"code"=>403, "message"=>"Request had insufficient authentication scopes.", "status"=>"PERMISSION_DENIED", "details"=>[{"@type"=>"type.googleapis.com/google.rpc.ErrorInfo", "reason"=>"ACCESS_TOKEN_SCOPE_INSUFFICIENT", "domain"=>"googleapis.com", "metadata"=>{"method"=>"google.identity.securetoken.v1.SecureToken.GrantToken", "service"=>"securetoken.googleapis.com"}}]}}

这是我检查过的。

  • 我的
    Token Service API
    已在我的 GCP 项目上启用。
  • 我的服务帐户具有
    owner
    角色。
  • 使用 API 密钥调用它时,使用 API 没有问题(但我想让它与服务帐户一起使用......)

这是我试图使其工作的代码。

      SCOPE = %w[
        https://www.googleapis.com/auth/firebase
        https://www.googleapis.com/auth/identitytoolkit
      ]
  
      def initialize
        decoded_service_account_json = Base64.decode64(ENV.fetch("GCP_JSON_KEYFILE_BASE64"))
        io = StringIO.new(decoded_service_account_json)
        @credentials = Google::Auth::DefaultCredentials.make_creds(scope: SCOPE, json_key_io: io)
      end

      # Exchange a refresh token for an ID token
      # References:
      #  - https://cloud.google.com/identity-platform/docs/reference/rest/v1/accounts/accounts/getIdpAuthentication
      def exchange_refresh_token(refresh_token)
        uri = URI.parse("https://securetoken.googleapis.com/v1/token")
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true

        request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/x-www-form-urlencoded' })
        request.body = URI.encode_www_form(
          'grant_type' => 'refresh_token',
          'refresh_token' => refresh_token
        )

        request.add_field('Authorization', @credentials.apply({})[:authorization])

        response = http.request(request)
        response_data = JSON.parse(response.body)

        if response.code.to_i == 200
          {
            id_token: response_data['id_token'],
            refresh_token: response_data['refresh_token'],
            expires_at: Time.now + response_data['expires_in'].to_i
          }
        else
          raise TokenExchangeError.new("Token exchange failed: #{response.code} - #{response_data['error_description']}")
        end
      end

你知道为什么它不起作用吗?或者也许

Token Service API
无法使用服务帐户?

提前谢谢您。

google-cloud-platform refresh-token google-identity-toolkit
1个回答
0
投票

我通过尝试和猜测找到了解决方案,因为文档没有提供任何有用的信息。

我需要在我的

https://www.googleapis.com/auth/securetoken
中添加
SCOPE
范围才能使用
https://securetoken.googleapis.com/v1/token

SCOPE = %w[
        https://www.googleapis.com/auth/firebase
        https://www.googleapis.com/auth/identitytoolkit
        https://www.googleapis.com/auth/securetoken
      ]
  
      def initialize
        decoded_service_account_json = Base64.decode64(ENV.fetch("GCP_JSON_KEYFILE_BASE64"))
        io = StringIO.new(decoded_service_account_json)
        @credentials = Google::Auth::DefaultCredentials.make_creds(scope: SCOPE, json_key_io: io)
      end

这完全是随机猜测...... 我在这里检查了所有可能的范围:https://developers.google.com/identity/protocols/oauth2/scopes

但是

https://www.googleapis.com/auth/securetoken
不是其中之一。即使 Google 搜索也不会返回
https://www.googleapis.com/auth/securetoken
范围的任何相关信息。

这真是令人沮丧。有人能告诉我是否有一种方法可以让我无需猜测就能找到解决方案?

https://www.googleapis.com/auth/securetoken
从哪里来?

© www.soinside.com 2019 - 2024. All rights reserved.