9

I have an application in GAE and I'm using a service account to call some google services. When I created a service account in the dashboard, a JSON key was provided to me. The content of the json is something like this:

{
  "private_key_id": "bar-foo",
  "private_key": "-----BEGIN PRIVATE KEY-----foo-bar\n-----END PRIVATE KEY-----\n",
  "client_email": "foo-bar@developer.gserviceaccount.com",
  "client_id": "bar-foo.apps.googleusercontent.com",
  "type": "service_account"
}

How can I use this private_key in my java code to generate a GoogleCredential object?

I was able to do that using the setServiceAccountPrivateKeyFromP12File method but for that I would need to create a p12 file and have it stored somewhere. With the json private key I could have it configured in my properties file.

I found a setServiceAccountPrivate method in the GoogleCredential.Builder that receives a PrivateKey object as parameter but I don't know how to generate this object from the value inside the json. All examples that I found were using the p12 file.

Luiz Guilherme
  • 1,601
  • 21
  • 37

2 Answers2

4

Since this question is still getting views and doesn't have an accepted answer, here is an example of how to use a JSON key with the Google API Client Library slightly adapted from the official documentation section 'Using OAuth 2.0 with the Google API Client Library for Java':

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
...
// Build service account credential.

GoogleCredential credential = GoogleCredential.fromStream(MyClass.class.getResourceAsStream("/MyProject-1234.json"))
    .createScoped(Collections.singleton(PlusScopes.PLUS_ME));
  // Set up global Plus instance.
  plus = new Plus.Builder(httpTransport, jsonFactory, credential)
      .setApplicationName(APPLICATION_NAME).build();

You would place your keyfile eg. 'MyProject-1234.json' into /src/main/resources and 'MyClass' above refers to the name of the parent class containing your method.

Adam
  • 5,697
  • 1
  • 20
  • 52
  • Where do you put "MyProject-1234.json" in your project structure? – ashughes Mar 15 '16 at 02:53
  • I realized that sample only contained a generic file reading example so I edited my answer to include a way that works on App Engine. This will actually work on any servlet application and there are other ways to do it as well eg. putting it under 'WEB-INF' and using getServletContext().getResourceAsStream("/WEB-INF/MyProject-1234.json"). – Adam Mar 18 '16 at 18:31
  • wouldn't putting the private key file under WEB-INF pose a security concern? – Johnny Wu Mar 25 '16 at 18:23
  • WEB-INF isn't part of the public document tree and should never be served to clients, however for the paranoid (myself included) I'd recommend sticking with /src/main/resources. I'm mentioning it for completeness though as it is as supported way of reading a file resource in GAE. – Adam Mar 25 '16 at 19:06
  • fromStream method is not visible – gagangupt16 Jul 15 '16 at 11:33
  • I get Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found { "code" : 404, "errors" : [ { "domain" : "global", "message" : "Domain not found.", "reason" : "notFound" } ], "message" : "Domain not found." } – Nicholas DiPiazza Jul 27 '17 at 20:39
-1

You should use the builtin service account that GAE makes on your behalf when you create a project. You can see an example of how to use it here: https://developers.google.com/bigquery/authorization#service-accounts-appengine

You can find more about service account from other questions here on SO: https://stackoverflow.com/a/24478017/700188 (its for python but there should be a corresponding java article)

EDIT:

Here is an article on the Google AppEngine documentation for using the built in service account identity to communicate with Google's APIs:

https://developers.google.com/appengine/docs/java/appidentity/#Java_Asserting_identity_to_Google_APIs

There's no need to make a separate service account for use with GAE as there's already one provided to you.

EDIT 2

Not sure if the private key in the JSON file is the same one in the p12 file, but if its you can try something like (sorry, my Java may be a bit rusty):

import com.google.api.client.util.SecurityUtils;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.PrivateKey;
// Read the JSON Private key as a byte[] array into bytes
PrivateKey serviceAccountPrivateKey = SecurityUtils.getRsaKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes));
Community
  • 1
  • 1
someone1
  • 3,570
  • 2
  • 22
  • 35
  • Not sure if we are talking about the samething here. – Luiz Guilherme Jul 16 '14 at 13:10
  • Are you trying to access Google's APIs you enabled via the Cloud Console from your GAE application? – someone1 Jul 16 '14 at 19:10
  • Yes, I am using the Google's APIs I enabled via console. – Luiz Guilherme Jul 16 '14 at 19:57
  • Then I think you should use the Service Account you get with your GAE app so you don't have to worry about things like JSON and P12 files. – someone1 Jul 16 '14 at 23:18
  • Yeah. But my case is not that simple. For some reasons specific reasons of my scenario, I need to use a Service Account that is not in my own project. The service account I'm using belongs to another project. – Luiz Guilherme Jul 17 '14 at 11:23
  • 1
    You can add your GAE App's Service account to the other project via the "Permissions" menu in the Cloud Console for that project. Your service account should be in the form of `your_app_id@appspot.gserviceaccount.com` – someone1 Jul 17 '14 at 13:01
  • Nice, I will try that. – Luiz Guilherme Jul 17 '14 at 13:03
  • Does not work for a vanilla private Service Account JSON file: `"java.security.InvalidKeyException" DerInputStream.getLength(): lengthTag=127, too big.` – 8bitjunkie Nov 06 '15 at 15:37