Skip to content

Commit

Permalink
Merge pull request #201 from guardian/various-updates
Browse files Browse the repository at this point in the history
Drop Scala 2.12, drop Joda-Time - `maxAuthAge` becomes a `java.time.Duration`
  • Loading branch information
rtyley committed Nov 8, 2023
2 parents 5315e8b + a8f0a10 commit fc646fc
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 49 deletions.
19 changes: 10 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Dependencies._

name := "play-googleauth"

ThisBuild / scalaVersion := "2.13.11"

val sonatypeReleaseSettings = Seq(
organization := "com.gu.play-googleauth",

Expand All @@ -28,32 +30,31 @@ val sonatypeReleaseSettings = Seq(
)
)

def projectWithPlayVersion(majorMinorVersion: String) =
Project(s"play-v$majorMinorVersion", file(s"play-v$majorMinorVersion")).settings(
scalaVersion := "2.12.18",
crossScalaVersions := Seq(scalaVersion.value, "2.13.11"),
def projectWithPlayVersion(playVersion: PlayVersion) =
Project(playVersion.projectId, file(playVersion.projectId)).settings(
crossScalaVersions := Seq(scalaVersion.value),
scalacOptions ++= Seq("-feature", "-deprecation"),

libraryDependencies ++= Seq(
"com.gu.play-secret-rotation" %% "core" % "0.37",
"com.gu.play-secret-rotation" %% "core" % "0.38",
"org.typelevel" %% "cats-core" % "2.9.0",
commonsCodec,
"org.scalatest" %% "scalatest" % "3.2.16" % Test,
"com.typesafe.akka" %% "akka-http-core" % "10.2.10" % Test
) ++ googleDirectoryAPI ++ playLibs(majorMinorVersion),
) ++ googleDirectoryAPI ++ playVersion.playLibs,

sonatypeReleaseSettings
)

lazy val `play-v27` = projectWithPlayVersion("27")
lazy val `play-v28` = projectWithPlayVersion("28")
lazy val `play-v27` = projectWithPlayVersion(PlayVersion.V27)
lazy val `play-v28` = projectWithPlayVersion(PlayVersion.V28)

lazy val `play-googleauth-root` = (project in file(".")).aggregate(
`play-v27`,
`play-v28`
).settings(
publishArtifact := false,
publish/skip := true,
publish / skip := true,

sonatypeReleaseSettings
)
6 changes: 2 additions & 4 deletions play-v27/src/main/scala/com/gu/googleauth/auth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package com.gu.googleauth
import java.math.BigInteger
import java.nio.charset.StandardCharsets.UTF_8
import java.security.SecureRandom
import java.time.Clock
import java.time.{Clock, Duration}
import java.util.{Base64, Date}

import com.gu.googleauth.AntiForgeryChecker._
import com.gu.play.secretrotation.DualSecretTransition.InitialSecret
import com.gu.play.secretrotation.SnapshotProvider
import io.jsonwebtoken.SignatureAlgorithm.HS256
import io.jsonwebtoken._
import org.joda.time.Duration
import play.api.Logging
import play.api.http.HeaderNames.USER_AGENT
import play.api.http.HttpConfiguration
Expand Down Expand Up @@ -203,7 +201,7 @@ object GoogleAuth {
"redirect_uri" -> Seq(config.redirectUrl),
"state" -> Seq(config.antiForgeryChecker.generateToken(sessionId))) ++
hdParameter(config.domains).map(domain => "hd" -> Seq(domain)) ++
config.maxAuthAge.map(age => "max_auth_age" -> Seq(s"${age.getStandardSeconds}")) ++
config.maxAuthAge.map(age => "max_auth_age" -> Seq(s"${age.toSeconds}")) ++
config.prompt.map(prompt => "prompt" -> Seq(prompt)) ++
userIdentity.map(_.email).map("login_hint" -> Seq(_))

Expand Down
2 changes: 1 addition & 1 deletion play-v27/src/main/scala/com/gu/googleauth/groups.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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.jdk.CollectionConverters._
import scala.concurrent._

