Skip to content

Commit 1d70d4f

Browse files
committed
Remove use of deprecated GoogleCredential class
This change is only related to the Google-Group-checking code in `play-googleauth`, which was using a deprecated class: The `com.google.api.client.googleapis.auth.oauth2.GoogleCredential` class in https://github.com/googleapis/google-api-java-client was deprecated in May 2019 by googleapis/google-api-java-client#1258 ...the deprecation advice recommends using the classes from the new library: https://github.com/googleapis/google-auth-library-java This commit switches to using the new `com.google.auth.oauth2.ServiceAccountCredentials` class from the `google-auth-library-oauth2-http` artifact. Given this new class, our custom `com.gu.googleauth.GoogleServiceAccount` Scala case class is no longer necessary, so has been deprecated, in favour of the user passing us an instance of `ServiceAccountCredentials` - which is actually easier for a user to generate! Here's an example of how you make and use an instance of the new credentials: ``` import org.apache.commons.io.Charsets.UTF_8 import org.apache.commons.io.IOUtils import com.google.auth.oauth2.ServiceAccountCredentials import com.gu.googleauth.GoogleGroupChecker val impersonatedUser: String = ... // email address of the 'impersonated' account val serviceAccountCert: String = ... // from Google Developers Console val credentials = ServiceAccountCredentials.fromStream(IOUtils.toInputStream(serviceAccountCert, UTF_8)) val groupChecker = new GoogleGroupChecker(impersonatedUser, credentials) ```
1 parent 0a5bcb2 commit 1d70d4f

3 files changed

Lines changed: 43 additions & 21 deletions

File tree

