From e15e9c2f350c61a97719153b6b224e32790e28e5 Mon Sep 17 00:00:00 2001 From: mineme0110 Date: Tue, 19 Nov 2024 18:48:35 +0000 Subject: [PATCH] Add integration test and refactoring code cleanup Signed-off-by: mineme0110 --- .../core/service/CredentialServiceImpl.scala | 3 +- .../PresentationSubmissionVerification.scala | 4 +- .../jwt/VerifiablePresentationPayload.scala | 46 ++++++++----------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceImpl.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceImpl.scala index bdd741e155..8fdcc7cd57 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceImpl.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceImpl.scala @@ -26,6 +26,7 @@ import org.hyperledger.identus.pollux.core.repository.{CredentialRepository, Cre import org.hyperledger.identus.pollux.prex.{ClaimFormat, Jwt, PresentationDefinition} import org.hyperledger.identus.pollux.sdjwt.* import org.hyperledger.identus.pollux.vc.jwt.{Issuer as JwtIssuer, *} +import org.hyperledger.identus.pollux.vc.jwt.PresentationPayload.Implicits.* import org.hyperledger.identus.shared.crypto.{Ed25519KeyPair, Secp256k1KeyPair} import org.hyperledger.identus.shared.http.UriResolver import org.hyperledger.identus.shared.messaging.{Producer, WalletIdAndRecordId} @@ -1505,7 +1506,7 @@ class CredentialServiceImpl( ZIO.fail(CredentialRequestValidationFailed(s"JWT presentation verification failed: $error")) jwtPresentation <- ZIO - .fromTry(JwtPresentation.decodeJwt(jwt)) + .fromTry(JwtPresentation.decodeJwt[JwtPresentationPayload](jwt)) .mapError(t => CredentialRequestValidationFailed(s"JWT presentation decoding failed: ${t.getMessage}")) } yield jwtPresentation } diff --git a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationSubmissionVerification.scala b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationSubmissionVerification.scala index fe167a1122..cf816034a5 100644 --- a/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationSubmissionVerification.scala +++ b/pollux/prex/src/main/scala/org/hyperledger/identus/pollux/prex/PresentationSubmissionVerification.scala @@ -13,7 +13,7 @@ import org.hyperledger.identus.pollux.prex.PresentationSubmissionError.{ JsonPathNotFound, SubmissionNotSatisfyInputDescriptors } -import org.hyperledger.identus.pollux.vc.jwt.{JWT, JwtCredential, JwtPresentation} +import org.hyperledger.identus.pollux.vc.jwt.{JWT, JwtCredential, JwtPresentation, JwtPresentationPayload} import org.hyperledger.identus.pollux.vc.jwt.CredentialPayload.Implicits.* import org.hyperledger.identus.pollux.vc.jwt.PresentationPayload.Implicits.* import org.hyperledger.identus.shared.json.{JsonInterop, JsonPath, JsonPathError, JsonSchemaValidatorImpl} @@ -220,7 +220,7 @@ object PresentationSubmissionVerification { .map(JWT(_)) .mapError(_ => InvalidDataTypeForClaimFormat(format, path, "string")) payload <- ZIO - .fromTry(JwtPresentation.decodeJwt(jwt)) + .fromTry(JwtPresentation.decodeJwt[JwtPresentationPayload](jwt)) .mapError(e => ClaimDecodeFailure(format, path, e.getMessage())) _ <- formatVerification(jwt) .mapError(errors => ClaimFormatVerificationFailure(format, path, errors.mkString)) 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 ac35178754..ffe96ca470 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 @@ -337,6 +337,12 @@ object JwtPresentation { .flatMap(decode[JwtPresentationPayload](_).toTry) } + def decodeJwt[A](jwt: JWT)(using decoder: io.circe.Decoder[A]): Try[A] = { + JwtCirce + .decodeRaw(jwt.value, options = JwtOptions(signature = false, expiration = false, notBefore = false)) + .flatMap(decode[A](_).toTry) + } + def decodeJwt(jwt: JWT, publicKey: PublicKey): Try[JwtPresentationPayload] = { JwtCirce .decodeRaw(jwt.value, publicKey, JwtOptions(expiration = false, notBefore = false)) @@ -370,7 +376,7 @@ object JwtPresentation { )(didResolver: DidResolver, uriResolver: UriResolver)(implicit clock: Clock ): IO[List[String], Validation[String, Unit]] = { - val validateJwtPresentation = Validation.fromTry(decodeJwt(jwt)).mapError(_.toString) + val validateJwtPresentation = Validation.fromTry(decodeJwt[JwtPresentationPayload](jwt)).mapError(_.toString) val credentialValidationZIO = ValidationUtils.foreach( @@ -405,7 +411,7 @@ object JwtPresentation { domain: String, challenge: String ): Validation[String, Unit] = { - val validateJwtPresentation = Validation.fromTry(decodeJwt(jwt)).mapError(_.toString) + val validateJwtPresentation = Validation.fromTry(decodeJwt[JwtPresentationPayload](jwt)).mapError(_.toString) for { decodeJwtPresentation <- validateJwtPresentation aud <- validateAudience(decodeJwtPresentation, Some(domain)) @@ -419,7 +425,7 @@ object JwtPresentation { challenge: Option[String], schemaIdAndTrustedIssuers: Seq[CredentialSchemaAndTrustedIssuersConstraint] ): Validation[String, Unit] = { - val validateJwtPresentation = Validation.fromTry(decodeJwt(jwt)).mapError(_.toString) + val validateJwtPresentation = Validation.fromTry(decodeJwt[JwtPresentationPayload](jwt)).mapError(_.toString) for { decodeJwtPresentation <- validateJwtPresentation aud <- validateAudience(decodeJwtPresentation, domain) @@ -451,15 +457,10 @@ object JwtPresentation { } yield i case (jwtVerifiableCredentialPayload: JwtVerifiableCredentialPayload) => - val decodeJWT = (jwt: JWT) => - Validation - .fromTry(JwtCirce.decodeRaw(jwt.value, options = JwtOptions(false, false, false))) - .mapError(_.getMessage) for { - jwtCredentialDecoded <- decodeJWT(jwtVerifiableCredentialPayload.jwt) jwtCredentialPayload <- Validation - .fromEither(decode[JwtCredentialPayload](jwtCredentialDecoded)) - .mapError(_.getMessage) + .fromTry(decodeJwt[JwtCredentialPayload](jwtVerifiableCredentialPayload.jwt)) + .mapError(_.toString) issuer = jwtCredentialPayload.issuer credentialSchemas = jwtCredentialPayload.maybeCredentialSchema s <- validateSchemaIds(credentialSchemas, expectedSchemaIds) @@ -520,10 +521,6 @@ object JwtPresentation { def verifyHolderBinding(jwt: JWT): Validation[String, Unit] = { import org.hyperledger.identus.pollux.vc.jwt.CredentialPayload.Implicits.* - val decodeJWT = (jwt: JWT) => - Validation - .fromTry(JwtCirce.decodeRaw(jwt.value, options = JwtOptions(false, false, false))) - .mapError(_.getMessage) def validateCredentialSubjectId( vcList: IndexedSeq[VerifiableCredentialPayload], @@ -546,10 +543,9 @@ object JwtPresentation { case (jwtVerifiableCredentialPayload: JwtVerifiableCredentialPayload) => for { - jwtCredentialDecoded <- decodeJWT(jwtVerifiableCredentialPayload.jwt) jwtCredentialPayload <- Validation - .fromEither(decode[JwtCredentialPayload](jwtCredentialDecoded)) - .mapError(_.getMessage) + .fromTry(decodeJwt[JwtCredentialPayload](jwtVerifiableCredentialPayload.jwt)) + .mapError(_.toString) mayBeSubjectDid = jwtCredentialPayload.maybeSub x <- if (mayBeSubjectDid.contains(iss)) { @@ -564,20 +560,15 @@ object JwtPresentation { .map(_ => ()) } for { - decodedJWT <- decodeJWT(jwt) - jwtPresentationPayload <- Validation.fromEither(decode[JwtPresentationPayload](decodedJWT)).mapError(_.getMessage) + jwtPresentationPayload <- Validation + .fromTry(decodeJwt[JwtPresentationPayload](jwt)) + .mapError(_.toString) result <- validateCredentialSubjectId(jwtPresentationPayload.vp.verifiableCredential, jwtPresentationPayload.iss) } yield result } def verifyDates(jwt: JWT, leeway: TemporalAmount)(implicit clock: Clock): Validation[String, Unit] = { val now = clock.instant() - - val decodeJWT = - Validation - .fromTry(JwtCirce.decodeRaw(jwt.value, options = JwtOptions(false, false, false))) - .mapError(_.getMessage) - def validateNbfNotAfterExp(maybeNbf: Option[Instant], maybeExp: Option[Instant]): Validation[String, Unit] = { val maybeResult = for { @@ -612,8 +603,9 @@ object JwtPresentation { } for { - decodedJWT <- decodeJWT - jwtCredentialPayload <- Validation.fromEither(decode[JwtPresentationPayload](decodedJWT)).mapError(_.getMessage) + jwtCredentialPayload <- Validation + .fromTry(decodeJwt[JwtPresentationPayload](jwt)) + .mapError(_.toString) maybeNbf = jwtCredentialPayload.maybeNbf maybeExp = jwtCredentialPayload.maybeExp result <- Validation.validateWith(