/**
Expand Down
12 changes: 6 additions & 6 deletions play-v27/src/main/scala/com/gu/googleauth/model.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.apache.commons.codec.binary.Base64
case class DiscoveryDocument(authorization_endpoint: String, token_endpoint: String, userinfo_endpoint: String)
object DiscoveryDocument {
val url = "https://accounts.google.com/.well-known/openid-configuration"
implicit val discoveryDocumentReads = Json.reads[DiscoveryDocument]
implicit val discoveryDocumentReads: Reads[DiscoveryDocument] = Json.reads[DiscoveryDocument]
def fromJson(json: JsValue) = Json.fromJson[DiscoveryDocument](json).getOrElse(
throw new IllegalArgumentException("Invalid discovery document")
)
Expand All @@ -31,27 +31,27 @@ object Token {
case class JwtClaims(iss: String, sub:String, azp: String, email: String, at_hash: String, email_verified: Boolean,
aud: String, hd: Option[String], iat: Long, exp: Long)
object JwtClaims {
implicit val claimsReads = Json.reads[JwtClaims]
implicit val claimsReads: Reads[JwtClaims] = Json.reads[JwtClaims]
}

case class UserInfo(gender: Option[String], sub: Option[String], name: String, given_name: String, family_name: String,
profile: Option[String], picture: Option[String], email: String, locale: String, hd: Option[String])
object UserInfo {
implicit val userInfoReads = Json.reads[UserInfo]
implicit val userInfoReads: Reads[UserInfo] = Json.reads[UserInfo]
def fromJson(json:JsValue):UserInfo = json.as[UserInfo]
}

case class JsonWebToken(jwt: String) {
val jwtParts: Array[String] = jwt.split('.')
val Array(headerJson, claimsJson) = jwtParts.take(2).map(Base64.decodeBase64).map(Json.parse)
val claims = claimsJson.as[JwtClaims]
val claims: JwtClaims = claimsJson.as[JwtClaims]
}

case class ErrorInfo(domain: String, reason: String, message: String)
object ErrorInfo {
implicit val errorInfoReads = Json.reads[ErrorInfo]
implicit val errorInfoReads: Reads[ErrorInfo] = Json.reads[ErrorInfo]
}
case class Error(errors: Seq[ErrorInfo], code: Int, message: String)
object Error {
implicit val errorReads = Json.reads[Error]
implicit val errorReads: Reads[Error] = Json.reads[Error]
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import play.api.{ApplicationLoader, BuiltInComponentsFromContext}
import play.filters.HttpFiltersComponents
import router.Routes

import scala.collection.JavaConverters._
import scala.jdk.CollectionConverters._

class AppComponents(context: ApplicationLoader.Context)
extends BuiltInComponentsFromContext(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
@(request: play.api.mvc.Security.AuthenticatedRequest[AnyContent, com.gu.googleauth.UserIdentity], error: Option[String] = None)
@import org.joda.time.DateTime

@import java.time.Instant
<html>
<head>
<title>Authorised</title>
Expand All @@ -18,7 +17,7 @@ <h1>Authorised</h1>
@request.user.avatarUrl.map { avatarUrl =>
<p><img class="avatar" src="@avatarUrl" alt="@request.user.firstName" /></p>
}
<p>The expiry time is @{new DateTime(request.user.exp*1000)}</p>
<p>The expiry time is @{Instant.ofEpochSecond(request.user.exp)}</p>
<p>You can go to the <a href="@routes.Login.login()">login page</a>
or <a href="@routes.Login.logout()">logout</a>.</p>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ class AntiForgeryCheckerTest extends AnyFlatSpec with Matchers with TryValues {
.failure.exception shouldBe a [SignatureException]
}

def mockRequest(state: String, sessionId: String): RequestHeader = {
def mockRequest(state: String, sessionId: String): RequestHeader =
FakeRequest("GET", path = s"?state=$state").withSession(antiForgery.sessionIdKeyName -> sessionId)
}

}
43 changes: 22 additions & 21 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ import sbt._
*/
object Dependencies {

private def exactPlayVersions(majorMinorVersion: String): String =
majorMinorVersion match {
case "27" => "2.7.9"
case "28" => "2.8.15"
case class PlayVersion(
majorMinorVersion: String,
groupId: String,
exactPlayVersion: String,
mockWsVersion: String
) {
val projectId = s"play-v$majorMinorVersion"

val playLibs: Seq[ModuleID] = {

val play = groupId %% "play" % exactPlayVersion % Provided
val playWS = groupId %% "play-ws" % exactPlayVersion % Provided
val playTest = groupId %% "play-test" % exactPlayVersion % Test

// mockWs depends on some play-ahc-ws classes, so include them for tests
val playAhcWs = "com.typesafe.play" %% "play-ahc-ws" % exactPlayVersion % Test
val mockWs = "de.leanovate.play-mockws" %% "play-mockws" % mockWsVersion % Test
Seq(play, playWS, playTest, playAhcWs, mockWs)
}
}

private def mockWsVersion(majorMinorVersion: String): String =
majorMinorVersion match {
case "27" => "2.7.1"
case "28" => "2.8.1"
}

def playLibs(majorMinorVersion: String): Seq[ModuleID] = {
val playVersion = exactPlayVersions(majorMinorVersion)

val play = "com.typesafe.play" %% "play" % playVersion % Provided
val playWS = "com.typesafe.play" %% "play-ws" % playVersion % Provided
val playTest = "com.typesafe.play" %% "play-test" % playVersion % Test

// mockWs depends on some play-ahc-ws classes, so include them for tests
val playAhcWs = "com.typesafe.play" %% "play-ahc-ws" % playVersion % Test
val mockWs = "de.leanovate.play-mockws" %% "play-mockws" % mockWsVersion(majorMinorVersion) % Test
Seq(play, playWS, playTest, playAhcWs, mockWs)
object PlayVersion {
val V27 = PlayVersion("27", "com.typesafe.play", "2.7.9", "2.7.1")
val V28 = PlayVersion("28", "com.typesafe.play", "2.8.20", "2.8.1")
}

val commonsCodec = "commons-codec" % "commons-codec" % "1.16.0"
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.2
sbt.version=1.9.7
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ThisBuild / version := "2.2.7-SNAPSHOT"
ThisBuild / version := "2.2.8-SNAPSHOT"

0 comments on commit fc646fc

Please sign in to comment.