diff --git a/build.sbt b/build.sbt index 32f694d..3929fc9 100644 --- a/build.sbt +++ b/build.sbt @@ -50,8 +50,8 @@ val sonatypeReleaseSettings = Seq( def projectWithPlayVersion(majorMinorVersion: String) = Project(s"play-v$majorMinorVersion", file(s"play-v$majorMinorVersion")).settings( - scalaVersion := "2.12.10", - + scalaVersion := "2.12.12", + crossScalaVersions := Seq(scalaVersion.value, "2.13.4"), scalacOptions ++= Seq("-feature", "-deprecation"), libraryDependencies ++= Seq( @@ -65,8 +65,8 @@ def projectWithPlayVersion(majorMinorVersion: String) = sonatypeReleaseSettings ) -lazy val `play-v27` = projectWithPlayVersion("27").settings(crossScalaVersions := Seq(scalaVersion.value, "2.13.1")) -lazy val `play-v28` = projectWithPlayVersion("28").settings(crossScalaVersions := Seq(scalaVersion.value, "2.13.1")) +lazy val `play-v27` = projectWithPlayVersion("27") +lazy val `play-v28` = projectWithPlayVersion("28") lazy val `play-googleauth-root` = (project in file(".")).aggregate( `play-v27`, diff --git a/play-v27/src/main/scala/com/gu/googleauth/groups.scala b/play-v27/src/main/scala/com/gu/googleauth/groups.scala index 2374beb..71c00a3 100644 --- a/play-v27/src/main/scala/com/gu/googleauth/groups.scala +++ b/play-v27/src/main/scala/com/gu/googleauth/groups.scala @@ -2,10 +2,11 @@ package com.gu.googleauth import java.security.PrivateKey -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport import com.google.api.client.json.jackson2.JacksonFactory import com.google.api.services.admin.directory.{Directory, DirectoryScopes} +import com.google.auth.http.HttpCredentialsAdapter +import com.google.auth.oauth2.ServiceAccountCredentials import scala.collection.JavaConverters._ import scala.concurrent._ @@ -22,6 +23,7 @@ import scala.concurrent._ * @param privateKey the Service Account's private key - from the P12 file generated when the Service Account was created * @param impersonatedUser the email address of the user the application will be impersonating */ +@deprecated("Use com.google.auth.oauth2.ServiceAccountCredentials instead", "play-googleauth 2.1.0") case class GoogleServiceAccount( email: String, privateKey: PrivateKey, @@ -35,25 +37,44 @@ case class GoogleServiceAccount( * doesn't seem to work?). The Service Account needs the following scope: * https://www.googleapis.com/auth/admin.directory.group.readonly * - * You also need a separate domain user account (eg example@guardian.co.uk), which - * will be 'impersonated' when making the calls. + * So long as you have the Service Account certificate as a string, you can easily make + * an instance of com.google.auth.oauth2.ServiceAccountCredentials like this: + * + * {{{ + * import org.apache.commons.io.Charsets.UTF_8 + * import org.apache.commons.io.IOUtils + * import com.google.auth.oauth2.ServiceAccountCredentials + * + * val serviceAccountCert: String = ... // certificate from Google Developers Console + * val credentials = ServiceAccountCredentials.fromStream(IOUtils.toInputStream(serviceAccountCert, UTF_8)) + * }}} + * + * @param impersonatedUser a separate domain-user account email address (eg 'example@guardian.co.uk'), the email address + * of the user the application will be impersonating when making calls. */ -class GoogleGroupChecker(directoryServiceAccount: GoogleServiceAccount) { +class GoogleGroupChecker(impersonatedUser: String, serviceAccountCredentials: ServiceAccountCredentials) { - val directoryService = { + @deprecated( + "this constructor is deprecated, use the constructor accepting com.google.auth.oauth2.ServiceAccountCredentials instead", + "play-googleauth 2.1.0" + ) + def this(googleServiceAccount: GoogleServiceAccount) = { + this( + googleServiceAccount.impersonatedUser, + ServiceAccountCredentials.newBuilder() + .setPrivateKey(googleServiceAccount.privateKey) + .setServiceAccountUser(googleServiceAccount.email) + .build() + ) + } + + val directoryService: Directory = { + val credentials = serviceAccountCredentials + .createDelegated(impersonatedUser) + .createScoped(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY) val transport = GoogleNetHttpTransport.newTrustedTransport() val jsonFactory = JacksonFactory.getDefaultInstance - - val credential = new GoogleCredential.Builder() - .setTransport(transport) - .setJsonFactory(jsonFactory) - .setServiceAccountId(directoryServiceAccount.email) - .setServiceAccountUser(directoryServiceAccount.impersonatedUser) - .setServiceAccountPrivateKey(directoryServiceAccount.privateKey) - .setServiceAccountScopes(Seq(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY).asJava) - .build() - - new Directory.Builder(transport, jsonFactory, null).setHttpRequestInitializer(credential).build + new Directory.Builder(transport, jsonFactory, new HttpCredentialsAdapter(credentials)).build } def retrieveGroupsFor(userEmail: String)(implicit ec: ExecutionContext): Future[Set[String]] = for { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 890572c..b0e32d7 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -46,7 +46,8 @@ object Dependencies { val googleDirectoryAPI = Seq( "com.google.apis" % "google-api-services-admin-directory" % "directory_v1-rev118-1.25.0" exclude("com.google.guava", "guava-jdk5"), "com.google.api-client" % "google-api-client" % "1.30.10", // Required as it fixes https://github.com/googleapis/google-api-java-client/issues/1487 - "com.google.guava" % "guava" % "25.0-jre" + "com.google.auth" % "google-auth-library-oauth2-http" % "0.22.0", + "com.google.guava" % "guava" % "30.0-jre" ) }