You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Service account调用Google Directory API遇401 Unauthorized错误排查求助

Troubleshooting 401 Unauthorized with Google Directory API & Service Account (Java 8)

Hey there, let's break down why you're hitting that 401 error when calling .execute()—especially since direct API calls work. Here are the most common pitfalls and debugging steps to check:

1. Verify Domain-Wide Delegation (DWD) Permissions in Google Workspace Admin Console

First, double-check the core setup for domain-wide delegation:

  • Make sure you (as a Google Workspace admin) added your service account's Client ID to the Domain-wide Delegation list in the Admin Console.
  • Confirm the API scopes you added match exactly what your code is requesting. For user read access, it should be https://www.googleapis.com/auth/admin.directory.user.readonly (or the full write scope if needed). Typos or missing scopes here are a top culprit.
  • Wait 5-10 minutes after updating scopes—sometimes changes take time to propagate across Google's systems.

2. Ensure You're Impersonating a Valid Domain User

Domain-wide delegation requires your service account to impersonate a domain user with sufficient permissions (usually a Workspace admin, or a user granted Directory API access).

  • In your code, did you call setServiceAccountUser("admin@yourdomain.com") when building the credential? This is mandatory—without it, the service account can't act on behalf of your domain.
  • Confirm the impersonated user actually has access to the Directory API. Test logging into the Admin Console with that user and checking if they can view users manually.

3. Validate Service Account Key Configuration

  • Double-check that the key file (JSON or P12) you're loading in code belongs to the correct service account. It's easy to accidentally use a key from a different project or account.
  • For JSON keys, ensure your code loads it correctly (no file path errors, and the app has read permissions for the file). Example snippet for JSON keys:
    GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("path/to/service-account-key.json"))
        .createScoped(Collections.singleton(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY))
        .createDelegated("admin@yourdomain.com");
    

4. Check Google API Client Version Compatibility

You mentioned using google-api-client v1.x—older versions might have bugs with service account authentication.

  • Upgrade to the latest stable v1.x release (e.g., 1.35.0) to rule out version-specific issues.
  • Ensure all related dependencies (like google-oauth-client, google-api-services-admin-directory) are on compatible versions—mismatched versions can cause silent auth failures.

5. Compare Request Headers (Direct API vs. Client Library)

Since direct API calls work, compare the authorization headers between your direct request and the client library's request:

  • Use a tool like WireMock or Fiddler to capture the client library's HTTP request. Check if the Authorization header has a valid Bearer token.
  • If the token is missing or invalid, your credential setup is the problem. If the token exists, verify the scopes embedded in the token (you can decode it at jwt.io) match the ones you need.

6. Rule Out Workspace Restrictions

  • If you're using a trial Google Workspace account, some API features might be limited. Confirm your plan allows Directory API access.
  • Check if there are any org-wide policies in the Admin Console that restrict API access for service accounts.

Example Working Code Snippet

Here's a minimal, correct setup to reference:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.admin.directory.Directory;
import com.google.api.services.admin.directory.DirectoryScopes;
import com.google.api.services.admin.directory.model.Users;

import java.io.FileInputStream;
import java.util.Collections;

public class DirectoryApiExample {
    public static void main(String[] args) throws Exception {
        NetHttpTransport httpTransport = new NetHttpTransport();
        JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();

        GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("service-account-key.json"))
                .createScoped(Collections.singleton(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY))
                .createDelegated("admin@yourdomain.com"); // Critical line

        Directory directory = new Directory.Builder(httpTransport, jsonFactory, credential)
                .setApplicationName("Your App Name")
                .build();

        Directory.Users.List listRequest = directory.users().list();
        listRequest.setDomain("yourdomain.com");
        Users users = listRequest.execute(); // Should work if setup is correct
    }
}

内容的提问来源于stack exchange,提问作者Angel Cuenca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:14:46