Skip to content

Commit

Permalink
feat: migrate JWT Scala dependency from Circe to zio-json
Browse files Browse the repository at this point in the history
Signed-off-by: Benjamin Voiturier <[email protected]>
  • Loading branch information
bvoiturier committed Dec 10, 2024
1 parent 9942ee4 commit e0ac2f4
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 20 deletions.
8 changes: 4 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ lazy val V = new {

val scalaUri = "4.0.3"

val jwtCirceVersion = "9.4.6"
val jwtZioVersion = "9.4.6"
val zioPreludeVersion = "1.0.0-RC31"

val apollo = "1.3.5"
Expand Down Expand Up @@ -121,7 +121,7 @@ lazy val D = new {
val zioConfigTypesafe: ModuleID = "dev.zio" %% "zio-config-typesafe" % V.zioConfig

val networkntJsonSchemaValidator = "com.networknt" % "json-schema-validator" % V.jsonSchemaValidator
val jwtCirce = "com.github.jwt-scala" %% "jwt-circe" % V.jwtCirceVersion
val jwtZio = "com.github.jwt-scala" %% "jwt-zio-json" % V.jwtZioVersion
val jsonCanonicalization: ModuleID = "io.github.erdtman" % "java-json-canonicalization" % "1.1"
val titaniumJsonLd: ModuleID = "com.apicatalog" % "titanium-json-ld" % "1.4.0"
val jakartaJson: ModuleID = "org.glassfish" % "jakarta.json" % "2.0.1"
Expand Down Expand Up @@ -329,7 +329,7 @@ lazy val D_Pollux_VC_JWT = new {
// Dependency Modules
val zioDependencies: Seq[ModuleID] = Seq(zio, zioPrelude, zioTest, zioTestSbt, zioTestMagnolia)
val baseDependencies: Seq[ModuleID] =
zioDependencies :+ D.jwtCirce :+ D.networkntJsonSchemaValidator :+ D.nimbusJwt :+ D.scalaTest
zioDependencies :+ D.jwtZio :+ D.networkntJsonSchemaValidator :+ D.nimbusJwt :+ D.scalaTest

// Project Dependencies
lazy val polluxVcJwtDependencies: Seq[ModuleID] = baseDependencies
Expand Down Expand Up @@ -412,7 +412,7 @@ lazy val D_CloudAgent = new {
lazy val keyManagementDependencies: Seq[ModuleID] =
baseDependencies ++ D.doobieDependencies ++ Seq(D.zioCatsInterop, D.zioMock, vaultDriver)

lazy val iamDependencies: Seq[ModuleID] = Seq(keycloakAuthz, D.jwtCirce)
lazy val iamDependencies: Seq[ModuleID] = Seq(keycloakAuthz, D.jwtZio)

lazy val serverDependencies: Seq[ModuleID] =
baseDependencies ++ tapirDependencies ++ postgresDependencies ++ Seq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import org.hyperledger.identus.iam.authentication.AuthenticationError.{
InvalidCredentials
}
import org.hyperledger.identus.shared.utils.Traverse.*
import pdi.jwt.{JwtCirce, JwtClaim, JwtOptions}
import pdi.jwt.{JwtZIOJson, JwtClaim, JwtOptions}
import zio.*
import zio.json.ast.Json

Expand Down Expand Up @@ -61,7 +61,7 @@ final class AccessToken private (token: String, claims: JwtClaim, rolesClaimPath

object AccessToken {
def fromString(token: String, rolesClaimPath: Seq[String] = Nil): Either[String, AccessToken] =
JwtCirce
JwtZIOJson
.decode(token, JwtOptions(false, false, false))
.map(claims => AccessToken(token, claims, rolesClaimPath))
.toEither
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ object JWTVerification {
def validateAlgorithm(jwt: JWT): Validation[String, Unit] = {
val decodedJWT =
Validation
.fromTry(JwtCirce.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.mapError(_.getMessage)
for {
decodedJwtTask <- decodedJWT
(header, _, _) = decodedJwtTask
algorithm <- Validation
.fromOptionWith("An algorithm must be specified in the header")(JwtCirce.parseHeader(header).algorithm)
.fromOptionWith("An algorithm must be specified in the header")(JwtZIOJson.parseHeader(header).algorithm)
result <-
Validation
.fromPredicateWith("Algorithm Not Supported")(
Expand All @@ -52,7 +52,7 @@ object JWTVerification {
)(issuerDidExtractor: T => String): IO[String, Validation[String, DIDDocument]] = {
val decodedJWT =
Validation
.fromTry(JwtCirce.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.mapError(_.getMessage)

val claim: Validation[String, String] =
Expand Down Expand Up @@ -100,15 +100,15 @@ object JWTVerification {
didResolver: DidResolver
)(decoder: String => Validation[String, T])(issuerDidExtractor: T => String): IO[String, Validation[String, Unit]] = {
val decodedJWT = Validation
.fromTry(JwtCirce.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.mapError(_.getMessage)

val extractAlgorithm: Validation[String, JwtAlgorithm] =
for {
decodedJwtTask <- decodedJWT
(header, _, _) = decodedJwtTask
algorithm <- Validation
.fromOptionWith("An algorithm must be specified in the header")(JwtCirce.parseHeader(header).algorithm)
.fromOptionWith("An algorithm must be specified in the header")(JwtZIOJson.parseHeader(header).algorithm)
} yield algorithm

val claim: Validation[String, String] =
Expand Down Expand Up @@ -243,7 +243,7 @@ object JWTVerification {

def extractJwtHeader(jwt: JWT): Validation[String, JwtHeader] = {
def parseHeaderUnsafe(json: Json): Either[String, JwtHeader] =
Try(JwtCirce.parseHeader(json.toJson)).toEither.left.map(_.getMessage)
Try(JwtZIOJson.parseHeader(json.toJson)).toEither.left.map(_.getMessage)

def decodeJwtHeader(header: String): Validation[String, JwtHeader] = {
val eitherResult = for {
Expand All @@ -254,7 +254,7 @@ object JWTVerification {
}
for {
decodedJwt <- Validation
.fromTry(JwtCirce.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRawAll(jwt.value, JwtOptions(false, false, false)))
.mapError(_.getMessage)
(header, _, _) = decodedJwt
jwtHeader <- decodeJwtHeader(header)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ object JwtCredential {

def decodeJwt(jwt: JWT): IO[String, JwtCredentialPayload] = {
val decodeJWT =
ZIO.fromTry(JwtCirce.decodeRawAll(jwt.value, JwtOptions(false, false, false))).mapError(_.getMessage)
ZIO.fromTry(JwtZIOJson.decodeRawAll(jwt.value, JwtOptions(false, false, false))).mapError(_.getMessage)

val validatedDecodedClaim: IO[String, JwtCredentialPayload] =
for {
Expand Down Expand Up @@ -672,7 +672,7 @@ object JwtCredential {
def validateExpiration(jwt: JWT, dateTime: OffsetDateTime): Validation[String, Unit] = {
Validation
.fromTry(
JwtCirce(Clock.fixed(dateTime.toInstant, ZoneId.of(dateTime.getOffset.getId)))
JwtZIOJson(Clock.fixed(dateTime.toInstant, ZoneId.of(dateTime.getOffset.getId)))
.decodeRawAll(jwt.value, JwtOptions(false, true, false))
)
.flatMap(_ => Validation.unit)
Expand All @@ -682,7 +682,7 @@ object JwtCredential {
def validateNotBefore(jwt: JWT, dateTime: OffsetDateTime): Validation[String, Unit] = {
Validation
.fromTry(
JwtCirce(Clock.fixed(dateTime.toInstant, ZoneId.of(dateTime.getOffset.getId)))
JwtZIOJson(Clock.fixed(dateTime.toInstant, ZoneId.of(dateTime.getOffset.getId)))
.decodeRawAll(jwt.value, JwtOptions(false, false, true))
)
.flatMap(_ => Validation.unit)
Expand All @@ -692,7 +692,7 @@ object JwtCredential {
def verifyDates(jwt: JWT, leeway: TemporalAmount)(implicit clock: Clock): Validation[String, Unit] = {
val decodeJWT =
Validation
.fromTry(JwtCirce.decodeRaw(jwt.value, options = JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRaw(jwt.value, options = JwtOptions(false, false, false)))
.mapError(_.getMessage)

for {
Expand Down Expand Up @@ -734,7 +734,7 @@ object JwtCredential {
def verifyRevocationStatusJwt(jwt: JWT)(uriResolver: UriResolver): IO[String, Validation[String, Unit]] = {
val decodeJWT =
ZIO
.fromTry(JwtCirce.decodeRaw(jwt.value, options = JwtOptions(false, false, false)))
.fromTry(JwtZIOJson.decodeRaw(jwt.value, options = JwtOptions(false, false, false)))
.mapError(_.getMessage)

val res = for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.hyperledger.identus.pollux.vc.jwt

import org.hyperledger.identus.castor.core.model.did.VerificationRelationship
import org.hyperledger.identus.shared.http.UriResolver
import pdi.jwt.{JwtCirce, JwtOptions}
import pdi.jwt.{JwtOptions, JwtZIOJson}
import zio.*
import zio.json.{DecoderOps, DeriveJsonDecoder, DeriveJsonEncoder, EncoderOps, JsonDecoder, JsonEncoder}
import zio.json.ast.{Json, JsonCursor}
Expand Down Expand Up @@ -314,7 +314,7 @@ object JwtPresentation {
encodeJwt(payload.toJwtPresentationPayload, issuer)

def decodeJwt[A](jwt: JWT)(using decoder: JsonDecoder[A]): Try[A] = {
JwtCirce
JwtZIOJson
.decodeRaw(jwt.value, options = JwtOptions(signature = false, expiration = false, notBefore = false))
.flatMap(a => a.fromJson[A].left.map(s => new RuntimeException(s)).toTry)
}
Expand Down

0 comments on commit e0ac2f4

Please sign in to comment.