build.sbt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ val sonatypeReleaseSettings = Seq(
5050

5151
def projectWithPlayVersion(majorMinorVersion: String) =
5252
Project(s"play-v$majorMinorVersion", file(s"play-v$majorMinorVersion")).settings(
53-
scalaVersion := "2.12.10",
54-
53+
scalaVersion := "2.12.12",
54+
crossScalaVersions := Seq(scalaVersion.value, "2.13.4"),
5555
scalacOptions ++= Seq("-feature", "-deprecation"),
5656

5757
libraryDependencies ++= Seq(
@@ -65,8 +65,8 @@ def projectWithPlayVersion(majorMinorVersion: String) =
6565
sonatypeReleaseSettings
6666
)
6767

68-
lazy val `play-v27` = projectWithPlayVersion("27").settings(crossScalaVersions := Seq(scalaVersion.value, "2.13.1"))
69-
lazy val `play-v28` = projectWithPlayVersion("28").settings(crossScalaVersions := Seq(scalaVersion.value, "2.13.1"))
68+
lazy val `play-v27` = projectWithPlayVersion("27")
69+
lazy val `play-v28` = projectWithPlayVersion("28")
7070

7171
lazy val `play-googleauth-root` = (project in file(".")).aggregate(
7272
`play-v27`,

play-v27/src/main/scala/com/gu/googleauth/groups.scala

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package com.gu.googleauth
22

33
import java.security.PrivateKey
44

5-
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
65
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
76
import com.google.api.client.json.jackson2.JacksonFactory
87
import com.google.api.services.admin.directory.{Directory, DirectoryScopes}
8+
import com.google.auth.http.HttpCredentialsAdapter
9+
import com.google.auth.oauth2.ServiceAccountCredentials
910

1011
import scala.collection.JavaConverters._
1112
import scala.concurrent._
@@ -22,6 +23,7 @@ import scala.concurrent._
2223
* @param privateKey the Service Account's private key - from the P12 file generated when the Service Account was created
2324
* @param impersonatedUser the email address of the user the application will be impersonating
2425
*/
26+
@deprecated("Use com.google.auth.oauth2.ServiceAccountCredentials instead", "play-googleauth 2.1.0")
2527
case class GoogleServiceAccount(
2628
email: String,
2729
privateKey: PrivateKey,
@@ -35,25 +37,44 @@ case class GoogleServiceAccount(
3537
* doesn't seem to work?). The Service Account needs the following scope:
3638
* https://www.googleapis.com/auth/admin.directory.group.readonly
3739
*
38-
* You also need a separate domain user account (eg example@guardian.co.uk), which
39-
* will be 'impersonated' when making the calls.
40+
* So long as you have the Service Account certificate as a string, you can easily make
41+
* an instance of com.google.auth.oauth2.ServiceAccountCredentials like this:
42+
*
43+
* {{{
44+
* import org.apache.commons.io.Charsets.UTF_8
45+
* import org.apache.commons.io.IOUtils
46+
* import com.google.auth.oauth2.ServiceAccountCredentials
47+
*
48+
* val serviceAccountCert: String = ... // certificate from Google Developers Console
49+
* val credentials = ServiceAccountCredentials.fromStream(IOUtils.toInputStream(serviceAccountCert, UTF_8))
50+
* }}}
51+
*
52+
* @param impersonatedUser a separate domain-user account email address (eg 'example@guardian.co.uk'), the email address
53+
* of the user the application will be impersonating when making calls.
4054
*/
41-
class GoogleGroupChecker(directoryServiceAccount: GoogleServiceAccount) {
55+
class GoogleGroupChecker(impersonatedUser: String, serviceAccountCredentials: ServiceAccountCredentials) {
4256

43-
val directoryService = {
57+
@deprecated(
58+
"this constructor is deprecated, use the constructor accepting com.google.auth.oauth2.ServiceAccountCredentials instead",
59+
"play-googleauth 2.1.0"
60+
)
61+
def this(googleServiceAccount: GoogleServiceAccount) = {
62+
this(
63+
googleServiceAccount.impersonatedUser,
64+
ServiceAccountCredentials.newBuilder()
65+
.setPrivateKey(googleServiceAccount.privateKey)
66+
.setServiceAccountUser(googleServiceAccount.email)
67+
.build()
68+
)
69+
}
70+
71+
val directoryService: Directory = {
72+
val credentials = serviceAccountCredentials
73+
.createDelegated(impersonatedUser)
74+
.createScoped(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY)
4475
val transport = GoogleNetHttpTransport.newTrustedTransport()
4576
val jsonFactory = JacksonFactory.getDefaultInstance
46-
47-
val credential = new GoogleCredential.Builder()
48-
.setTransport(transport)
49-
.setJsonFactory(jsonFactory)
50-
.setServiceAccountId(directoryServiceAccount.email)
51-
.setServiceAccountUser(directoryServiceAccount.impersonatedUser)
52-
.setServiceAccountPrivateKey(directoryServiceAccount.privateKey)
53-
.setServiceAccountScopes(Seq(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY).asJava)
54-
.build()
55-
56-
new Directory.Builder(transport, jsonFactory, null).setHttpRequestInitializer(credential).build
77+
new Directory.Builder(transport, jsonFactory, new HttpCredentialsAdapter(credentials)).build
5778
}
5879

5980
def retrieveGroupsFor(userEmail: String)(implicit ec: ExecutionContext): Future[Set[String]] = for {

project/Dependencies.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ object Dependencies {
4646
val googleDirectoryAPI = Seq(
4747
"com.google.apis" % "google-api-services-admin-directory" % "directory_v1-rev118-1.25.0" exclude("com.google.guava", "guava-jdk5"),
4848
"com.google.api-client" % "google-api-client" % "1.30.10", // Required as it fixes https://github.com/googleapis/google-api-java-client/issues/1487
49-
"com.google.guava" % "guava" % "25.0-jre"
49+
"com.google.auth" % "google-auth-library-oauth2-http" % "0.22.0",
50+
"com.google.guava" % "guava" % "30.0-jre"
5051
)
5152

5253
}

0 commit comments

Comments
 (0)