Skip to content

Commit

Permalink
feat: Receive/Store Presentation Request (#776)
Browse files Browse the repository at this point in the history
Signed-off-by: Bassam Riman <[email protected]>
  • Loading branch information
CryptoKnightIOG committed Dec 19, 2023
1 parent 4968c40 commit 58e81f5
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ object PresentationError {
object MissingCredential extends PresentationError
object MissingCredentialFormat extends PresentationError
final case class UnsupportedCredentialFormat(vcFormat: String) extends PresentationError

final case class InvalidAnoncredPresentationRequest(error: String) extends PresentationError
final case class MissingAnoncredPresentationRequest(error: String) extends PresentationError
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import zio.*
import java.rmi.UnexpectedException
import java.time.Instant
import java.util as ju
import java.util.UUID
import java.util.{UUID, Base64 as JBase64}

private class PresentationServiceImpl(
presentationRepository: PresentationRepository,
Expand Down Expand Up @@ -278,9 +278,17 @@ private class PresentationServiceImpl(
val jsonF = PresentCredentialRequestFormat.JWT.name // stable identifier
val anoncredF = PresentCredentialRequestFormat.Anoncred.name // stable identifier
head.format match
case None => ZIO.fail(PresentationError.MissingCredentialFormat)
case Some(`jsonF`) => ZIO.succeed(CredentialFormat.JWT)
case Some(`anoncredF`) => ZIO.succeed(CredentialFormat.AnonCreds)
case None => ZIO.fail(PresentationError.MissingCredentialFormat)
case Some(`jsonF`) => ZIO.succeed(CredentialFormat.JWT)
case Some(`anoncredF`) =>
head.data match
case Base64(data) =>
val decodedData = new String(JBase64.getUrlDecoder.decode(data))
AnoncredPresentationRequestV1.schemaSerDes
.validate(decodedData)
.map(_ => CredentialFormat.AnonCreds)
.mapError(error => InvalidAnoncredPresentationRequest(error.error))
case _ => ZIO.fail(InvalidAnoncredPresentationRequest("Expecting Base64-encoded data"))
case Some(unsupportedFormat) => ZIO.fail(PresentationError.UnsupportedCredentialFormat(unsupportedFormat))
case _ => ZIO.fail(PresentationError.UnexpectedError("Presentation with multi attachments"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ object PresentationServiceSpec extends ZIOSpecDefault with PresentationServiceSp
fails(equalTo(UnsupportedCredentialFormat(vcFormat = "Some/UnsupportedCredentialFormat")))
)
},
test("receiveRequestPresentation updates the RequestPresentation in PresentatinRecord") {
test("receiveRequestPresentation JWT updates the RequestPresentation in PresentationRecord") {
for {
svc <- ZIO.service[PresentationService]
connectionId = Some("connectionId")
Expand Down Expand Up @@ -350,6 +350,100 @@ object PresentationServiceSpec extends ZIOSpecDefault with PresentationServiceSp
assertTrue(aRecord.requestPresentationData == Some(requestPresentation))
}
},
test("receiveRequestPresentation Anoncred updates the RequestPresentation in PresentationRecord") {
for {
svc <- ZIO.service[PresentationService]
connectionId = Some("connectionId")
body = RequestPresentation.Body(goal_code = Some("Presentation Request"))
prover = DidId("did:peer:Prover")
verifier = DidId("did:peer:Verifier")
anoncredPresentationRequestV1 = AnoncredPresentationRequestV1(
Map.empty,
Map.empty,
"name",
"nonce",
"version",
None
)
attachmentDescriptor = AttachmentDescriptor.buildBase64Attachment(
mediaType = Some("application/json"),
format = Some(PresentCredentialRequestFormat.Anoncred.name),
payload = AnoncredPresentationRequestV1.schemaSerDes.serialize(anoncredPresentationRequestV1).getBytes()
)
requestPresentation = RequestPresentation(
body = body,
attachments = Seq(attachmentDescriptor),
to = prover,
from = verifier,
)
aRecord <- svc.receiveRequestPresentation(connectionId, requestPresentation)

} yield {
assertTrue(aRecord.connectionId == connectionId) &&
assertTrue(aRecord.protocolState == PresentationRecord.ProtocolState.RequestReceived) &&
assertTrue(aRecord.requestPresentationData == Some(requestPresentation))
}
},
test("receiveRequestPresentation Anoncred should fail given invalid attachment") {
for {
svc <- ZIO.service[PresentationService]
connectionId = Some("connectionId")
body = RequestPresentation.Body(goal_code = Some("Presentation Request"))
presentationAttachmentAsJson =
"""{
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "us.gov/DriverLicense",
"credential_manifest": {}
}"""
prover = DidId("did:peer:Prover")
verifier = DidId("did:peer:Verifier")

attachmentDescriptor = AttachmentDescriptor.buildJsonAttachment(
payload = presentationAttachmentAsJson,
format = Some(PresentCredentialProposeFormat.Anoncred.name)
)
requestPresentation = RequestPresentation(
body = body,
attachments = Seq(attachmentDescriptor),
to = prover,
from = verifier,
)
result <- svc.receiveRequestPresentation(connectionId, requestPresentation).exit

} yield assert(result)(
fails(equalTo(InvalidAnoncredPresentationRequest("Expecting Base64-encoded data")))
)
},
test("receiveRequestPresentation Anoncred should fail given invalid anoncred format") {
for {
svc <- ZIO.service[PresentationService]
connectionId = Some("connectionId")
body = RequestPresentation.Body(goal_code = Some("Presentation Request"))
presentationAttachmentAsJson =
"""{
"challenge": "1f44d55f-f161-4938-a659-f8026467f126",
"domain": "us.gov/DriverLicense",
"credential_manifest": {}
}"""
prover = DidId("did:peer:Prover")
verifier = DidId("did:peer:Verifier")
attachmentDescriptor = AttachmentDescriptor.buildBase64Attachment(
mediaType = Some("application/json"),
format = Some(PresentCredentialRequestFormat.Anoncred.name),
payload = presentationAttachmentAsJson.getBytes()
)
requestPresentation = RequestPresentation(
body = body,
attachments = Seq(attachmentDescriptor),
to = prover,
from = verifier,
)
result <- svc.receiveRequestPresentation(connectionId, requestPresentation).exit

} yield assert(result)(
fails(isSubtype[InvalidAnoncredPresentationRequest](anything))
)
},
test("acceptRequestPresentation updates the PresentatinRecord JWT") {
for {
repo <- ZIO.service[CredentialRepository]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ object PresentProofController {
ErrorResponse.badRequest(title = "InvalidFlowState", detail = Some(msg))
case PresentationError.MissingAnoncredPresentationRequest(msg) =>
ErrorResponse.badRequest(title = "Missing Anoncred Presentation Request", detail = Some(msg))
case PresentationError.InvalidAnoncredPresentationRequest(msg) =>
ErrorResponse.badRequest(title = "Invalid Anoncred Presentation Request", detail = Some(msg))
case PresentationError.UnexpectedError(msg) =>
ErrorResponse.internalServerError(detail = Some(msg))
case PresentationError.IssuedCredentialNotFoundError(_) =>
Expand Down

0 comments on commit 58e81f5

Please sign in to comment.