Auth once example

First we need to import everthing that we need.

import java.time.Instant
import cats.effect._
import io.github.jkobejs.google.oauth4s.ServerToServer
import io.github.jkobejs.google.oauth4s.ServiceAccountKeyReader
import scala.concurrent.ExecutionContext.Implicits.global

We will use cats.effect.IO effect wrapper to make our computation pure. To be able to use it we need to create context shift and timer which are need for shifting execution and scheduling of tasks.

implicit val ctx = IO.contextShift(global)
// ctx: ContextShift[IO] = cats.effect.internals.IOContextShift@41fd8e05
implicit val timer = IO.timer(global)
// timer: Timer[IO] = cats.effect.internals.IOTimer@19c49569

To communicate with google auth api we need to create claims and settings. We can do it in two ways, create them manually (private key should we read in a safe way) or read service account key data from google service account key file and use it to create settings.

Let’s first do it manually.

{
  val privateKey = "sample-private-key" // read it in a safe way
  val clientEmail = "sample@email.iam.gserviceaccount.com"
  val url = "https://www.googleapis.com/oauth2/v4/token"
  val scope = "https://www.googleapis.com/auth/devstorage.read_write"
  
  val claims = ServerToServer.GoogleClaims(
    issuer = clientEmail,
    scope = scope,
    audience = url,
    expiration = Instant.now().plusSeconds(3600),
    issuedAt = Instant.now()
  )
  
  val settings = ServerToServer.Settings(
    uri = "https://www.googleapis.com/oauth2/v4/token",
    privateKey = privateKey,
    grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer",
    claims = claims
  )
  
  ServerToServer.auth[IO](settings, global)
}
// res0: IO[ServerToServer.AuthResponse] = Async(
//   cats.effect.internals.IOBracket$$$Lambda$7711/1364152185@57b1da94,
//   false
// )

Now lets see how to use ServiceAccountKey.

for {
  serviceAccountKey <- ServiceAccountKeyReader.readServiceAccountKey[IO]("src/test/resources/service-account.json", global)
  scope = "https://www.googleapis.com/auth/devstorage.read_write"
  claims = ServerToServer.GoogleClaims(
    issuer = serviceAccountKey.client_email,
    scope = scope,
    audience = serviceAccountKey.token_uri,
    expiration = Instant.now().plusSeconds(3600),
    issuedAt = Instant.now()
  )
  settings =  ServerToServer.Settings(
    uri = serviceAccountKey.token_uri,
    privateKey = serviceAccountKey.private_key,
    grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer",
    claims = claims
  )
 response <- ServerToServer.auth[IO](settings, global)
} yield response
// res1: IO[ServerToServer.AuthResponse] = Bind(
//   Map(
//     Bind(
//       Pure(src/test/resources/service-account.json),
//       io.github.jkobejs.google.oauth4s.ServiceAccountKeyReader$$$Lambda$7713/7612392@74764392
//     ),
//     <function1>,
//     0
//   ),
//   <function1>
// )