What is the alternative to the deprecated 'GoogleCredential'?
Asked Answered
P

4

31

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?

Plating answered 17/9, 2019 at 10:45 Comment(6)
Where are you seeing that GoogleCredential is deprecated?Interpret
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.0Littman
@JohnHanley The same place where it's being initialized.Plating
Please include the exact message in your question. My builds do not show a deprecated message. Which Java version and JDK are you using?Interpret
@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".Plating
If my answer helped you, could you accept it, so it gains greater visibility for other community users? Thanks @RoshanUpretiHunk
P
60

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();
Plating answered 17/9, 2019 at 12:29 Comment(6)
Thanks, @Roshan! The tricky part for me was how to get the HttpRequestInitializer from the GoogleCredentials; googling for it brought me here :)Sunup
How do you get the service account credentials using a p12 private key file?Merridie
@Merridie 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));Plating
HttpCredentialsAdapter is all I needed, thanks!Stoush
Awesome! Curious to know how you figured out the HttpCredentialsAdapter constructor part...Courtmartial
Worked quite well even after two years of last comment.Vestal
H
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();
Hunk answered 17/9, 2019 at 11:54 Comment(7)
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)Worn
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.Hunk
i'll provide right now an answer - but i would certainly remove my -1 if you change your answer (at least slightly)Worn
@MartinFrank Perfect! I believe my edited answer now provides a basic example of Credential Loading and how deprecated GoogleCredential class changed into GoogleCredentials Thanks.Hunk
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).Sunup
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.Stouthearted
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 GoogleCredentialsIconostasis
I
4

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();

Iconostasis answered 25/1, 2021 at 13:58 Comment(0)
D
3

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();
Dreary answered 29/12, 2020 at 16:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.