Google服务帐户无法模拟GSuite用户

Google服务帐户无法模拟GSuite用户

问题描述:

from google.oauth2 import service_account
import googleapiclient.discovery

SCOPES = ['https://www.googleapis.com/auth/calendar']
SERVICE_ACCOUNT_FILE = 'GOOGLE_SECRET.json'

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

delegated_credentials = credentials.with_subject('address@example.com')

google_calendar = googleapiclient.discovery.build('calendar', 'v3', credentials=delegated_credentials)

events = google_calendar.events().list(
    calendarId='address@example.com',
    maxResults=10
).execute()

上述代码的结果为:

google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.', '{\n  "error" : "unauthorized_client",\n  "error_description" : "Client is unauthorized to retrieve access tokens using this method."\n}')

Domain-wide delegation已打开.已在GSuite中使用适当的范围授权了服务帐户客户ID.

Domain-wide delegation is on. The service account client ID is authorized with the appropriate scopes in GSuite.

该服务帐户可用于普通凭据.它仅不适用于委托凭证.

The service account works for normal credentials. It only doesn't work for delegated credentials.

我在我们的域中尝试了不同的API(作用域)和不同的用户.

I've tried different APIs (scopes) and different users in our domain.

我有一位同事试图从头开始编写一个样本,他得到了同样的东西.

I had a colleague try to code up a sample from scratch and he got the same thing.

我认为您的问题是,在致电

I think you're problem is that your not authorising your credentials before making the call to the Calendar API but there is a couple of differences that you have that I use in my own implementation

  • 使用以下导入语句from oauth2client.service_account import ServiceAccountCredentialsfrom apiclient import discovery
  • 使用from_json_keyfile_name方法
  • 授权凭据,并在构建服务时将其作为http参数传递
  • Use the following import statements from oauth2client.service_account import ServiceAccountCredentials and from apiclient import discovery
  • Use the from_json_keyfile_name method
  • Authorize the credentials and pass it as a http argument when building the service

尝试对您的代码进行此修改:

Try this modification to your code:

from apiclient import discovery
from oauth2client.service_account import ServiceAccountCredentials
import httplib2

SCOPES = ['https://www.googleapis.com/auth/calendar']
SERVICE_ACCOUNT_FILE = 'GOOGLE_SECRET.json'

credentials = ServiceAccountCredentials.from_json_keyfile_name(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

# Use the create_delegated() method and authorize the delegated credentials
delegated_credentials = credentials.create_delegated('address@example.com')  
delegated_http = delegated_credentials.authorize(httplib2.Http())
google_calendar = discovery.build('calendar', 'v3', http=delegated_http)

events = google_calendar.events().list(
    calendarId='address@example.com',
    maxResults=10
).execute()

我还建议您在API调用中设置calendarId='primary',以便始终返回当前为其委派了凭据的用户的主日历.

I would also suggest setting calendarId='primary' in your API call so that you always return the primary calendar of the user who you currently have delegated credentials for.

有关使用ServiceAccountCredentials进行身份验证的更多信息,请参见以下链接: http://oauth2client.readthedocs.io/en/latest/source/oauth2client.service_account.html

For more information on authenticating using ServiceAccountCredentials see the following link: http://oauth2client.readthedocs.io/en/latest/source/oauth2client.service_account.html