26

I'd been employing the following Java method to set a bucket notification in GCS.

private void setBucketNotification(String bucketName, String topicId) {

List<String> eventType = new ArrayList<>();
eventType.add("OBJECT_FINALIZE");

try {
  Notification notification = new Notification();
  notification.setTopic(topicId);
  notification.setEventTypes(eventType);
  notification.setPayloadFormat("JSON_API_V1");

  final GoogleCredential googleCredential = GoogleCredential
      .fromStream(Objects.requireNonNull(classloader.getResourceAsStream("Key.json")))
      .createScoped(Collections.singletonList(StorageScopes.DEVSTORAGE_FULL_CONTROL));  

  final com.google.api.services.storage.Storage myStorage = new com.google.api.services.storage.Storage.Builder(
      new NetHttpTransport(), new JacksonFactory(), googleCredential).build();

  Notification v = myStorage.notifications().insert(bucketName, notification).execute();

} catch (IOException e) {
  log.error("Caught an IOException {}",e);
  }
}

It's been working fine so far, but lately, I'm getting a complaint regarding the deprecation of GoogleCredential class, and tried doing some research with a hope to find a possible replacement, but couldn't find anything. Can anyone help me point in the right direction?

Roshan Upreti
  • 1,782
  • 3
  • 21
  • 34
  • Where are you seeing that `GoogleCredential` is deprecated? – John Hanley Sep 17 '19 at 18:38
  • perhaps you need to change the library you're using? google-auth-library-java or com.google.apis:google-api-services-oauth2:v1-rev155-1.25.0 – Puttzy Sep 18 '19 at 03:21
  • @JohnHanley The same place where it's being initialized. – Roshan Upreti Sep 18 '19 at 05:16
  • Please include the exact message in your question. My builds do not show a deprecated message. Which Java version and JDK are you using? – John Hanley Sep 18 '19 at 05:40
  • 1
    @JohnHanley It Just said that 'com.google.api.client.googleapis.auth.oauth2.GoogleCredential is deprecated'. I don't know how exact and clear I could be apart from this. I'm using java version "1.8.0_212". – Roshan Upreti Sep 18 '19 at 06:29
  • If my answer helped you, could you accept it, so it gains greater visibility for other community users? Thanks @RoshanUpreti – sllopis Sep 18 '19 at 07:24

4 Answers4

50

After a while of looking around, I managed to fix it, using GoogleCredentials and HttpRequestInitializer. The code changes are as follows.

final GoogleCredential googleCredential = GoogleCredential
  .fromStream(Objects.requireNonNull(classloader.getResourceAsStream("Key.json")))
  .createScoped(Collections.singletonList(StorageScopes.DEVSTORAGE_FULL_CONTROL));

final com.google.api.services.storage.Storage myStorage = new com.google.api.services.storage.Storage.Builder(
      new NetHttpTransport(), new JacksonFactory(), googleCredential).build();

becomes

final GoogleCredentials googleCredentials = serviceAccountCredentials
                    .createScoped(Collections.singletonList(StorageScopes.DEVSTORAGE_FULL_CONTROL));
            HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(googleCredentials);        

final com.google.api.services.storage.Storage myStorage = new com.google.api.services.storage.Storage.Builder(
                new NetHttpTransport(), new JacksonFactory(), requestInitializer).build();
Roshan Upreti
  • 1,782
  • 3
  • 21
  • 34
  • 2
    Thanks, @Roshan! The tricky part for me was how to get the `HttpRequestInitializer` from the `GoogleCredentials`; googling for it brought me here :) – Tom Apr 23 '20 at 22:07
  • 2
    How do you get the service account credentials using a p12 private key file? – insa_c Apr 25 '20 at 06:08
  • 2
    @insa_c Why don't you use the `json` file with `ServiceAccountCredentials`, like this: `ServiceAccountCredentials.fromStream(Objects.requireNonNull(classloader.getResourceAsStream("Key.json"))) .createScoped(Collections.singletonList(StorageScopes.DEVSTORAGE_FULL_CONTROL));` – Roshan Upreti Jun 15 '20 at 13:15
  • 1
    `HttpCredentialsAdapter` is all I needed, thanks! – Risal Fajar Amiyardi May 10 '21 at 15:12
  • Awesome! Curious to know how you figured out the `HttpCredentialsAdapter` constructor part... – Satyam Raj Sep 14 '22 at 09:09
