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

Replace Spray JWT dependency #3030

Merged
merged 3 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import akka.stream.Materializer
import akka.stream.alpakka.google.http.GoogleHttp
import akka.stream.alpakka.google.{implicits, RequestSettings}
import pdi.jwt.JwtAlgorithm.RS256
import pdi.jwt.{JwtClaim, JwtSprayJson}
import pdi.jwt.JwtClaim
import spray.json.DefaultJsonProtocol._
import spray.json.JsonFormat

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (C) since 2016 Lightbend Inc. <https://www.lightbend.com>
*/

/*
* This software is licensed under the Apache 2 license.
* Copyright 2021 JWT-Scala Contributors.
ennru marked this conversation as resolved.
Show resolved Hide resolved
*/

package akka.stream.alpakka.google.auth

import pdi.jwt.{JwtAlgorithm, JwtClaim, JwtHeader, JwtJsonCommon}

import java.time.Clock
import pdi.jwt.exceptions.JwtNonStringException
import spray.json._

/**
* Implementation of `JwtCore` using `JsObject` from spray-json.
*
* This class originally came from jwt-spray-json,
* but was removed in https://github.com/jwt-scala/jwt-scala/commit/bf1131ce02480103c0b953b97da001105a3ee038
*/
trait JwtSprayJsonParser[H, C] extends JwtJsonCommon[JsObject, H, C] {
ennru marked this conversation as resolved.
Show resolved Hide resolved
protected def parse(value: String): JsObject = value.parseJson.asJsObject

protected def stringify(value: JsObject): String = value.compactPrint

protected def getAlgorithm(header: JsObject): Option[JwtAlgorithm] =
header.fields.get("alg").flatMap {
case JsString("none") => None
case JsString(algo) => Option(JwtAlgorithm.fromString(algo))
case JsNull => None
case _ => throw new JwtNonStringException("alg")
}

}

object JwtSprayJson extends JwtSprayJson(Clock.systemUTC) {
def apply(clock: Clock): JwtSprayJson = new JwtSprayJson(clock)
}

class JwtSprayJson(override val clock: Clock) extends JwtSprayJsonParser[JwtHeader, JwtClaim] {

import DefaultJsonProtocol._
override def parseHeader(header: String): JwtHeader = {
val jsObj = parse(header)
JwtHeader(
algorithm = getAlgorithm(jsObj),
typ = safeGetField[String](jsObj, "typ"),
contentType = safeGetField[String](jsObj, "cty"),
keyId = safeGetField[String](jsObj, "kid")
)
}

override def parseClaim(claim: String): JwtClaim = {
val jsObj = parse(claim)
val content = JsObject(jsObj.fields - "iss" - "sub" - "aud" - "exp" - "nbf" - "iat" - "jti")
JwtClaim(
content = stringify(content),
issuer = safeGetField[String](jsObj, "iss"),
subject = safeGetField[String](jsObj, "sub"),
audience = safeGetField[Set[String]](jsObj, "aud")
.orElse(safeGetField[String](jsObj, "aud").map(s => Set(s))),
expiration = safeGetField[Long](jsObj, "exp"),
notBefore = safeGetField[Long](jsObj, "nbf"),
issuedAt = safeGetField[Long](jsObj, "iat"),
jwtId = safeGetField[String](jsObj, "jti")
)
}

private[this] def safeRead[A: JsonReader](js: JsValue) =
safeReader[A].read(js).fold(_ => None, a => Option(a))

private[this] def safeGetField[A: JsonReader](js: JsObject, name: String) =
js.fields.get(name).flatMap(safeRead[A])
}
7 changes: 4 additions & 3 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ object Dependencies {
val CouchbaseVersion = "2.7.16"
val CouchbaseVersionForDocs = "2.7"

val JwtCoreVersion = "3.0.1"
// https://github.com/jwt-scala/jwt-scala/releases
val JwtScalaVersion = "9.4.4"

val log4jOverSlf4jVersion = "1.7.36"
val jclOverSlf4jVersion = "1.7.36"
Expand Down Expand Up @@ -204,7 +205,7 @@ object Dependencies {
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion,
"com.github.jwt-scala" %% "jwt-spray-json" % "9.0.2", // ApacheV2
"com.github.jwt-scala" %% "jwt-json-common" % JwtScalaVersion,
// https://github.com/googleapis/google-auth-library-java
"com.google.auth" % "google-auth-library-credentials" % GoogleAuthVersion,
"io.specto" % "hoverfly-java" % hoverflyVersion % Test // ApacheV2
Expand Down Expand Up @@ -304,7 +305,7 @@ object Dependencies {
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion,
"com.github.jwt-scala" %% "jwt-spray-json" % "7.1.4" // ApacheV2
"com.github.jwt-scala" %% "jwt-json-common" % JwtScalaVersion
) ++ Mockito
)

Expand Down
Loading