Skip to content

Commit

Permalink
feat: connection less presentation expiration time (#1294)
Browse files Browse the repository at this point in the history
Signed-off-by: mineme0110 <[email protected]>
  • Loading branch information
mineme0110 authored Aug 20, 2024
1 parent d7394c8 commit 6024c97
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pollux {
syncRevocationStatusesBgJobProcessingParallelism = ${?SYNC_REVOCATION_STATUSES_BG_JOB_PROCESSING_PARALLELISM}
credential.sdJwt.expiry = 30 days
credential.sdJwt.expiry = ${?CREDENTIAL_SD_JWT_EXPIRY}
presentationInvitationExpiry = 300 seconds
presentationInvitationExpiry = ${?PRESENTATION_INVITATION_EXPIRY}
}

connect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ final case class PolluxConfig(
presentationBgJobProcessingParallelism: Int,
syncRevocationStatusesBgJobRecurrenceDelay: Duration,
syncRevocationStatusesBgJobProcessingParallelism: Int,
presentationInvitationExpiry: Duration,
)
final case class ConnectConfig(
database: DatabaseConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.hyperledger.identus.castor.core.model.error.DIDResolutionError as Cas
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.mercury.*
import org.hyperledger.identus.mercury.model.*
import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation
import org.hyperledger.identus.mercury.protocol.presentproof.*
import org.hyperledger.identus.mercury.protocol.reportproblem.v2.{ProblemCode, ReportProblem}
import org.hyperledger.identus.pollux.core.model.*
Expand Down Expand Up @@ -436,7 +437,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_,
PresentationReceived,
credentialFormat,
_,
invitation,
Some(requestPresentation),
_,
Some(presentation),
Expand All @@ -450,7 +451,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_
) => // Verifier
ZIO.logDebug("PresentationRecord: PresentationReceived") *> ZIO.unit
Verifier.PresentationReceived.handle(id, requestPresentation, presentation, credentialFormat)
Verifier.PresentationReceived.handle(id, requestPresentation, presentation, credentialFormat, invitation)

case PresentationRecord(
id,
Expand Down Expand Up @@ -893,29 +894,51 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation,
credentialFormat: CredentialFormat
credentialFormat: CredentialFormat,
invitation: Option[Invitation]
): ZIO[
AppConfig & JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
val result =
credentialFormat match {
case CredentialFormat.JWT => handleJWT(id, requestPresentation, presentation)
case CredentialFormat.SDJWT => handleSDJWT(id, presentation)
case CredentialFormat.AnonCreds => handleAnoncred(id, requestPresentation, presentation)
case CredentialFormat.JWT => handleJWT(id, requestPresentation, presentation, invitation)
case CredentialFormat.SDJWT => handleSDJWT(id, presentation, invitation)
case CredentialFormat.AnonCreds => handleAnoncred(id, requestPresentation, presentation, invitation)
}
result @@ metric
}

private def handleJWT(id: DidCommID, requestPresentation: RequestPresentation, presentation: Presentation): ZIO[
private def checkInvitationExpiry(
id: DidCommID,
invitation: Option[Invitation]
): ZIO[PresentationService & WalletAccessContext, PresentationError, Unit] = {
invitation.flatMap(_.expires_time) match {
case Some(expiryTime) if Instant.now().getEpochSecond > expiryTime =>
for {
service <- ZIO.service[PresentationService]
_ <- service.markPresentationInvitationExpired(id)
_ <- ZIO.fail(PresentationError.InvitationExpired(s"Invitation has expired. Expiry time: $expiryTime"))
} yield ()
case _ => ZIO.unit
}
}

private def handleJWT(
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation,
invitation: Option[Invitation]
): ZIO[
AppConfig & JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
val clock = java.time.Clock.system(ZoneId.systemDefault)
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
didResolverService <- ZIO.service[JwtDidResolver]
credentialsClaimsValidationResult <- presentation.attachments.head.data match {
Expand Down Expand Up @@ -1022,13 +1045,14 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
} yield result
}

private def handleSDJWT(id: DidCommID, presentation: Presentation): ZIO[
private def handleSDJWT(id: DidCommID, presentation: Presentation, invitation: Option[Invitation]): ZIO[
JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
didResolverService <- ZIO.service[JwtDidResolver]
credentialsClaimsValidationResult <- presentation.attachments.head.data match {
Expand Down Expand Up @@ -1090,20 +1114,22 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
private def handleAnoncred(
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation
presentation: Presentation,
invitation: Option[Invitation]
): ZIO[
PresentationService & DIDNonSecretStorage & MESSAGING_RESOURCES,
PresentationError | DIDSecretStorageError,
Unit
] = {
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
presReceivedToProcessedAspect = CustomMetricsAspect.endRecordingTime(
s"${id}_present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge",
"present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge"
)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
service <- ZIO.service[PresentationService]
presReceivedToProcessedAspect = CustomMetricsAspect.endRecordingTime(
s"${id}_present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge",
"present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge"
)
_ <- (service
.verifyAnoncredPresentation(presentation, requestPresentation, id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext)) @@ presReceivedToProcessedAspect)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class PresentProofControllerImpl(
req.claims,
req.anoncredPresentationRequest,
None,
None,
None
)
case req: OOBRequestPresentationInput =>
Expand All @@ -92,7 +93,8 @@ class PresentProofControllerImpl(
req.claims,
req.anoncredPresentationRequest,
req.goalCode,
req.goal
req.goal,
Some(appConfig.pollux.presentationInvitationExpiry)
)
}
}
Expand All @@ -107,7 +109,8 @@ class PresentProofControllerImpl(
claims: Option[zio.json.ast.Json.Obj],
anoncredPresentationRequest: Option[AnoncredPresentationRequestV1],
goalCode: Option[String],
goal: Option[String]
goal: Option[String],
expirationDuration: Option[Duration],
): ZIO[WalletAccessContext, PresentationError, PresentationRecord] = {
val format = credentialFormat.map(CredentialFormat.valueOf).getOrElse(CredentialFormat.JWT)
format match {
Expand All @@ -126,7 +129,8 @@ class PresentProofControllerImpl(
},
options = options,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case CredentialFormat.SDJWT =>
claims match {
Expand All @@ -146,7 +150,8 @@ class PresentProofControllerImpl(
claimsToDisclose = claimsToDisclose,
options = options,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case None =>
ZIO.fail(
Expand All @@ -165,7 +170,8 @@ class PresentProofControllerImpl(
connectionId = connectionId,
presentationRequest = presentationRequest,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case None =>
ZIO.fail(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ final case class Invitation(
`type`: PIURI = Invitation.`type`,
from: DidId,
body: Invitation.Body,
attachments: Option[Seq[AttachmentDescriptor]] = None
attachments: Option[Seq[AttachmentDescriptor]] = None,
created_time: Option[Long] = None,
expires_time: Option[Long] = None,
) {
assert(`type` == "https://didcomm.org/out-of-band/2.0/invitation")
def toBase64: String = java.util.Base64.getUrlEncoder.encodeToString(this.asJson.deepDropNullValues.noSpaces.getBytes)

}

object Invitation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@ package org.hyperledger.identus.mercury.protocol.presentproof

import org.hyperledger.identus.mercury.model.{AttachmentDescriptor, DidId}
import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation
import zio.Duration

import java.time.Instant

object PresentProofInvitation {
def makeInvitation(
from: DidId,
goalCode: Option[String],
goal: Option[String],
invitationId: String,
requestPresentation: RequestPresentation
requestPresentation: RequestPresentation,
expirationDuration: Option[Duration] = None,
): Invitation = {
val attachmentDescriptor = AttachmentDescriptor.buildJsonAttachment(payload = requestPresentation)
val now = Instant.now
Invitation(
id = invitationId,
from = from,
created_time = Some(now.getEpochSecond),
expires_time = expirationDuration.map(now.plus(_).getEpochSecond),
body = Invitation.Body(
goal_code = goalCode,
goal = goal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ object PresentationError {
cause
)

final case class InvitationExpired(msg: String)
extends PresentationError(
StatusCode.BadRequest,
msg
)

final case class InvitationAlreadyReceived(msg: String)
extends PresentationError(
StatusCode.BadRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ trait PresentationService {
options: Option[org.hyperledger.identus.pollux.core.model.presentation.Options],
goalCode: Option[String],
goal: Option[String],
expirationDuration: Option[Duration],
): ZIO[WalletAccessContext, PresentationError, PresentationRecord]

def createSDJWTPresentationRecord(
Expand All @@ -40,6 +41,7 @@ trait PresentationService {
options: Option[org.hyperledger.identus.pollux.core.model.presentation.Options],
goalCode: Option[String],
goal: Option[String],
expirationDuration: Option[Duration],
): ZIO[WalletAccessContext, PresentationError, PresentationRecord]

def createAnoncredPresentationRecord(
Expand All @@ -50,6 +52,7 @@ trait PresentationService {
presentationRequest: AnoncredPresentationRequestV1,
goalCode: Option[String],
goal: Option[String],
expirationDuration: Option[Duration],
): ZIO[WalletAccessContext, PresentationError, PresentationRecord]

def getPresentationRecords(
Expand Down Expand Up @@ -180,4 +183,8 @@ trait PresentationService {
pairwiseProverDID: DidId,
invitation: String
): ZIO[WalletAccessContext, PresentationError, RequestPresentation]

def markPresentationInvitationExpired(
recordId: DidCommID
): ZIO[WalletAccessContext, PresentationError, PresentationRecord]
}
Loading

0 comments on commit 6024c97

Please sign in to comment.