12

You can find an alternative solution as being posted on the Google APIs Github repository commits.

Please use Google Auth Library for Java for handling Application Default Credentials and other non-OAuth2 based authentication.

Explicit Credential Loading sample code:

To get Credentials from a Service Account JSON key use GoogleCredentials.fromStream(InputStream) or GoogleCredentials.fromStream(InputStream, HttpTransportFactory). Note that the credentials must be refreshed before the access token is available.

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("/path/to/credentials.json"));
credentials.refreshIfExpired();
AccessToken token = credentials.getAccessToken();
// OR
AccessToken token = credentials.refreshAccessToken();
sllopis
  • 2,292
  • 1
  • 8
  • 13
  • 2
    this is a link-only answer - even though it provides the proper information i strongly would hope you could add an example on how to use the api (-1) – Martin Frank Mar 12 '20 at 09:46
  • Hey @MartinFrank. You are totally right. Hyperlinks can be modified or broken. It's always best practice to add some example code or text to further explain. It's been quite some time since I posted this answer. It was during my Stackoverflow beginnings, and I was not aware of such things. Please bear with me on this one. Thanks for pointing it out. – sllopis Mar 12 '20 at 09:53
  • i'll provide right now an answer - but i would certainly remove my -1 if you change your answer (at least slightly) – Martin Frank Mar 12 '20 at 09:54
  • @MartinFrank Perfect! I believe my edited answer now provides a basic example of Credential Loading and how deprecated `GoogleCredential` class changed into `GoogleCredentials` Thanks. – sllopis Mar 12 '20 at 10:01
  • While this answer shows some ways to work with `GoogleCredentials`, it does **not** show how to obtain an `HttpRequestInitializer` from it, which is what's necessary in order to use it as a replacement for the deprecated `GoogleCredential` in the code in the question (and which is explained in @Roshan's answer). – Tom Apr 23 '20 at 22:11
  • When `GoogleCredential` from `com.google.api.client.googleapis.auth.oauth2` works with the Firebase API, `GoogleCredentials` from `com.google.auth.oauth2` doesn't. It seems that they aren't exactly equivalent. – didil May 02 '20 at 12:05
  • `com.google.api.client.googleapis.auth.oauth2.GoogleCredential.Builder` has `setServiceAccountUser(String serviceAccountUser)` which sets the email address of the user the application is trying to impersonate, but `com.google.auth.oauth2.GoogleCredentials` doesn't. Please somebody share an example how to do impersonation with this new `GoogleCredentials` – Denis Jan 22 '21 at 21:18
3

I had to solve similar task when using Google Admin SDK API and
com.google.api.services.admin.directory.Directory was needed.

    final ServiceAccountCredentials serviceAccountCredentials = ServiceAccountCredentials.fromPkcs8(
            clientId,
            clientEmail,
            serviceAccountPkcs8Key,
            serviceAccountPkcs8Id,
            Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY));
    final GoogleCredentials delegatedCredentials = serviceAccountCredentials.createDelegated(delegatedUserEmail);
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(delegatedCredentials);

    Directory directory = new Directory.Builder(httpTransport, JSON_FACTORY, requestInitializer)
            .setApplicationName(applicationName)
            .build();

Denis
  • 759
  • 1
  • 9
  • 22
2

Use google-auth-library-oauth2-http library

Code:

ServiceAccountCredentials getServiceAccountCredentials(String privateKeyJson) 
throws IOException {
   try (InputStream stream = new ByteArrayInputStream(privateKeyJson.getBytes())) {
      return ServiceAccountCredentials.fromStream(stream);
   }
}
ServiceAccountCredentials serviceAccountCredentials = getServiceAccountCredentials(privateKeyJson);
String privateKeyId = serviceAccountCredentials.getPrivateKeyId();
RSAPrivateKey key = (RSAPrivateKey)  serviceAccountCredentials.getPrivateKey();
rrc
  • 61
  • 1
  • 4