簡體   English   中英

Gmail API 服務帳戶 unauthorized_client 錯誤,即使具有全域權限

[英]Gmail API service account unauthorized_client error even with domain-wide authority

我已經廣泛閱讀了如何使用服務帳戶訪問 GCP Gmail API 並使用此處的說明授予它域范圍的權限:

https://support.google.com/a/answer/162106

這是我的服務帳戶:

在此處輸入圖像描述

這是添加到域范圍權限的范圍。 您可以看到該 ID 與服務帳戶匹配。

在此處輸入圖像描述

我注意到的一件事是我的 GCP 項目是一個內部項目,我沒有發布它或任何東西,但是當我添加 scope 時,它沒有顯示服務帳戶 email 名稱,而是顯示項目名稱。 這有什么區別嗎? 我需要在這里設置什么嗎? 在 OAuth 同意屏幕中,我看到項目名稱正在那里定義。 我也在此屏幕上添加了所有相同的 scope,不確定是否有任何區別。

在此處輸入圖像描述

這是我的代碼:

from google.oauth2 import service_account
from googleapiclient import discovery
credentials_file = get_credentials('gmail.json')
scopes = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.labels', 'https://www.googleapis.com/auth/gmail.modify']
credentials = service_account.Credentials.from_service_account_info(credentials_file, scopes=scopes)
delegated_credentials = credentials.with_subject("abc@mydomain.com")
GMAIL_SERVICE = discovery.build('gmail', 'v1', credentials=delegated_credentials)
labels = GMAIL_SERVICE.users().labels().list(userId='me').execute()

錯誤信息:

Google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any scopes requested.', {'error': 'unauthorized_client', 'error_description': '客戶端未授權使用此方法檢索訪問令牌,或者客戶端未授權請求的任何范圍。'})

不確定我能否准確回答原始問題(我認為不能),但在這里我開發的雲功能是如何完成的。 針對此答案編寫/采用了以下特定代碼片段,但未經過測試:

import os
import google.auth
import google.auth.iam
from google.oauth2 import service_account
from google.auth.exceptions import MutualTLSChannelError
from google.auth.transport import requests
import googleapiclient.discovery

from google.cloud import error_reporting

GMAIL_SERV_ACCOUNT = "A service account which makes the API CALL"
OAUTH_TOKEN_URI = "https://accounts.google.com/o/oauth2/token"
GMAIL_SCOPES_LIST = ["https://mail.google.com/"] # for example
GMAIL_USER = "User's email address, who's email we would like to access. abc@mydomain.com - from your question"

# inside the cloud function code:

    local_credentials, project_id = google.auth.default()
    local_credentials.refresh(requests.Request())

    signer = google.auth.iam.Signer(requests.Request(), local_credentials, GMAIL_SERV_ACCOUNT)
    delegate_credentials = service_account.Credentials(
        signer, GMAIL_SERV_ACCOUNT, OAUTH_TOKEN_URI, scopes=GMAIL_SCOPES_LIST, subject=GMAIL_USER)
    delegate_credentials.refresh(requests.Request())

    try:
        email_api_service = googleapiclient.discovery.build(
            'gmail', 'v1', credentials=delegate_credentials, cache_discovery=False)
    except MutualTLSChannelError as err:
        # handle it somehow, for example (stupid, artificial)
        ER = error_reporting.Client(service="my-app", version=os.getenv("K_REVISION", "0"))
        ER.report_exception()
        return 0

因此,我的想法是使用我的(或“本地”)雲功能的服務帳戶來創建專用服務帳戶的憑據(GMAIL_SERV_ACCOUNT - 在許多不同的“本地”服務帳戶下運行的許多不同的雲功能中使用); 然后使用該“委托”服務帳戶獲得 API 服務訪問權限。

我不記得 GMAIL_SERV_ACCOUNT 是否應該具有任何特定的 IAM 角色。 但我認為“本地”雲功能的服務帳戶應該為它獲取roles/iam.serviceAccountTokenCreator

更新:

關於 IAM 角色的一些說明。 在 terraform(我將它用於我的 CICD)中,對於給定的功能組件,它看起來是:

# this service account is an 'external' for the given functional component, 
# it is managed in another repository and terraform state file
# so we should get it at first 
data "google_service_account" "gmail_srv_account" {
 project    = "some project id"
 account_id = "actual GMAIL_SERV_ACCOUNT account"
}

# now we provide IAM role for that working with it
# where 'google_service_account.local_cf_sa' is the service account, 
# under which the given cloud function is running
resource "google_service_account_iam_member" "iam_token_creator_gmail_sa" {
 service_account_id = data.google_service_account.gmail_srv_account.name
 role               = "roles/iam.serviceAccountTokenCreator"
 member             = "serviceAccount:${google_service_account.local_cf_sa.email}"
 depends_on         = [
   google_service_account.local_cf_sa,
 ]
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM