2013-01-07 24 views
8

Google API(バージョンgoogle-oauth-java-client-1.12.0-beta)を使用しています。 OAuth2アクセストークンを取得しましたが、 "invalid_grant"が戻ってきました。 参考:ここでhttps://developers.google.com/accounts/docs/OAuth2ServiceAccountGoogle APIを使用してトークンを取得できません[google-oauth-java-client-1.12.0-beta]

はコードです:

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 = "[email protected]"; 
    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(); 
    } 
} 

結果:

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) 

ここでの問題は何ですか?どんなヒントも高く評価されます。

答えて

7

GoogleサービスとGoogle APIクライアントライブラリでサービスアカウントを使用する場合は、読み取り専用のユーティリティクラスが存在するため、署名を作成してJWTトークンを作成する必要はありません。 OAuth 2.0

ただし、詳細な説明と複数のプログラミング言語のコードサンプルが含まれているGoogleドライブのドキュメントを除き、これはあまり詳しく説明されていません。あなたは読んでください: https://developers.google.com/drive/service-accounts#google_apis_console_project_service_accounts

いくつかの問題を自分のコードで:

  • サービスアカウントのIDを形にする必要があります:<some-id>@developer.gserviceaccount.comは(はい、私はそれが奇妙な代わりに、クライアントIDのメールを知っています)
  • Google Apps domain Wide delegationを実行するときにはprincipalを設定するだけですが、Gmailアカウントではできません。あなたのケースでは管理者がドメインにアクセス権を付与したGoogle Appsアカウントでのみ設定できます。

以下は、JavaのOAuth 2.0 w/Serviceアカウントのコードサンプルです。

注:the URL Shortener libraryもダウンロードする必要があります。

/** 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; 
} 
+1

adsenseを使用しているときにこの「invalid_grant」例外が引き続き発生しています。クライアントIDは有効で、スコープはAdSenseScopes.ADSENSEです。 AdSense Management APIが有効になっています。それを修正する手がかりがない – user12384512

+0

私はNodeJSラッパーで作業しても非常に役に立ちます。私の問題は、アプリケーションの電子メールアドレスの代わりにアカウントの電子メールを使用したことでした。ありがとう! –

+0

すてきな答え!私はGoogleスプレッドシートJava APIにJWTエラーを受け取りました。あなたの答えを反映するために私の資格情報を交換したときに、私は今、私はあなたの答えを反映するために私の資格情報を交換しました。 GoogleスプレッドシートAPIを使用してプライベートにリクエストを送信します。 また、シートで作業する場合は、サービスアカウントの電子メールアドレス(ダウンロードしたjsonキー/ IDファイル)のプライベートシート(共有ボタン経由)のアクセス許可を確認してください。 – ganta

関連する問題