【问题标题】:Error getting access token for service account: 401 Unauthorized when using Calendar API using service account获取服务帐户的访问令牌时出错:使用服务帐户使用日历 API 时出现 401 未授权
【发布时间】:2020-08-03 14:22:54
【问题描述】:

我有一个具有域范围委派设置的服务帐户,我正在尝试使用该服务帐户创建新帐户(google-api-services-admin-directory),然后添加一些预设日历(google-api-services-calendar) 到新创建的帐户。

我对目录 api 没有任何问题。我必须使用服务帐户创建一个委派(管理员)用户,并且所有 directory-api 调用都可以正常工作。

但是,我无法让 calendar-api 调用正常工作。

Java 依赖项:

compile group: 'com.google.auth', name: 'google-auth-library-oauth2-http', version:'0.20.0'
compile group: 'com.google.apis', name: 'google-api-services-admin-directory', version:'directory_v1-rev53-1.20.0'
compile group: 'com.google.apis', name: 'google-api-services-calendar', version:'v3-rev20200315-1.30.9'


Java 代码:

private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final List<String> SCOPES = 
Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER, DirectoryScopes.ADMIN_DIRECTORY_GROUP,
      CalendarScopes.CALENDAR);
private static final String CREDENTIALS_FILE_PATH = "config/google-service-account-credentials.json";
.....
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
sourceCredentials =
          ServiceAccountCredentials.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH));
sourceCredentials = (ServiceAccountCredentials) sourceCredentials.createScoped(SCOPES);

.....

GoogleCredentials targetCredentials = sourceCredentials.createDelegated("newuser@email");
  HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(targetCredentials);
  targetCredentials.refreshIfExpired();//Not sure if this is required. It didn't help though
  Calendar calendarService = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer).setApplicationName(MainApp.SERVICE_NAME).build();

  for (String calendarKey : listOfCalendars)) {
    CalendarListEntry cle = new CalendarListEntry();
    cle.setId(calendarKey);
    calendarService.calendarList().insert(cle).execute();//Fails with a 401
  }

堆栈跟踪:

Caused by: java.io.IOException: Error getting access token for service account: 401 Unauthorized
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:444)
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
at com.google.auth.oauth2.OAuth2Credentials.refreshIfExpired(OAuth2Credentials.java:174)
at myApp.GSuiteSDKHelper.updateDefaultCalendars(GSuiteSDKHelper.java:169)
... 65 more
Caused by: com.google.api.client.http.HttpResponseException: 401 Unauthorized
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:441)
... 68 mo

有趣的是,错误是间歇性的。重新部署后,我总是可以第一次尝试工作。之后,它是一个成功或失败。

  • 我确实将服务帐户添加到我尝试添加的日历中,并确保服务帐户是日历上的“所有者”。

【问题讨论】:

  • 自运行 API 调用以来,您是否更改了任何范围?您能否刷新令牌(即删除并生成新令牌)以确保这不是问题?此外,如果您尝试将日历 API 与该服务帐户独立使用而不使用目录 API,您是否能够调用日历 API?让我知道情况如何。谢谢!
  • 我没有改变范围。我的 Java 代码中有 3 个作用域,以及 Google 管理(安全)控制台中带有客户端 ID 的 API 访问列表。我正在使用服务帐户来运行 API,因此我没有手动存储/缓存任何令牌。我的理解是客户端库将在需要时(过期)刷新令牌,看起来这是问题的一部分。当您说没有目录 API 的日历 API 时,我是否应该也将范围更改为日历 API?谢谢!
  • 即使在 Java 以及 API 访问管理控制台中使用所有三个范围,如果我将 Java 代码限制为仅调用日历 API(而不是目录 API),我确实看到了成功.我确实注意到了几次 SocketException,但从未注意到 401。
  • 您好,您还有这个问题吗?如果是这种情况,如果您直接与目标用户进行身份验证(而不是通过服务帐户 DWD),您是否会遇到相同的错误?您确定该用户具有相应的管理员权限吗?
  • @icedek 你好。你设法解决了这个问题吗?

标签: google-cloud-platform google-calendar-api google-workspace google-client google-auth-library


【解决方案1】:

类似的事情发生在我身上,就我而言,我可以通过添加范围来解决它:"https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 2018-10-20
    • 2014-09-08
    • 2018-09-03
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    相关资源
    最近更新 更多