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 0019db7792..e464b5ab70 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 @@ -252,7 +252,9 @@ object CredentialPayload { ("credentialStatus", w3cCredentialPayload.maybeCredentialStatus.asJson), ("refreshService", w3cCredentialPayload.maybeRefreshService.asJson), ("evidence", w3cCredentialPayload.maybeEvidence.asJson), - ("termsOfUse", w3cCredentialPayload.maybeTermsOfUse.asJson) + ("termsOfUse", w3cCredentialPayload.maybeTermsOfUse.asJson), + ("validFrom", w3cCredentialPayload.maybeValidFrom.asJson), + ("validUntil", w3cCredentialPayload.maybeValidUntil.asJson) ) .deepDropNullValues .dropEmptyValues @@ -268,7 +270,9 @@ object CredentialPayload { ("credentialStatus", jwtVc.maybeCredentialStatus.asJson), ("refreshService", jwtVc.maybeRefreshService.asJson), ("evidence", jwtVc.maybeEvidence.asJson), - ("termsOfUse", jwtVc.maybeTermsOfUse.asJson) + ("termsOfUse", jwtVc.maybeTermsOfUse.asJson), + ("validFrom", jwtVc.maybeValidFrom.asJson), + ("validUntil", jwtVc.maybeValidUntil.asJson) ) .deepDropNullValues .dropEmptyValues @@ -360,8 +364,8 @@ object CredentialPayload { issuer <- c.downField("issuer").as[String] issuanceDate <- c.downField("issuanceDate").as[Instant] maybeExpirationDate <- c.downField("expirationDate").as[Option[Instant]] - maybeValidFrom <- c.downField("maybeValidFrom").as[Option[Instant]] - maybeValidUntil <- c.downField("maybeValidUntil").as[Option[Instant]] + maybeValidFrom <- c.downField("validFrom").as[Option[Instant]] + maybeValidUntil <- c.downField("validUntil").as[Option[Instant]] maybeCredentialSchema <- c.downField("credentialSchema").as[Option[CredentialSchema]] credentialSubject <- c.downField("credentialSubject").as[Json] maybeCredentialStatus <- c.downField("credentialStatus").as[Option[CredentialStatus]] @@ -405,8 +409,8 @@ object CredentialPayload { maybeRefreshService <- c.downField("refreshService").as[Option[RefreshService]] maybeEvidence <- c.downField("evidence").as[Option[Json]] maybeTermsOfUse <- c.downField("termsOfUse").as[Option[Json]] - maybeValidFrom <- c.downField("maybeValidFrom").as[Option[Instant]] - maybeValidUntil <- c.downField("maybeValidUntil").as[Option[Instant]] + maybeValidFrom <- c.downField("validFrom").as[Option[Instant]] + maybeValidUntil <- c.downField("validUntil").as[Option[Instant]] } yield { JwtVc( `@context` = `@context`, @@ -751,12 +755,6 @@ object JwtCredential { .mapError(_.getMessage) } - def verifyDates(jwtPayload: JwtVerifiableCredentialPayload, leeway: TemporalAmount)(implicit - clock: Clock - ): Validation[String, Unit] = { - verifyDates(jwtPayload.jwt, leeway)(clock) - } - def verifyDates(jwt: JWT, leeway: TemporalAmount)(implicit clock: Clock): Validation[String, Unit] = { val decodeJWT = Validation diff --git a/pollux/vc-jwt/src/test/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerificationTest.scala b/pollux/vc-jwt/src/test/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerificationTest.scala index da506bbff2..3f05de0c35 100644 --- a/pollux/vc-jwt/src/test/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerificationTest.scala +++ b/pollux/vc-jwt/src/test/scala/org/hyperledger/identus/pollux/vc/jwt/JWTVerificationTest.scala @@ -9,11 +9,12 @@ import org.hyperledger.identus.castor.core.model.did.VerificationRelationship import org.hyperledger.identus.pollux.vc.jwt.CredentialPayload.Implicits.* import org.hyperledger.identus.shared.http.* import zio.* +import zio.prelude.Validation import zio.test.* import zio.test.Assertion.* import java.security.Security -import java.time.Instant +import java.time.{Clock, Instant, ZoneId} object JWTVerificationTest extends ZIOSpecDefault { @@ -62,7 +63,9 @@ object JWTVerificationTest extends ZIOSpecDefault { |""".stripMargin private def createJwtCredential(issuer: IssuerWithKey): JWT = { + val validFrom = Instant.parse("2010-01-05T00:00:00Z") // ISSUANCE DATE val jwtCredentialNbf = Instant.parse("2010-01-01T00:00:00Z") // ISSUANCE DATE + val validUntil = Instant.parse("2010-01-09T00:00:00Z") // EXPIRATION DATE val jwtCredentialExp = Instant.parse("2010-01-12T00:00:00Z") // EXPIRATION DATE val jwtCredentialPayload = JwtCredentialPayload( iss = issuer.issuer.did.value, @@ -76,8 +79,8 @@ object JWTVerificationTest extends ZIOSpecDefault { maybeRefreshService = None, maybeEvidence = None, maybeTermsOfUse = None, - maybeValidFrom = None, - maybeValidUntil = None + maybeValidFrom = Some(validFrom), + maybeValidUntil = Some(validUntil) ), nbf = jwtCredentialNbf, // ISSUANCE DATE aud = Set.empty, @@ -183,6 +186,42 @@ object JWTVerificationTest extends ZIOSpecDefault { ) ) }, + test("validate dates happy path") { + val issuer = createUser(DID("did:prism:issuer")) + val jwtCredential = createJwtCredential(issuer) + for { + validation <- ZIO.succeed( + JwtCredential + .verifyDates(jwtCredential, java.time.Duration.ZERO)( + Clock.fixed(Instant.parse("2010-01-08T00:00:00Z"), ZoneId.systemDefault()) + ) + ) + } yield assertTrue(validation.fold(_ => false, _ => true)) + }, + test("validate dates should fail given after valid until") { + val issuer = createUser(DID("did:prism:issuer")) + val jwtCredential = createJwtCredential(issuer) + for { + validation <- ZIO.succeed( + JwtCredential + .verifyDates(jwtCredential, java.time.Duration.ZERO)( + Clock.fixed(Instant.parse("2010-01-10T00:00:00Z"), ZoneId.systemDefault()) + ) + ) + } yield assertTrue(validation.fold(_ => true, _ => false)) + }, + test("validate dates should fail given before valid from") { + val issuer = createUser(DID("did:prism:issuer")) + val jwtCredential = createJwtCredential(issuer) + for { + validation <- ZIO.succeed( + JwtCredential + .verifyDates(jwtCredential, java.time.Duration.ZERO)( + Clock.fixed(Instant.parse("2010-01-02T00:00:00Z"), ZoneId.systemDefault()) + ) + ) + } yield assertTrue(validation.fold(_ => true, _ => false)) + }, test("validate PrismDID issued JWT VC using verification publicKeys") { val issuer = createUser(DID("did:prism:issuer")) val jwtCredential = createJwtCredential(issuer)