来自服务帐户和已安装的应用凭据的Google Task Queue身份验证

时间:2015-03-29 23:02:25

标签: google-app-engine google-api google-oauth google-api-client task-queue

摘要:使用已安装的(本机)应用程序凭据,我可以使用OAuth2和REST API v1beta2授权和使用拉取任务队列。这没关系,但我更愿意在服务帐户下授权和使用任务队列,因为使用已安装的应用凭据需要我在任务队列ACL中使用我自己的电子邮件地址(见下文)。但是,当我授权使用服务帐户(双方Oauth2)时,在将服务帐户电子邮件地址添加到队列ACL后,我使用队列获得权限错误。 有没有办法在本机客户端应用程序中使用服务帐户下的任务队列?

详细信息:我对使用电子邮件地址指定权限的任务队列ACL感到有点困惑 - 安装的应用凭据似乎没有相关的电子邮件地址。但是,当你第一次通过三足OAuth授权时,它基本上会使用你在浏览器中登录的任何谷歌帐户。因此,当我在队列ACL下包含我自己的电子邮件地址时,它可以正常工作:

queue:
- name: my-queue
  mode: pull
  acl:
  - user_email: my-email@example.com
  - writer_email: my-email@example.com

但是,如果我以相同的方式添加我的服务帐户电子邮件地址,并使用服务帐户进行授权,则会收到错误403:you are not allowed to make this api call

queue:
- name: my-queue
  mode: pull
  acl:
  - user_email: 12345-abcd@developer.gserviceaccount.com
  - writer_email: 12345-abcd@developer.gserviceaccount.com

我已经仔细检查了服务电子邮件地址是否正确,并尝试在queue.yaml文件中引用它,得到相同的错误。

这向我表明,由于某种原因,任务队列没有将我的授权与服务帐户电子邮件地址相关联。它不喜欢两条腿的OAuth,还是别的什么?

请注意,服务帐户授权本身 工作(下面的ruby代码),它是后续的API调用,并且显然ACL权限是直接的错误的原因。

# issuer == service account email address

def service_auth!(issuer, p12_file)
  key = Google::APIClient::KeyUtils.load_from_pkcs12(p12_file, 'notasecret')
  client.authorization = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
    :audience => 'https://accounts.google.com/o/oauth2/token',
    :scope => 'https://www.googleapis.com/auth/prediction',
    :issuer => issuer,
    :signing_key => key)
  client.authorization.fetch_access_token!

  api = client.discovered_api(TASKQUEUE_API, TASKQUEUE_API_VERSION)

  return client, api
end

1 个答案:

答案 0 :(得分:1)

我认为问题可能只是您的范围(' https://www.googleapis.com/auth/prediction')。

我可以使用服务帐户授权和调用TaskQueue API,而不会出现任何问题。我的例子是在Python中(抱歉,我不是Rubyist):

queue.yaml:

queue:
- name: pull
  mode: pull
  retry_parameters:
    task_retry_limit: 5
  acl:
  - user_email: 12345-abcd@developer.gserviceaccount.com
  - writer_email: 12345-abcd@developer.gserviceaccount.com

<强>源:

client_email = '12345-abcd@developer.gserviceaccount.com'

with open('service_account.p12', 'rb') as f:
  private_key = f.read()

credentials = SignedJwtAssertionCredentials(client_email, private_key,
    ['https://www.googleapis.com/auth/taskqueue',
     'https://www.googleapis.com/auth/taskqueue.consumer'])

http = httplib2.Http()
http = credentials.authorize(http)

api = build('taskqueue', 'v1beta2', http=http)   

# Do stuff with api ...