Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove use of deprecated GoogleCredential class #81

Merged
merged 1 commit into from
Dec 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,18 @@ Once you have completed those 3 steps, you should be able to integrate it in you
- This is how you can build your credentials from the json cert file you have downloaded:

```scala
import java.io.FileInputStream

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.gu.googleauth.GoogleServiceAccount
import org.apache.commons.io.Charsets.UTF_8
import org.apache.commons.io.IOUtils
import com.google.auth.oauth2.ServiceAccountCredentials

object GoogleAuthConf {
val impersonatedUser = ??? // read from config
}

private lazy val credentials: GoogleCredential = {
val fileInputStream = new FileInputStream("/path/to/your-service-account-cert.json")
GoogleCredential.fromStream(fileInputStream)
val impersonatedUser: String = ??? // read from config
val serviceAccountCert: String = ??? // JSON certificate from Google Developers Console - read from secure storage
}

private val serviceAccount = GoogleServiceAccount(
credentials.getServiceAccountId, // This should contain the *email address* that is associated with your service account
credentials.getServiceAccountPrivateKey, // This should contain the *private key* that is associated with your service account
GoogleAuthConf.impersonatedUser // This is the admin user email address we mentioned earlier
GoogleAuthConf.impersonatedUser, // This is the admin user email address we mentioned earlier
ServiceAccountCredentials.fromStream(IOUtils.toInputStream(serviceAccountCert, UTF_8))
)
```

Expand Down
8 changes: 4 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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`,
Expand Down
53 changes: 37 additions & 16 deletions play-v27/src/main/scala/com/gu/googleauth/groups.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.directory.{Directory, DirectoryScopes}
import com.google.auth.http.HttpCredentialsAdapter
import com.google.auth.oauth2.ServiceAccountCredentials

import scala.collection.JavaConverters._
import scala.concurrent._
Expand All @@ -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,
Expand All @@ -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 [email protected]), 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 '[email protected]'), 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 {
Expand Down
1 change: 1 addition & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ object Dependencies {
val googleDirectoryAPI = Seq(
"com.google.apis" % "google-api-services-admin-directory" % "directory_v1-rev20191003-1.30.8" exclude("com.google.guava", "guava-jdk5"),
"com.google.api-client" % "google-api-client" % "1.31.1", // https://app.snyk.io/vuln/SNYK-JAVA-COMGOOGLEOAUTHCLIENT-575276
"com.google.auth" % "google-auth-library-oauth2-http" % "0.22.0",
"com.google.guava" % "guava" % "30.0-jre"
)

Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version in ThisBuild := "2.0.3-SNAPSHOT"
version in ThisBuild := "2.1.0-SNAPSHOT"