From e03ebbc1380752a1030d6c00bbe984b5658fdd48 Mon Sep 17 00:00:00 2001 From: Cristian Gonzalez <113917899+cristianIOHK@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:13:22 -0400 Subject: [PATCH] feat: contactless presentation request (#192) Signed-off-by: Cristian G --- .../identus/walletsdk/domain/models/Errors.kt | 2 +- .../domain/models/MessageAttachment.kt | 5 + .../identus/walletsdk/edgeagent/EdgeAgent.kt | 98 +++++++++++++++++-- .../walletsdk/edgeagent/EdgeAgentError.kt | 9 ++ .../outOfBand/OutOfBandInvitation.kt | 8 +- .../proofOfPresentation/Presentation.kt | 22 ----- .../ProposePresentation.kt | 24 ----- .../RequestPresentation.kt | 2 +- .../walletsdk/edgeagent/EdgeAgentTests.kt | 84 +++++++++++++++- .../ui/contacts/ContactsViewModel.kt | 22 +++-- sampleapp/src/main/res/values/strings.xml | 2 +- 11 files changed, 209 insertions(+), 69 deletions(-) diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/Errors.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/Errors.kt index defd9a425..5a7784d4f 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/Errors.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/Errors.kt @@ -691,7 +691,7 @@ constructor( /** * Represents an error that occurs when a field is null but should not be. */ - class NonNullableError(val field: String) : PolluxError("Field $field are non nullable.") { + class NonNullableError(val field: String) : PolluxError("Field $field is non nullable.") { override val code: Int get() = 516 } diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/MessageAttachment.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/MessageAttachment.kt index f655e0a4d..d4d19f27a 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/MessageAttachment.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/domain/models/MessageAttachment.kt @@ -7,6 +7,7 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.encodeToString import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json @@ -321,6 +322,10 @@ object AttachmentDataSerializer : KSerializer { jsonSerializable.decodeFromJsonElement(AttachmentData.AttachmentJsonData.serializer(), json) } + json.containsKey("json") -> { + AttachmentData.AttachmentJsonData(data = Json.encodeToString(json["json"]!!.jsonObject)) + } + else -> throw SerializationException("Unknown AttachmentData type") } } diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgent.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgent.kt index 34e986ef1..7f3005358 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgent.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgent.kt @@ -22,6 +22,7 @@ import io.ktor.http.ContentType import io.ktor.http.HttpMethod import io.ktor.http.Url import io.ktor.serialization.kotlinx.json.json +import io.ktor.util.date.getTimeMillis import java.net.UnknownHostException import java.security.SecureRandom import java.util.* @@ -34,12 +35,15 @@ import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.launch +import kotlinx.datetime.Instant import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import org.hyperledger.identus.apollo.base64.base64UrlEncoded import org.hyperledger.identus.walletsdk.apollo.utils.Ed25519KeyPair import org.hyperledger.identus.walletsdk.apollo.utils.Ed25519PrivateKey @@ -902,14 +906,91 @@ open class EdgeAgent { } /** - * Accepts an Out-of-Band (DIDComm) invitation and establishes a new connection + * Accepts an Out-of-Band (DIDComm), verifies if it contains attachments or not. If it does contain attachments + * means is a contactless request presentation. If it does not, it just creates a pair and establishes a connection. * @param invitation The Out-of-Band invitation to accept * @throws [EdgeAgentError.NoMediatorAvailableError] if there is no mediator available or other errors occur during the acceptance process */ suspend fun acceptOutOfBandInvitation(invitation: OutOfBandInvitation) { val ownDID = createNewPeerDID(updateMediator = true) - val pair = DIDCommConnectionRunner(invitation, pluto, ownDID, connectionManager).run() - connectionManager.addConnection(pair) + if (invitation.attachments.isNotEmpty()) { + // If attachments not empty, means connectionless presentation + val now = Instant.fromEpochMilliseconds(getTimeMillis()) + val expiryDate = Instant.fromEpochSeconds(invitation.expiresTime) + if (now > expiryDate) { + throw EdgeAgentError.ExpiredInvitation() + } + + val jsonString = invitation.attachments.firstNotNullOf { it.data.getDataAsJsonString() } + val requestPresentationJson = Json.parseToJsonElement(jsonString).jsonObject + if (!requestPresentationJson.containsKey("id")) { + throw EdgeAgentError.MissingOrNullFieldError("id", "Request") + } + if (!requestPresentationJson.containsKey("body")) { + throw EdgeAgentError.MissingOrNullFieldError("body", "Request") + } + if (!requestPresentationJson.containsKey("attachments")) { + throw EdgeAgentError.MissingOrNullFieldError("attachments", "Request") + } + if (!requestPresentationJson.containsKey("thid")) { + throw EdgeAgentError.MissingOrNullFieldError("thid", "Request") + } + if (!requestPresentationJson.containsKey("from")) { + throw EdgeAgentError.MissingOrNullFieldError("from", "Request") + } + + val requestId = requestPresentationJson["id"]!! + val requestBody = requestPresentationJson["body"]!! + val requestAttachments = requestPresentationJson["attachments"]!! + val requestThid = requestPresentationJson["thid"]!! + val requestFrom = requestPresentationJson["from"]!! + + if (requestAttachments.jsonArray.size == 0) { + throw EdgeAgentError.MissingOrNullFieldError("attachments", "Request") + } + val attachmentJsonObject = requestAttachments.jsonArray[0] + if (!attachmentJsonObject.jsonObject.containsKey("id")) { + throw EdgeAgentError.MissingOrNullFieldError("id", "Request attachments") + } + if (!attachmentJsonObject.jsonObject.containsKey("media_type")) { + throw EdgeAgentError.MissingOrNullFieldError("media_type", "Request attachments") + } + if (!attachmentJsonObject.jsonObject.containsKey("data")) { + if (!attachmentJsonObject.jsonObject["data"]!!.jsonObject.containsKey("json")) { + throw EdgeAgentError.MissingOrNullFieldError("json", "Request attachments data") + } + throw EdgeAgentError.MissingOrNullFieldError("data", "Request attachments") + } + if (!attachmentJsonObject.jsonObject.containsKey("format")) { + throw EdgeAgentError.MissingOrNullFieldError("format", "Request attachments") + } + val attachmentId = attachmentJsonObject.jsonObject["id"]!! + val attachmentMediaType = attachmentJsonObject.jsonObject["media_type"]!! + val attachmentData = attachmentJsonObject.jsonObject["data"]!!.jsonObject["json"]!! + val attachmentFormat = attachmentJsonObject.jsonObject["format"]!! + + val attachmentDescriptor = AttachmentDescriptor( + id = attachmentId.jsonPrimitive.content, + mediaType = attachmentMediaType.jsonPrimitive.content, + data = AttachmentJsonData(attachmentData.toString()), + format = attachmentFormat.jsonPrimitive.content + ) + + val requestPresentation = RequestPresentation( + id = requestId.jsonPrimitive.content, + body = Json.decodeFromString(requestBody.jsonObject.toString()), + attachments = arrayOf(attachmentDescriptor), + thid = requestThid.jsonPrimitive.content, + from = DID(requestFrom.jsonPrimitive.content), + to = ownDID + ) + + pluto.storeMessage(requestPresentation.makeMessage()) + } else { + // Regular OOB invitation + val pair = DIDCommConnectionRunner(invitation, pluto, ownDID, connectionManager).run() + connectionManager.addConnection(pair) + } } /** @@ -1060,8 +1141,10 @@ open class EdgeAgent { data = AttachmentBase64(presentationString.base64UrlEncoded) ) + val fromDID = request.to ?: createNewPeerDID(updateMediator = true) + return Presentation( - from = request.to, + from = fromDID, to = request.from, thid = request.thid, body = Presentation.Body(request.body.goalCode, request.body.comment), @@ -1172,11 +1255,13 @@ open class EdgeAgent { format = CredentialType.PRESENTATION_EXCHANGE_SUBMISSION.type, data = AttachmentBase64(presentationSubmissionProof.base64UrlEncoded) ) + + val fromDID = requestPresentation.to ?: createNewPeerDID(updateMediator = true) return Presentation( body = Presentation.Body(), attachments = arrayOf(attachmentDescriptor), thid = requestPresentation.thid ?: requestPresentation.id, - from = requestPresentation.to, + from = fromDID, to = requestPresentation.from ) } else { @@ -1192,11 +1277,12 @@ open class EdgeAgent { format = CredentialType.PRESENTATION_EXCHANGE_SUBMISSION.type, data = AttachmentBase64(presentationSubmissionProof.base64UrlEncoded) ) + val fromDID = requestPresentation.to ?: createNewPeerDID(updateMediator = true) return Presentation( body = Presentation.Body(), attachments = arrayOf(attachmentDescriptor), thid = requestPresentation.thid ?: requestPresentation.id, - from = requestPresentation.to, + from = fromDID, to = requestPresentation.from ) } diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentError.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentError.kt index a6f26621c..afce6e5c2 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentError.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentError.kt @@ -143,4 +143,13 @@ sealed class EdgeAgentError : KnownPrismError() { override val message: String get() = "This credential does not fulfill the criteria required by the request." } + + class ExpiredInvitation() : + EdgeAgentError() { + override val code: Int + get() = 615 + + override val message: String + get() = "This invitation has expired." + } } diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/outOfBand/OutOfBandInvitation.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/outOfBand/OutOfBandInvitation.kt index 8bf374033..934d3b908 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/outOfBand/OutOfBandInvitation.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/outOfBand/OutOfBandInvitation.kt @@ -4,6 +4,7 @@ import kotlinx.serialization.EncodeDefault import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import org.hyperledger.identus.walletsdk.domain.models.AttachmentDescriptor import org.hyperledger.identus.walletsdk.edgeagent.GOAL_CODE import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType import java.util.UUID @@ -23,7 +24,12 @@ constructor( @EncodeDefault val type: ProtocolType = ProtocolType.Didcomminvitation, @EncodeDefault - val typ: String? = null + val typ: String? = null, + val attachments: Array = arrayOf(), + @SerialName("created_time") + val createdTime: Long = 0, + @SerialName("expires_time") + val expiresTime: Long = 0 ) : InvitationType() { /** diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/Presentation.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/Presentation.kt index 81e79ecd1..08d8a0039 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/Presentation.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/Presentation.kt @@ -182,28 +182,6 @@ class Presentation { ) } - /** - * Converts a message into a Presentation object. - * - * @param msg The input message to convert. - * @return The converted Presentation object. - * @throws EdgeAgentError.InvalidMessageType If the message type is invalid. - */ - @Throws(EdgeAgentError.InvalidMessageType::class) - fun makePresentationFromRequest(msg: Message): Presentation { - val requestPresentation = RequestPresentation.fromMessage(msg) - return Presentation( - body = Body( - goalCode = requestPresentation.body.goalCode, - comment = requestPresentation.body.comment - ), - attachments = requestPresentation.attachments, - thid = requestPresentation.id, - from = requestPresentation.to, - to = requestPresentation.from - ) - } - /** * Compares this Presentation object with the specified object for equality. * diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/ProposePresentation.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/ProposePresentation.kt index 0e21452fb..889b96b82 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/ProposePresentation.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/ProposePresentation.kt @@ -113,30 +113,6 @@ class ProposePresentation { ) } - /** - * Creates a proposal presentation from a request message. - * - * @param msg The request message. - * @return The created `ProposePresentation` object. - * @throws EdgeAgentError.InvalidMessageType If the message type does not represent the expected protocol. - */ - @Throws(EdgeAgentError.InvalidMessageType::class) - fun makeProposalFromRequest(msg: Message): ProposePresentation { - val request = RequestPresentation.fromMessage(msg) - - return ProposePresentation( - body = Body( - goalCode = request.body.goalCode, - comment = request.body.comment, - proofTypes = request.body.proofTypes - ), - attachments = request.attachments, - thid = msg.id, - from = request.to, - to = request.from - ) - } - /** * Compares this object with the specified object for equality. * diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/RequestPresentation.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/RequestPresentation.kt index 009f91f05..bc397e2bc 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/RequestPresentation.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/protocols/proofOfPresentation/RequestPresentation.kt @@ -33,7 +33,7 @@ data class RequestPresentation( val attachments: Array, val thid: String? = null, val from: DID, - val to: DID, + val to: DID? = null, val direction: Message.Direction = Message.Direction.RECEIVED ) { diff --git a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentTests.kt b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentTests.kt index 27125e8dc..efcab27ed 100644 --- a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentTests.kt +++ b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/EdgeAgentTests.kt @@ -9,11 +9,13 @@ import com.nimbusds.jose.JWEObject import io.ktor.http.HttpStatusCode import java.security.interfaces.ECPublicKey import java.util.* +import java.util.concurrent.TimeUnit import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject import org.hyperledger.identus.apollo.base64.base64UrlDecoded import org.hyperledger.identus.apollo.base64.base64UrlDecodedBytes import org.hyperledger.identus.apollo.base64.base64UrlEncoded @@ -83,6 +85,7 @@ import org.hyperledger.identus.walletsdk.pollux.models.CredentialRequestMeta import org.hyperledger.identus.walletsdk.pollux.models.JWTCredential import org.hyperledger.identus.walletsdk.pollux.models.PresentationSubmission import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -93,6 +96,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.spy import kotlin.test.assertEquals @@ -1343,7 +1347,8 @@ class EdgeAgentTests { "{\"presentation_submission\":{\"id\":\"00000000-c224-45d7-0000-0000732f4932\",\"definition_id\":\"32f54163-7166-48f1-93d8-ff217bdb0653\",\"descriptor_map\":[{\"id\":\"wa_driver_license\",\"format\":\"jwt\",\"path\":\"$.verifiablePresentation[0]\"}]},\"verifiablePresentation\":[\"eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng\"]}" val presentationSubmission = presentationSubmissionString - val presentationDefinitionRequest = """{"presentation_definition":{"id":"32f54163-7166-48f1-93d8-ff217bdb0653","input_descriptors":[{"id":"wa_driver_license","name":"Washington State Business License","purpose":"We can only allow licensed Washington State business representatives into the WA Business Conference","constraints":{"fields":[{"path":["${'$'}.credentialSubject.dateOfBirth","${'$'}.credentialSubject.dob","${'$'}.vc.credentialSubject.dateOfBirth","${'$'}.vc.credentialSubject.dob"]}]}}],"format":{"jwt":{"alg":["ES256K"]}}},"options":{"domain":"domain","challenge":"challenge"}}""" + val presentationDefinitionRequest = + """{"presentation_definition":{"id":"32f54163-7166-48f1-93d8-ff217bdb0653","input_descriptors":[{"id":"wa_driver_license","name":"Washington State Business License","purpose":"We can only allow licensed Washington State business representatives into the WA Business Conference","constraints":{"fields":[{"path":["${'$'}.credentialSubject.dateOfBirth","${'$'}.credentialSubject.dob","${'$'}.vc.credentialSubject.dateOfBirth","${'$'}.vc.credentialSubject.dob"]}]}}],"format":{"jwt":{"alg":["ES256K"]}}},"options":{"domain":"domain","challenge":"challenge"}}""" val credential = JWTCredential.fromJwtString( "eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng" ) @@ -1381,7 +1386,7 @@ class EdgeAgentTests { assertTrue(attachmentData is AttachmentBase64) val expectedPresentationSubmission = Json.decodeFromString(presentationSubmissionString) - val attachmentDataString = attachmentData.base64.base64UrlDecoded + val attachmentDataString = attachmentData.getDataAsJsonString() val actualPresentationSubmission = Json.decodeFromString(attachmentDataString) assertEquals( @@ -1445,7 +1450,7 @@ class EdgeAgentTests { assertTrue(attachmentData is AttachmentBase64) assertEquals( 3, - attachmentData.base64.base64UrlDecoded.split(".").count() + attachmentData.getDataAsJsonString().split(".").count() ) } @@ -1481,7 +1486,8 @@ class EdgeAgentTests { // Mock getDIDPrivateKeysByDID response `when`(plutoMock.getDIDPrivateKeysByDID(any())).thenReturn(flow { emit(storablePrivateKeys) }) - val presentationSubmission = """{"presentation_submission":{"id":"00000000-c224-45d7-0000-0000732f4932","definition_id":"32f54163-7166-48f1-93d8-ff217bdb0653","descriptor_map":[{"id":"wa_driver_license","format":"jwt","path":"${'$'}.verifiablePresentation[0]"}]},"verifiablePresentation":["eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng"]}""" + val presentationSubmission = + """{"presentation_submission":{"id":"00000000-c224-45d7-0000-0000732f4932","definition_id":"32f54163-7166-48f1-93d8-ff217bdb0653","descriptor_map":[{"id":"wa_driver_license","format":"jwt","path":"${'$'}.verifiablePresentation[0]"}]},"verifiablePresentation":["eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng"]}""" // Mock createPresentationSubmission response `when`(polluxMock.createJWTPresentationSubmission(any(), any(), any())).thenReturn( presentationSubmission @@ -1850,6 +1856,76 @@ class EdgeAgentTests { } } + @Test + fun `test connectionless Presentation request with expired invitations`() = runTest { + val agent = spy( + EdgeAgent( + apollo = apolloMock, + castor = castorMock, + pluto = plutoMock, + mercury = mercuryMock, + pollux = polluxMock, + connectionManager = connectionManagerMock, + seed = seed, + api = null, + logger = PrismLoggerMock() + ) + ) + + val outOfBandUrl = + "https://my.domain.com/path?_oob=eyJpZCI6IjViMjUwMjIzLWExNDItNDRmYi1hOWJkLWU1MjBlNGI0ZjQzMiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzIuMC9pbnZpdGF0aW9uIiwiZnJvbSI6ImRpZDpwZWVyOjIuRXo2TFNkV0hWQ1BFOHc0NWZETjM4aUh0ZFJ6WGkyTFNqQmRSUjRGTmNOUm12VkNKcy5WejZNa2Z2aUI5S1F1OGlnNVZpeG1HZHM3dmdMNmoyUXNOUGFybkZaanBNQ0E5aHpQLlNleUowSWpvaVpHMGlMQ0p6SWpwN0luVnlhU0k2SW1oMGRIQTZMeTh4T1RJdU1UWTRMakV1TXpjNk9EQTNNQzlrYVdSamIyMXRJaXdpY2lJNlcxMHNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAiLCJib2R5Ijp7ImdvYWxfY29kZSI6InByZXNlbnQtdnAiLCJnb2FsIjoiUmVxdWVzdCBwcm9vZiBvZiB2YWNjaW5hdGlvbiBpbmZvcm1hdGlvbiIsImFjY2VwdCI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiIyYTZmOGM4NS05ZGE3LTRkMjQtOGRhNS0wYzliZDY5ZTBiMDEiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJpZCI6IjI1NTI5MTBiLWI0NmMtNDM3Yy1hNDdhLTlmODQ5OWI5ZTg0ZiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0uYXRhbGFwcmlzbS5pby9wcmVzZW50LXByb29mLzMuMC9yZXF1ZXN0LXByZXNlbnRhdGlvbiIsImJvZHkiOnsiZ29hbF9jb2RlIjoiUmVxdWVzdCBQcm9vZiBQcmVzZW50YXRpb24iLCJ3aWxsX2NvbmZpcm0iOmZhbHNlLCJwcm9vZl90eXBlcyI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiJiYWJiNTJmMS05NDUyLTQzOGYtYjk3MC0yZDJjOTFmZTAyNGYiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJvcHRpb25zIjp7ImNoYWxsZW5nZSI6IjExYzkxNDkzLTAxYjMtNGM0ZC1hYzM2LWIzMzZiYWI1YmRkZiIsImRvbWFpbiI6Imh0dHBzOi8vcHJpc20tdmVyaWZpZXIuY29tIn0sInByZXNlbnRhdGlvbl9kZWZpbml0aW9uIjp7ImlkIjoiMGNmMzQ2ZDItYWY1Ny00Y2E1LTg2Y2EtYTA1NTE1NjZlYzZmIiwiaW5wdXRfZGVzY3JpcHRvcnMiOltdfX19LCJmb3JtYXQiOiJwcmlzbS9qd3QifV0sInRoaWQiOiI1YjI1MDIyMy1hMTQyLTQ0ZmItYTliZC1lNTIwZTRiNGY0MzIiLCJmcm9tIjoiZGlkOnBlZXI6Mi5FejZMU2RXSFZDUEU4dzQ1ZkROMzhpSHRkUnpYaTJMU2pCZFJSNEZOY05SbXZWQ0pzLlZ6Nk1rZnZpQjlLUXU4aWc1Vml4bUdkczd2Z0w2ajJRc05QYXJuRlpqcE1DQTloelAuU2V5SjBJam9pWkcwaUxDSnpJanA3SW5WeWFTSTZJbWgwZEhBNkx5OHhPVEl1TVRZNExqRXVNemM2T0RBM01DOWthV1JqYjIxdElpd2ljaUk2VzEwc0ltRWlPbHNpWkdsa1kyOXRiUzkyTWlKZGZYMCJ9fX1dLCJjcmVhdGVkX3RpbWUiOjE3MjQzMzkxNDQsImV4cGlyZXNfdGltZSI6MTcyNDMzOTQ0NH0" + val oob = agent.parseInvitation(outOfBandUrl) + assertTrue(oob is OutOfBandInvitation) + oob as OutOfBandInvitation + + doReturn(DID("did:peer:asdf")).`when`(agent).createNewPeerDID(updateMediator = true) + assertFailsWith(EdgeAgentError.ExpiredInvitation::class) { + agent.acceptOutOfBandInvitation(oob) + } + } + + @Test + fun `test connectionless Presentation request correctly`() = runTest { + val agent = spy( + EdgeAgent( + apollo = apolloMock, + castor = castorMock, + pluto = plutoMock, + mercury = mercuryMock, + pollux = polluxMock, + connectionManager = connectionManagerMock, + seed = seed, + api = null, + logger = PrismLoggerMock() + ) + ) + + val notExpiredTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(30) + val notExpiredInvitation = + """{"id":"5b250223-a142-44fb-a9bd-e520e4b4f432","type":"https://didcomm.org/out-of-band/2.0/invitation","from":"did:peer:2.Ez6LSdWHVCPE8w45fDN38iHtdRzXi2LSjBdRR4FNcNRmvVCJs.Vz6MkfviB9KQu8ig5VixmGds7vgL6j2QsNParnFZjpMCA9hzP.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHA6Ly8xOTIuMTY4LjEuMzc6ODA3MC9kaWRjb21tIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfX0","body":{"goal_code":"present-vp","goal":"Request proof of vaccination information","accept":[]},"attachments":[{"id":"2a6f8c85-9da7-4d24-8da5-0c9bd69e0b01","media_type":"application/json","data":{"json":{"id":"2552910b-b46c-437c-a47a-9f8499b9e84f","type":"https://didcomm.atalaprism.io/present-proof/3.0/request-presentation","body":{"goal_code":"Request Proof Presentation","will_confirm":false,"proof_types":[]},"attachments":[{"id":"babb52f1-9452-438f-b970-2d2c91fe024f","media_type":"application/json","data":{"json":{"options":{"challenge":"11c91493-01b3-4c4d-ac36-b336bab5bddf","domain":"https://prism-verifier.com"},"presentation_definition":{"id":"0cf346d2-af57-4ca5-86ca-a0551566ec6f","input_descriptors":[]}}},"format":"prism/jwt"}],"thid":"5b250223-a142-44fb-a9bd-e520e4b4f432","from":"did:peer:2.Ez6LSdWHVCPE8w45fDN38iHtdRzXi2LSjBdRR4FNcNRmvVCJs.Vz6MkfviB9KQu8ig5VixmGds7vgL6j2QsNParnFZjpMCA9hzP.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHA6Ly8xOTIuMTY4LjEuMzc6ODA3MC9kaWRjb21tIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfX0"}}}],"created_time":1724339144,"expires_time":$notExpiredTime}""" + val base64Invitation = notExpiredInvitation.base64UrlEncoded + + val outOfBandUrl = "https://my.domain.com/path?_oob=$base64Invitation" + val oob = agent.parseInvitation(outOfBandUrl) + assertTrue(oob is OutOfBandInvitation) + oob as OutOfBandInvitation + + doReturn(DID("did:peer:asdf")).`when`(agent).createNewPeerDID(updateMediator = true) + agent.acceptOutOfBandInvitation(oob) + val captor = argumentCaptor() + verify(plutoMock).storeMessage(captor.capture()) + val msg = captor.lastValue + assertEquals(ProtocolType.DidcommRequestPresentation.value, msg.piuri) + assertEquals("5b250223-a142-44fb-a9bd-e520e4b4f432", msg.thid) + val attachments = msg.attachments + assertEquals(1, attachments.size) + val attachmentJsonData = attachments.first().data + assertTrue(attachmentJsonData is AttachmentData.AttachmentJsonData) + val json = Json.parseToJsonElement(attachmentJsonData.getDataAsJsonString()) + assertTrue(json.jsonObject.containsKey("options")) + assertTrue(json.jsonObject.containsKey("presentation_definition")) + } + val getCredentialDefinitionResponse = "{\"schemaId\":\"http://host.docker.internal:8000/prism-agent/schema-registry/schemas/5e0d5a93-4bfd-3111-a956-5d5bc82f76cc\",\"type\":\"CL\",\"tag\":\"licence\",\"value\":{\"primary\":{\"n\":\"105195159277979097653318357586659371305119697478469834190626350283715795188687389523188659352120689851168860621983864738336838773213022505168653440146374011050277159372491059901432822905781969400722059341786498751125483895348734607382548396665339315322605154516776326303787844694026898270194867398625429469096229269732265502538641116512214652017416624138065704599041020588805936844771273861390913500753293895219370960892829297672575154196820931047049021760519166121287056337193413235473255257349024671869248216238831094979209384406168241010010012567685965827447177652200129684927663161550376084422586141212281146491949\",\"s\":\"85376740935726732134199731472843597191822272986425414914465211197069650618238336366149699822721009443794877925725075553195071288777117865451699414058058985000654277974066307286552934230286237253977472401290858765904161191229985245519871949378628131263513153683765553672655918133136828182050729012388157183851720391379381006921499997765191873729408614024320763554099291141052786589157823043612948619201525441997065264492145372001259366749278235381762443117203343617927241093647322654346302447381494008414208398219626199373278313446814209403507903682881070548386699522575055488393512785511441688197244526708647113340516\",\"r\":{\"dateofissuance\":\"16159515692057558658031632775257139859912833740243870833808276956469677196577164655991169139545328065546186056342530531355718904597216453319851305621683589202769847381737819412615902541110462703838858425423753481085962114120185123089078513531045426316918036549403698066078445947881055316312848598741184161901260446303171175343050250045452903485086185722998336149005743485268486377824763449026501058416292877646187105446333888525480394665310217044483841168928926515929150167890936706159800372381200383816724043496032886366767166850459338411710056171379538841845247931898550165532492578625954615979453881721709564750235\",\"drivingclass\":\"83649701835078373520097916558245060224505938113940626586910000950978790663411517512280043632278010831292224659523658613504637416710001103641231226266903556936380105758523760424939825687213460920436570466066231912959327201876189240504388424799892400351592593406285436824571943165913587899115814843543998396726679289422080229750418336051741708013580146373647528674381958028243228435161765957312248113519708734663989428761879029086059388435772829434952754093999424834120341657211221855300108096057633128467059590470639772605075954658131680801785637700237403873940041665483384938586320674338994185073499523485570537331062\",\"emailaddress\":\"96995643129591814391344614133120459563648002327749700279517548454036811217735867585059116635583558148259032071807493674533230465312311981127622542797279917256478867847832932893748528200469349058284133058865149153179959849308383505167342565738382180666525211256221655129861213392455759272915565057394420728271409215556596974900718332893753172173500744392522771654048192448229319313386967045678744665093451560743782910263014930200762027209565313884859542996067229707388839912195826334964819133016500346618083969320902775088800287566711941842968839787149808739739233388585677095545116231323172342995837636586249573194609\",\"drivinglicenseid\":\"102840929811153624977554462471309185033977661854754815794111114507549576719389525167082631547450413573293352276930065480432301200611396989595571202142654033217842162456070556560693402484110499573693863745648118310258284468114751958738878996458420605301017450868522680454545537837403398645500541915771765220093329728663621098538954397330411649083351383375839056527007892276284168437065687748085384178113959961057476582871100422859953560730152958588610850909069434658487744782540788968302663076149478487413357533660817020800754493642858564081116318655661240523146995256712471572605700346459123074377380656921337264554594\",\"familyname\":\"2428690037146701497427424649573806616639612325136606164619283916796880313617677563507218774958436668407050506838114136163250163675016510113975582318007560622124292458766639319715064358235569650961433812439763343736699708535945693241909905707497180931492818502593885932421170612418693515054756633264933222189766691632082890045477718331705366111669009551578289182848340651375008362238266590844461708981816856194045325523248527964502118319210042254240848590574645476930113881493472578612352948284862674703949781070309344526122291448990325949065193279599181502524961004046979227803224474342778516917124487012958845744311\",\"master_secret\":\"96236339155824229583363924057798366491998077727991424922911165403434522806469328114407334094535810942859512352089785125683335350062474092708044674085769524387654467267128528564551803293661877480971961092735622606052503557881856409855812611523475975566606131897917979412576797874632169829901968854843162299366867885636535326810998541141840561418097240137120398317445832694001031827068485975315937269024666370665530455146256019590700349556357390218401217383173228376078058967743472704019765210324846681867991543267171763037513180046865961560351035005185946817643006206395175857900512245900162751815626427008481585714891\"},\"rctxt\":\"54359809198312125478916383106913469635175253891208897419510030559787479974126666313900084654632259260010008369569778456071591398552341004538623276997178295939490854663263886825856426285604332554317424030793691008221895556474599466123873279022389276698551452690414982831059651505731449763128921782866843113361548859434294057249048041670761184683271568216202174527891374770703485794299697663353847310928998125365841476766767508733046891626759537001358973715760759776149482147060701775948253839125589216812475133616408444838011643485797584321993661048373877626880635937563283836661934456534313802815974883441215836680800\",\"z\":\"99592262675748359673042256590146366586480829950402370244401571195191609039150608482506917768910598228167758026656953725016982562881531475875469671976107506976812319765644401707559997823702387678953647104105378063905395973550729717937712350758544336716556268064226491839700352305793370980462034813589488455836259737325502578253339820590260554457468082536249525493340350556649403477875367398139579018197084796440810685458274393317299082017275568964540311198115802021902455672385575542594821996060452628805634468222196284384514736044680778624637228114693554834388824212714580770066729185685978935409859595244639193538156\"}},\"issuerId\":\"did:prism:604ba1764ab89993f9a74625cc4f3e04737919639293eb382cc7adc53767f550\"}" diff --git a/sampleapp/src/main/java/org/hyperledger/identus/walletsdk/sampleapp/ui/contacts/ContactsViewModel.kt b/sampleapp/src/main/java/org/hyperledger/identus/walletsdk/sampleapp/ui/contacts/ContactsViewModel.kt index 46b695b88..902a3ce6e 100644 --- a/sampleapp/src/main/java/org/hyperledger/identus/walletsdk/sampleapp/ui/contacts/ContactsViewModel.kt +++ b/sampleapp/src/main/java/org/hyperledger/identus/walletsdk/sampleapp/ui/contacts/ContactsViewModel.kt @@ -36,18 +36,22 @@ class ContactsViewModel(application: Application) : AndroidViewModel(application fun parseAndAcceptOOB(oobUrl: String) { Sdk.getInstance().agent.let { agent -> viewModelScope.launch { - when (val invitation = agent.parseInvitation(oobUrl)) { - is OutOfBandInvitation -> { - agent.acceptOutOfBandInvitation(invitation) - } + try { + when (val invitation = agent.parseInvitation(oobUrl)) { + is OutOfBandInvitation -> { + agent.acceptOutOfBandInvitation(invitation) + } - is PrismOnboardingInvitation -> { - agent.acceptInvitation(invitation) - } + is PrismOnboardingInvitation -> { + agent.acceptInvitation(invitation) + } - else -> { - throw EdgeAgentError.UnknownInvitationTypeError(invitation.toString()) + else -> { + throw EdgeAgentError.UnknownInvitationTypeError(invitation.toString()) + } } + } catch (e: Exception) { + println("Exception: ${e.message}") } } } diff --git a/sampleapp/src/main/res/values/strings.xml b/sampleapp/src/main/res/values/strings.xml index e01d620c2..8d3555fcb 100644 --- a/sampleapp/src/main/res/values/strings.xml +++ b/sampleapp/src/main/res/values/strings.xml @@ -31,7 +31,7 @@ Mediator DID: Agent status: - did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHA6Ly8xOTIuMTY4LjY4LjExMzo4MDgwIiwiYSI6WyJkaWRjb21tL3YyIl19fQ + did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHA6Ly8xOTIuMTY4LjY4LjExMzo4MDgwIiwiYSI6WyJkaWRjb21tL3YyIl19fQ.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6IndzOi8vMTkyLjE2OC42OC4xMTM6ODA4MC93cyIsImEiOlsiZGlkY29tbS92MiJdfX0 Credentials Host: