简体   繁体   English

无法使用Google API [google-oauth-java-client-1.12.0-beta]获取服务帐户流的令牌

[英]Unable to get token using Google APIs [google-oauth-java-client-1.12.0-beta] for service account flow

I am using Google APIs (version google-oauth-java-client-1.12.0-beta) to get a OAuth2 access token but got back "invalid_grant". 我使用Google API(版本为google-oauth-java-client-1.12.0-beta)来获取OAuth2访问令牌但返回“invalid_grant”。 Ref: https://developers.google.com/accounts/docs/OAuth2ServiceAccount 参考: https//developers.google.com/accounts/docs/OAuth2ServiceAccount

Here is the code: 这是代码:

import com.google.api.client.auth.jsontoken.JsonWebSignature;
import com.google.api.client.auth.jsontoken.JsonWebToken;
import com.google.api.client.auth.jsontoken.RsaSHA256Signer;
import com.google.api.client.auth.oauth2.TokenRequest;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Clock;

import java.io.FileInputStream;
import java.io.IOException;

import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;


public class TestClient
{
  private static PrivateKey getPrivateKey(String keyFile, String alias, String password)
    throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException
  {
    KeyStore keystore = KeyStore.getInstance("PKCS12");
    keystore.load(new FileInputStream(keyFile), password.toCharArray());
    PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, password.toCharArray());

    return privateKey;
  }

  public static void main(String[] args)
    throws GeneralSecurityException, IOException
  {
    String password = "notasecret";
    String alias = "privatekey";
    String keyFile = "<private key file>.p12";
    String serviceAccountScopes = "https://www.googleapis.com/auth/urlshortener";
    String serviceAccountUser = "user1@gmail.com";
    String serviceAccountId = "<a/c id>.apps.googleusercontent.com";
    JsonWebSignature.Header header = new JsonWebSignature.Header();
    header.setAlgorithm("RS256");
    header.setType("JWT"); 

    JsonWebToken.Payload payload = new JsonWebToken.Payload(Clock.SYSTEM);
    long currentTime = Clock.SYSTEM.currentTimeMillis();
    payload.setIssuer(serviceAccountId)
       .setAudience("https://accounts.google.com/o/oauth2/token")
       .setIssuedAtTimeSeconds(currentTime / 1000)
       .setExpirationTimeSeconds(currentTime / 1000 + 3600)
       .setPrincipal(serviceAccountUser);
    payload.put("scope", serviceAccountScopes); 
    System.out.println(payload.toPrettyString());

    PrivateKey serviceAccountPrivateKey = getPrivateKey(keyFile, alias, password);
    String assertion = RsaSHA256Signer.sign(serviceAccountPrivateKey, getJsonFactory(), header, payload);     
    TokenRequest request = new TokenRequest(getTransport(), getJsonFactory(), new GenericUrl(getTokenServerEncodedUrl()), "assertion");     

    request.put("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");     
    request.put("assertion", assertion);     
    TokenResponse resp = request.execute();    
    System.out.println("token : " + resp.getAccessToken());
  }

  private static String getTokenServerEncodedUrl()
  {
    return "https://accounts.google.com/o/oauth2/token";
  }

  private static JsonFactory getJsonFactory()
  {
    return new JacksonFactory();
  }

  private static HttpTransport getTransport()
  {
    return new NetHttpTransport();
  }
}

Result: 结果:

Exception in thread "main" com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "invalid_grant"
}
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)

What is the problem here? 这里有什么问题? any hint would be appreciated. 任何暗示将不胜感激。

When using Service Accounts on Google Services and the Google APIs Client library you don't have to create the signature and construct the JWT Token by yourself as there are read-to-use utility classes to simply perform Service accounts authorization via OAuth 2.0. 在Google服务和Google API客户端库上使用服务帐户时,您不必自己创建签名并构建JWT令牌,因为有读取使用的实用程序类只需通过OAuth 2.0执行服务帐户授权。

However this is not very well documented except on the Google Drive documentation which contains detailed explanation and code samples in multiple programming languages. 但是,除了Google Drive文档中包含多种编程语言的详细说明和代码示例之外,这一点并没有得到很好的记录。 You should read: https://developers.google.com/drive/service-accounts#google_apis_console_project_service_accounts 您应该阅读: https//developers.google.com/drive/service-accounts#google_apis_console_project_service_accounts

Some issues with your code: 您的代码存在一些问题:

  • The ID of the service account should be in the form: <some-id>@developer.gserviceaccount.com (yes the email instead of the Client ID, I know it's weird) 服务帐户的ID应采用以下格式: <some-id>@developer.gserviceaccount.com (是的是电子邮件而不是客户端ID,我知道这很奇怪)
  • You only set the principal when doing Google Apps domain Wide delegation but you can't do that on Gmail accounts of course, only on Google Apps accounts whose domain you have been granted access to by an administrator so in your case: don't set it. 您只能在执行Google Apps域广泛授权时设置principal ,但当然不能在Gmail帐户上执行此操作,仅限于您的域已被管理员授予访问权限的Google Apps帐户,因此在您的情况下:请勿设置它。

Below is the code sample for OAuth 2.0 w/ Service accounts in Java. 下面是使用Java的OAuth 2.0 w / Service帐户的代码示例。

Note: You'll also need to download the URL Shortener library . 注意:您还需要下载URL Shortener库

/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "<some-id>@developer.gserviceaccount.com";

/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/path/to/<public_key_fingerprint>-privatekey.p12";

/**
 * Build and returns a URL Shortner service object authorized with the service accounts.
 *
 * @return URL Shortner service object that is ready to make requests.
 */
public static Drive getDriveService() throws GeneralSecurityException, IOException, URISyntaxException {
  HttpTransport httpTransport = new NetHttpTransport();
  JacksonFactory jsonFactory = new JacksonFactory();
  GoogleCredential credential = new GoogleCredential.Builder()
      .setTransport(httpTransport)
      .setJsonFactory(jsonFactory)
      .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
      .setServiceAccountScopes(UrlshortenerScopes.URLSHORTENER)
      .setServiceAccountPrivateKeyFromP12File(
          new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
      .build();
  Urlshortener service = new Urlshortener.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential).build();
  return service;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Java中的OAuth 2.0服务帐户的Google电子邮件设置API - Google Email Settings api using OAuth 2.0 service account in java 用于获取访问令牌的Google oauth java客户端失败,并显示“400 Bad Request {”error“:”invalid_request“}” - Google oauth java client to get an access token fails with “400 Bad Request { ”error“ : ”invalid_request“ }” 用于获取访问令牌的Google oauth java客户端失败,并显示“400 Bad Request {”error“:”invalid_request“}” - Google oauth java client to get an access token fails with “400 Bad Request { ”error“ : ”invalid_request“ }” google oauth2 如何获取服务帐户的私钥 - google oauth2 how to get private key for service account google-oauth-java-client-强制访问令牌默认生存期 - google-oauth-java-client - Force access token default lifetime 如何使用gcloud或Google Cloud Java SDK生成oauth令牌,客户端ID和密码 - How to generate oauth token, client id and secret using gcloud or Google Cloud Java SDK Google Appengine oauth令牌指向错误的帐户 - Google Appengine oauth token points to the wrong account 如何使用 fabric8 java 客户端获取 kubernetes 服务帐户访问令牌? - How to get kubernetes service account access token using fabric8 java client? 在使用服务帐户进行身份验证时,使用Google Drive API创建文件会转到哪个帐户? - Creating files go to which account using Google Drive APIs when authenticating with a service account? 使用用户名,密码和client_id从Google API OAuth获取id_token-无需client_secret - Get id_token from Google API OAuth using username, password, client_id - without client_secret
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM