From e0ac2f479f8d2654d412061fed103cbd0c4f11db Mon Sep 17 00:00:00 2001 From: Benjamin Voiturier Date: Tue, 10 Dec 2024 16:09:11 +0100 Subject: [PATCH] feat: migrate JWT Scala dependency from Circe to zio-json Signed-off-by: Benjamin Voiturier --- build.sbt | 8 ++++---- .../oidc/KeycloakAuthenticator.scala | 4 ++-- .../identus/pollux/vc/jwt/JWTVerification.scala | 14 +++++++------- .../vc/jwt/VerifiableCredentialPayload.scala | 10 +++++----- .../vc/jwt/VerifiablePresentationPayload.scala | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/build.sbt b/build.sbt index 4107ba2b03..5efc89ffd8 100644 --- a/build.sbt +++ b/build.sbt @@ -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" @@ -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" @@ -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 @@ -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( diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/iam/authentication/oidc/KeycloakAuthenticator.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/iam/authentication/oidc/KeycloakAuthenticator.scala index 146253739a..c692b42b81 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/iam/authentication/oidc/KeycloakAuthenticator.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/iam/authentication/oidc/KeycloakAuthenticator.scala @@ -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 @@ -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 diff --git a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerification.scala b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerification.scala index 8986700173..3899575ac1 100644 --- a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerification.scala +++ b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerification.scala @@ -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")( @@ -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] = @@ -100,7 +100,7 @@ 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] = @@ -108,7 +108,7 @@ object JWTVerification { 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] = @@ -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 { @@ -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) diff --git a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiableCredentialPayload.scala b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiableCredentialPayload.scala index b109529f29..b8bd641944 100644 --- a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiableCredentialPayload.scala +++ b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiableCredentialPayload.scala @@ -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 { @@ -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) @@ -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) @@ -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 { @@ -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 { diff --git a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiablePresentationPayload.scala b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiablePresentationPayload.scala index 4d50c9b2e1..f08496efd2 100644 --- a/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiablePresentationPayload.scala +++ b/pollux/vc-jwt/src/main/scala/org/hyperledger/identus/pollux/vc/jwt/VerifiablePresentationPayload.scala @@ -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} @@ -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) }