From e05d36b9da6dbdfaf1585288d6be3e9941a4994c Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Thu, 14 Dec 2023 16:06:55 +0200 Subject: [PATCH 1/7] Check that the DID is consistent between the Deep Link and all messages received from the counterparty --- VCL/build.gradle | 4 +- .../api/entities/VCLCredentialManifest.kt | 60 +++++++------- .../VCLCredentialManifestDescriptor.kt | 3 +- ...LCredentialManifestDescriptorByDeepLink.kt | 3 +- .../entities/VCLFinalizeOffersDescriptor.kt | 3 +- .../entities/VCLGenerateOffersDescriptor.kt | 3 +- .../api/entities/VCLOffer.kt | 22 +++++ .../api/entities/VCLOffers.kt | 2 +- .../api/entities/error/VCLErrorCode.kt | 7 +- .../impl/VclBlocksProvider.kt | 17 +++- .../FinalizeOffersRepositoryImpl.kt | 11 +-- .../GenerateOffersRepositoryImpl.kt | 19 +++-- .../usecases/CredentialManifestUseCaseImpl.kt | 80 +++++++++++++------ .../usecases/FinalizeOffersUseCaseImpl.kt | 78 +++++++++++++----- .../usecases/GenerateOffersUseCaseImpl.kt | 46 ++++++++++- .../PresentationRequestUseCaseImpl.kt | 61 ++++++-------- .../impl/data/utils/Utils.kt | 13 +++ .../CredentialDidVerifierImpl.kt | 26 +++--- .../CredentialIssuerVerifierEmptyImpl.kt | 7 +- .../CredentialIssuerVerifierImpl.kt | 21 +++-- ...redentialManifestByDeepLinkVerifierImpl.kt | 28 +++++++ .../CredentialsByDeepLinkVerifierImpl.kt | 30 +++++++ .../verifiers/OffersByDeepLinkVerifierImpl.kt | 29 +++++++ ...esentationRequestByDeepLinkVerifierImpl.kt | 30 +++++++ .../repositories/FinalizeOffersRepository.kt | 2 +- .../CredentialDidVerifier.kt | 5 +- .../CredentialIssuerVerifier.kt | 5 +- .../CredentialManifestByDeepLinkVerifier.kt | 19 +++++ .../CredentialsByDeepLinkVerifier.kt | 19 +++++ .../verifiers/OffersByDeepLinkVerifier.kt | 19 +++++ .../PresentationRequestByDeepLinkVerifier.kt | 19 +++++ .../impl/extensions/StringExtensions.kt | 20 +++++ .../entities/VCLCredentialManifestTest.kt | 4 +- .../VCLFinalizeOffersDescriptorTest.kt | 2 +- .../resources/valid/GenerateOffersMocks.kt | 7 +- .../usecases/CredentialManifestUseCaseTest.kt | 2 + .../usecases/FinalizeOffersUseCaseTest.kt | 11 ++- .../usecases/GenerateOffersUseCaseTest.kt | 4 + .../PresentationRequestUseCaseTest.kt | 3 +- .../CredentialDidVerifierTest.kt | 20 +++-- .../CredentialIssuerVerifierTest.kt | 42 ++++------ ...redentialManifestByDeepLinkVerifierTest.kt | 59 ++++++++++++++ .../CredentialsByDeepLinkVerifierTest.kt | 58 ++++++++++++++ .../verifiers/OffersByDeepLinkVerifierTest.kt | 68 ++++++++++++++++ ...esentationRequestByDeepLinkVerifierTest.kt | 46 +++++++++++ .../ProfileServiceTypeVerifierTest.kt | 2 +- app/src/main/java/com/vcl/wallet/Utils.kt | 4 +- 47 files changed, 823 insertions(+), 220 deletions(-) create mode 100644 VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffer.kt rename VCL/src/main/java/io/velocitycareerlabs/impl/data/{utils => verifiers}/CredentialDidVerifierImpl.kt (63%) rename VCL/src/main/java/io/velocitycareerlabs/impl/data/{utils => verifiers}/CredentialIssuerVerifierEmptyImpl.kt (78%) rename VCL/src/main/java/io/velocitycareerlabs/impl/data/{utils => verifiers}/CredentialIssuerVerifierImpl.kt (95%) create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt rename VCL/src/main/java/io/velocitycareerlabs/impl/domain/{utils => verifiers}/CredentialDidVerifier.kt (79%) rename VCL/src/main/java/io/velocitycareerlabs/impl/domain/{utils => verifiers}/CredentialIssuerVerifier.kt (76%) create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialManifestByDeepLinkVerifier.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialsByDeepLinkVerifier.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/OffersByDeepLinkVerifier.kt create mode 100644 VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/PresentationRequestByDeepLinkVerifier.kt rename VCL/src/test/java/io/velocitycareerlabs/{utils => verifiers}/CredentialDidVerifierTest.kt (89%) rename VCL/src/test/java/io/velocitycareerlabs/{utils => verifiers}/CredentialIssuerVerifierTest.kt (88%) create mode 100644 VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialManifestByDeepLinkVerifierTest.kt create mode 100644 VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialsByDeepLinkVerifierTest.kt create mode 100644 VCL/src/test/java/io/velocitycareerlabs/verifiers/OffersByDeepLinkVerifierTest.kt create mode 100644 VCL/src/test/java/io/velocitycareerlabs/verifiers/PresentationRequestByDeepLinkVerifierTest.kt rename VCL/src/test/java/io/velocitycareerlabs/{utils => verifiers}/ProfileServiceTypeVerifierTest.kt (99%) diff --git a/VCL/build.gradle b/VCL/build.gradle index 05944349..07959df6 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.21.0" - versionCode 116 + versionName "1.22.0" + versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt index 40dbd818..4dd896a6 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt @@ -7,40 +7,46 @@ package io.velocitycareerlabs.api.entities -import io.velocitycareerlabs.impl.extensions.getUrlSubPath -import kotlin.io.path.ExperimentalPathApi - data class VCLCredentialManifest( val jwt: VCLJwt, val vendorOriginContext: String? = null, - val verifiedProfile: VCLVerifiedProfile + val verifiedProfile: VCLVerifiedProfile, + val deepLink: VCLDeepLink? = null ) { val iss: String get() = jwt.payload?.toJSONObject()?.get(KeyIss) as? String ?: "" - val did: String get() = iss - val issuerId: String get() = retrieveIssuerId() + val aud: String get() = retrieveAud() + val issuerId: String get() = jwt.payload?.toJSONObject()?.get(CodingKeys.KeyIssuer) as? String + ?: (jwt.payload?.toJSONObject()?.get(CodingKeys.KeyIssuer) as? Map<*, *>)?.get(CodingKeys.KeyId) as? String + ?: "" val exchangeId: String get() = jwt.payload?.toJSONObject()?.get(KeyExchangeId) as? String ?: "" - val presentationDefinitionId: String get() = (jwt.payload?.toJSONObject()?.get(KeyPresentationDefinitionId) as? Map<*, *>)?.get( - KeyId) as? String ?: "" - - val finalizeOffersUri: String get() = - (jwt.payload?.toJSONObject()?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( - VCLCredentialManifest.KeyFinalizeOffersUri - )?.toString() ?: "" - - val checkOffersUri: String get() = - (jwt.payload?.toJSONObject()?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( - VCLCredentialManifest.KeyCheckOffersUri - )?.toString() ?: "" - - val submitPresentationUri: String get() = - (jwt.payload?.toJSONObject()?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( - VCLCredentialManifest.KeySubmitIdentificationUri - )?.toString() ?: "" - - @OptIn(ExperimentalStdlibApi::class) - private fun retrieveIssuerId() = - ((jwt.payload?.toJSONObject()?.getOrDefault(CodingKeys.KeyMetadata, HashMap()) as? Map )?.getOrDefault(CodingKeys.KeyFinalizeOffersUri, "") as? String ?: "").substringBefore("/issue/") + val presentationDefinitionId: String + get() = (jwt.payload?.toJSONObject()?.get(KeyPresentationDefinitionId) as? Map<*, *>)?.get( + KeyId + ) as? String ?: "" + + val finalizeOffersUri: String + get() = + (jwt.payload?.toJSONObject() + ?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( + VCLCredentialManifest.KeyFinalizeOffersUri + )?.toString() ?: "" + val checkOffersUri: String + get() = + (jwt.payload?.toJSONObject() + ?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( + VCLCredentialManifest.KeyCheckOffersUri + )?.toString() ?: "" + + val submitPresentationUri: String + get() = + (jwt.payload?.toJSONObject() + ?.get(VCLCredentialManifest.KeyMetadata) as? Map<*, *>)?.get( + VCLCredentialManifest.KeySubmitIdentificationUri + )?.toString() ?: "" + + private fun retrieveAud() = + ((jwt.payload?.toJSONObject()?.getOrDefault(CodingKeys.KeyMetadata, HashMap()) as? Map )?.getOrDefault(CodingKeys.KeyFinalizeOffersUri, "") as? String ?: "").substringBefore("/issue/") companion object CodingKeys { const val KeyIssuingRequest = "issuing_request" diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptor.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptor.kt index e6d4bd00..b2fd6715 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptor.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptor.kt @@ -14,7 +14,8 @@ open class VCLCredentialManifestDescriptor( val issuingType: VCLIssuingType = VCLIssuingType.Career, val credentialTypes: List? = null, val pushDelegate: VCLPushDelegate? = null, - val vendorOriginContext: String? = null + val vendorOriginContext: String? = null, + val deepLink: VCLDeepLink? = null ) { val did = uri?.getUrlSubPath(KeyDidPrefix) diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptorByDeepLink.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptorByDeepLink.kt index 55804434..7fa11ac4 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptorByDeepLink.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifestDescriptorByDeepLink.kt @@ -13,5 +13,6 @@ class VCLCredentialManifestDescriptorByDeepLink( ): VCLCredentialManifestDescriptor( uri = deepLink.requestUri, issuingType = issuingType, - vendorOriginContext = deepLink.vendorOriginContext + vendorOriginContext = deepLink.vendorOriginContext, + deepLink = deepLink ) \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLFinalizeOffersDescriptor.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLFinalizeOffersDescriptor.kt index 0f47f8fc..e19caa1f 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLFinalizeOffersDescriptor.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLFinalizeOffersDescriptor.kt @@ -4,7 +4,6 @@ * Copyright 2022 Velocity Career Labs inc. * SPDX-License-Identifier: Apache-2.0 */ - package io.velocitycareerlabs.api.entities import io.velocitycareerlabs.impl.extensions.toJsonArray @@ -22,8 +21,8 @@ data class VCLFinalizeOffersDescriptor( .putOpt(KeyApprovedOfferIds, approvedOfferIds.toJsonArray()) .putOpt(KeyRejectedOfferIds, rejectedOfferIds.toJsonArray()) - val did: String get() = credentialManifest.did val issuerId: String get() = credentialManifest.issuerId + val aud: String get() = credentialManifest.aud val exchangeId: String get() = credentialManifest.exchangeId val finalizeOffersUri: String get() = credentialManifest.finalizeOffersUri val serviceTypes: VCLServiceTypes get() = credentialManifest.verifiedProfile.serviceTypes diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLGenerateOffersDescriptor.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLGenerateOffersDescriptor.kt index d0bc7fd8..78cc0ab6 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLGenerateOffersDescriptor.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLGenerateOffersDescriptor.kt @@ -22,9 +22,8 @@ data class VCLGenerateOffersDescriptor( .putOpt(KeyTypes,types?.toJsonArray()) .putOpt(KeyOfferHashes,offerHashes?.toJsonArray()) - val did: String get() = credentialManifest.did + val issuerId: String get() = credentialManifest.issuerId val exchangeId: String get() = credentialManifest.exchangeId - val checkOffersUri: String get() = credentialManifest.checkOffersUri companion object CodingKeys { diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffer.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffer.kt new file mode 100644 index 00000000..0870ad06 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffer.kt @@ -0,0 +1,22 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.api.entities + +import org.json.JSONObject + +data class VCLOffer(val payload: JSONObject) { + val issuerId: String get() = payload.optJSONObject(CodingKeys.KeyIssuer)?.optString(KeyId) + ?: payload.optString(CodingKeys.KeyIssuer) + ?: "" + val id: String get() = payload.optString(CodingKeys.KeyId) ?: "" + + companion object CodingKeys { + const val KeyId = "id" + const val KeyDid = "did" + const val KeyIssuer = "issuer" + } +} diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffers.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffers.kt index 5fd3bb7c..89ea8295 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffers.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLOffers.kt @@ -12,7 +12,7 @@ import org.json.JSONObject data class VCLOffers ( val payload: JSONObject, - val all: JSONArray, + val all: List, val responseCode: Int, val sessionToken: VCLToken, val challenge: String, diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/error/VCLErrorCode.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/error/VCLErrorCode.kt index f4cf43d4..874c4d00 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/error/VCLErrorCode.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/error/VCLErrorCode.kt @@ -17,5 +17,10 @@ internal enum class VCLErrorCode(val value: String) { IssuerRequiresNotaryPermission("issuer_requires_notary_permission"), InvalidCredentialSubjectType("invalid_credential_subject_type"), InvalidCredentialSubjectContext("invalid_credential_subject_context"), - IssuerUnexpectedPermissionFailure("issuer_unexpected_permission_failure") + IssuerUnexpectedPermissionFailure("issuer_unexpected_permission_failure"), + // DID consistent with the Deep Link + MismatchedRequestIssuerDid("mismatched_request_issuer_did"), + MismatchedOfferIssuerDid("mismatched_offer_issuer_did"), + MismatchedCredentialIssuerDid("mismatched_credential_issuer_did"), + MismatchedPresentationRequestInspectorDid("mismatched_presentation_request_inspector_did") } \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/VclBlocksProvider.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/VclBlocksProvider.kt index 5aa3fe5b..3c005032 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/VclBlocksProvider.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/VclBlocksProvider.kt @@ -13,7 +13,7 @@ import io.velocitycareerlabs.api.entities.VCLCredentialTypes import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.api.entities.error.VCLErrorCode import io.velocitycareerlabs.api.entities.initialization.VCLCryptoServicesDescriptor -import io.velocitycareerlabs.impl.data.utils.CredentialDidVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialDidVerifierImpl import io.velocitycareerlabs.impl.data.infrastructure.db.CacheServiceImpl import io.velocitycareerlabs.impl.data.infrastructure.db.SecretStoreServiceImpl import io.velocitycareerlabs.impl.data.infrastructure.network.NetworkServiceImpl @@ -25,11 +25,16 @@ import io.velocitycareerlabs.impl.data.usecases.* import io.velocitycareerlabs.api.jwt.VCLJwtSignService import io.velocitycareerlabs.api.jwt.VCLJwtVerifyService import io.velocitycareerlabs.api.keys.VCLKeyService -import io.velocitycareerlabs.impl.data.utils.CredentialIssuerVerifierEmptyImpl -import io.velocitycareerlabs.impl.data.utils.CredentialIssuerVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierEmptyImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialManifestByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialsByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.OffersByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.PresentationRequestByDeepLinkVerifierImpl import io.velocitycareerlabs.impl.domain.models.* import io.velocitycareerlabs.impl.domain.usecases.* -import io.velocitycareerlabs.impl.domain.utils.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.PresentationRequestByDeepLinkVerifier import io.velocitycareerlabs.impl.jwt.local.VCLJwtSignServiceLocalImpl import io.velocitycareerlabs.impl.jwt.local.VCLJwtVerifyServiceLocalImpl import io.velocitycareerlabs.impl.jwt.remote.VCLJwtSignServiceRemoteImpl @@ -169,6 +174,7 @@ internal object VclBlocksProvider { chooseJwtSignService(context, cryptoServicesDescriptor), chooseJwtVerifyService(cryptoServicesDescriptor) ), + PresentationRequestByDeepLinkVerifierImpl(), ExecutorImpl() ) @@ -212,6 +218,7 @@ internal object VclBlocksProvider { chooseJwtSignService(context, cryptoServicesDescriptor), chooseJwtVerifyService(cryptoServicesDescriptor) ), + CredentialManifestByDeepLinkVerifierImpl(), ExecutorImpl() ) @@ -244,6 +251,7 @@ internal object VclBlocksProvider { GenerateOffersRepositoryImpl( NetworkServiceImpl() ), + OffersByDeepLinkVerifierImpl(), ExecutorImpl() ) @@ -272,6 +280,7 @@ internal object VclBlocksProvider { ), credentialIssuerVerifier, CredentialDidVerifierImpl(), + CredentialsByDeepLinkVerifierImpl(), ExecutorImpl() ) } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/FinalizeOffersRepositoryImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/FinalizeOffersRepositoryImpl.kt index 344f2c5e..41541665 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/FinalizeOffersRepositoryImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/FinalizeOffersRepositoryImpl.kt @@ -12,9 +12,12 @@ import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.impl.data.infrastructure.network.Request import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService import io.velocitycareerlabs.impl.domain.repositories.FinalizeOffersRepository +import io.velocitycareerlabs.impl.extensions.toJsonArray +import io.velocitycareerlabs.impl.extensions.toJwtList import io.velocitycareerlabs.impl.extensions.toList import org.json.JSONArray import java.lang.Exception +import java.util.concurrent.CompletableFuture internal class FinalizeOffersRepositoryImpl( private val networkService: NetworkService @@ -25,7 +28,7 @@ internal class FinalizeOffersRepositoryImpl( finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, sessionToken: VCLToken, proof: VCLJwt, - completionBlock: (VCLResult>) -> Unit + completionBlock: (VCLResult>) -> Unit ) { networkService.sendRequest( endpoint = finalizeOffersDescriptor.finalizeOffersUri, @@ -40,14 +43,12 @@ internal class FinalizeOffersRepositoryImpl( result.handleResult( { finalizedOffersResponse -> try { - val encodedJwts = - JSONArray(finalizedOffersResponse.payload).toList() as? List - encodedJwts?.let { + finalizedOffersResponse.payload.toJwtList()?.let { completionBlock(VCLResult.Success(it)) } ?: run { completionBlock( VCLResult.Failure( - VCLError("Failed to parse: $finalizedOffersResponse.payload") + VCLError("Failed to parse: ${finalizedOffersResponse.payload}") ) ) } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/GenerateOffersRepositoryImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/GenerateOffersRepositoryImpl.kt index abc524d5..8dd2de4d 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/GenerateOffersRepositoryImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/repositories/GenerateOffersRepositoryImpl.kt @@ -11,6 +11,7 @@ import io.velocitycareerlabs.api.entities.* import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.impl.data.infrastructure.network.Request import io.velocitycareerlabs.impl.data.infrastructure.network.Response +import io.velocitycareerlabs.impl.data.utils.Utils import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService import io.velocitycareerlabs.impl.domain.repositories.GenerateOffersRepository import io.velocitycareerlabs.impl.extensions.toJsonArray @@ -42,9 +43,11 @@ internal class GenerateOffersRepositoryImpl( result.handleResult( { offersResponse -> try { - completionBlock(VCLResult.Success( - parse(offersResponse, sessionToken) - )) + completionBlock( + VCLResult.Success( + parse(offersResponse, sessionToken) + ) + ) } catch (ex: Exception) { completionBlock(VCLResult.Failure(VCLError(ex))) } @@ -62,17 +65,19 @@ internal class GenerateOffersRepositoryImpl( offersResponse.payload.toJsonObject()?.let { payload -> return VCLOffers( payload = payload, - all = payload.optJSONArray(VCLOffers.CodingKeys.KeyOffers) ?: JSONArray(), + all = Utils.offersFromJsonArray( + payload.optJSONArray(VCLOffers.CodingKeys.KeyOffers) ?: JSONArray() + ), responseCode = offersResponse.code, sessionToken = sessionToken, challenge = payload.optString(VCLOffers.CodingKeys.KeyChallenge) ?: "" ) } ?: run { // VCLXVnfProtocolVersion.XVnfProtocolVersion1 - offersResponse.payload.toJsonArray()?.let { allOffers -> + offersResponse.payload.toJsonArray()?.let { offersJsonArray -> return VCLOffers( payload = JSONObject(), - all = allOffers, + all = Utils.offersFromJsonArray(offersJsonArray), responseCode = offersResponse.code, sessionToken = sessionToken, challenge = "" @@ -81,7 +86,7 @@ internal class GenerateOffersRepositoryImpl( // No offers return VCLOffers( payload = JSONObject(), - all = JSONArray(), + all = listOf(), responseCode = offersResponse.code, sessionToken = sessionToken, challenge = "" diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/CredentialManifestUseCaseImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/CredentialManifestUseCaseImpl.kt index d2196708..e18141a5 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/CredentialManifestUseCaseImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/CredentialManifestUseCaseImpl.kt @@ -14,15 +14,20 @@ import io.velocitycareerlabs.impl.domain.repositories.CredentialManifestReposito import io.velocitycareerlabs.impl.domain.repositories.JwtServiceRepository import io.velocitycareerlabs.impl.domain.repositories.ResolveKidRepository import io.velocitycareerlabs.impl.domain.usecases.CredentialManifestUseCase +import io.velocitycareerlabs.impl.domain.verifiers.CredentialManifestByDeepLinkVerifier import io.velocitycareerlabs.impl.extensions.encode +import io.velocitycareerlabs.impl.utils.VCLLog internal class CredentialManifestUseCaseImpl( private val credentialManifestRepository: CredentialManifestRepository, private val resolveKidRepository: ResolveKidRepository, private val jwtServiceRepository: JwtServiceRepository, + private val credentialManifestByDeepLinkVerifier: CredentialManifestByDeepLinkVerifier, private val executor: Executor ): CredentialManifestUseCase { + private val TAG = CredentialManifestUseCaseImpl::class.simpleName + override fun getCredentialManifest( credentialManifestDescriptor: VCLCredentialManifestDescriptor, verifiedProfile: VCLVerifiedProfile, @@ -37,9 +42,12 @@ internal class CredentialManifestUseCaseImpl( { jwtStr -> try { onGetCredentialManifestSuccess( - VCLJwt(jwtStr), - credentialManifestDescriptor, - verifiedProfile, + VCLCredentialManifest( + VCLJwt(jwtStr), + credentialManifestDescriptor.vendorOriginContext, + verifiedProfile, + credentialManifestDescriptor.deepLink + ), remoteCryptoServicesToken, completionBlock ) @@ -56,21 +64,48 @@ internal class CredentialManifestUseCaseImpl( } private fun onGetCredentialManifestSuccess( - jwt: VCLJwt, - credentialManifestDescriptor: VCLCredentialManifestDescriptor, - verifiedProfile: VCLVerifiedProfile, + credentialManifest: VCLCredentialManifest, remoteCryptoServicesToken: VCLToken?, completionBlock: (VCLResult) -> Unit ) { - jwt.kid?.replace("#", "#".encode())?.let { kid -> + credentialManifest.deepLink?.let { deepLink -> + credentialManifestByDeepLinkVerifier.verifyCredentialManifest(credentialManifest, deepLink) { + it.handleResult( + { isVerified -> + VCLLog.d(TAG, "Credential manifest deep link verification result: $isVerified") + onCredentialManifestDidVerificationSuccess( + credentialManifest, + remoteCryptoServicesToken, + completionBlock + ) + }, + { error -> + onError(error, completionBlock) + } + ) + } + } ?: run { + VCLLog.d(TAG, "Deep link was not provided => nothing to verify") + onCredentialManifestDidVerificationSuccess( + credentialManifest, + remoteCryptoServicesToken, + completionBlock + ) + } + } + + private fun onCredentialManifestDidVerificationSuccess( + credentialManifest: VCLCredentialManifest, + remoteCryptoServicesToken: VCLToken?, + completionBlock: (VCLResult) -> Unit + ) { + credentialManifest.jwt.kid?.replace("#", "#".encode())?.let { kid -> resolveKidRepository.getPublicKey(kid) { publicKeyResult -> publicKeyResult.handleResult( { publicKey -> onResolvePublicKeySuccess( publicKey, - jwt, - credentialManifestDescriptor, - verifiedProfile, + credentialManifest, remoteCryptoServicesToken, completionBlock ) @@ -87,14 +122,12 @@ internal class CredentialManifestUseCaseImpl( private fun onResolvePublicKeySuccess( publicJwk: VCLPublicJwk, - jwt: VCLJwt, - credentialManifestDescriptor: VCLCredentialManifestDescriptor, - verifiedProfile: VCLVerifiedProfile, + credentialManifest: VCLCredentialManifest, remoteCryptoServicesToken: VCLToken?, completionBlock: (VCLResult) -> Unit ) { jwtServiceRepository.verifyJwt( - jwt, + credentialManifest.jwt, publicJwk, remoteCryptoServicesToken ) @@ -103,9 +136,7 @@ internal class CredentialManifestUseCaseImpl( { isVerified -> onVerificationSuccess( isVerified, - jwt, - credentialManifestDescriptor, - verifiedProfile, + credentialManifest, completionBlock ) }, @@ -118,21 +149,18 @@ internal class CredentialManifestUseCaseImpl( private fun onVerificationSuccess( isVerified: Boolean, - jwt: VCLJwt, - credentialManifestDescriptor: VCLCredentialManifestDescriptor, - verifiedProfile: VCLVerifiedProfile, + credentialManifest: VCLCredentialManifest, completionBlock: (VCLResult) -> Unit ) { if (isVerified) { executor.runOnMain { - completionBlock(VCLResult.Success(VCLCredentialManifest( - jwt, - credentialManifestDescriptor.vendorOriginContext, - verifiedProfile - ))) + completionBlock(VCLResult.Success(credentialManifest)) } } else { - onError(VCLError("Failed to verify: $jwt"), completionBlock) + onError( + VCLError("Failed to verify credentialManifest jwt:\n${credentialManifest.jwt}"), + completionBlock + ) } } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/FinalizeOffersUseCaseImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/FinalizeOffersUseCaseImpl.kt index 826a522b..78c5fb8f 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/FinalizeOffersUseCaseImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/FinalizeOffersUseCaseImpl.kt @@ -4,18 +4,19 @@ * Copyright 2022 Velocity Career Labs inc. * SPDX-License-Identifier: Apache-2.0 */ - package io.velocitycareerlabs.impl.data.usecases import io.velocitycareerlabs.api.entities.* import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor import io.velocitycareerlabs.api.entities.error.VCLError -import io.velocitycareerlabs.impl.domain.utils.CredentialDidVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialDidVerifier import io.velocitycareerlabs.impl.domain.infrastructure.executors.Executor import io.velocitycareerlabs.impl.domain.repositories.FinalizeOffersRepository import io.velocitycareerlabs.impl.domain.repositories.JwtServiceRepository import io.velocitycareerlabs.impl.domain.usecases.FinalizeOffersUseCase -import io.velocitycareerlabs.impl.domain.utils.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialsByDeepLinkVerifier +import io.velocitycareerlabs.impl.utils.VCLLog import java.util.UUID internal class FinalizeOffersUseCaseImpl( @@ -23,8 +24,11 @@ internal class FinalizeOffersUseCaseImpl( private val jwtServiceRepository: JwtServiceRepository, private val credentialIssuerVerifier: CredentialIssuerVerifier, private val credentialDidVerifier: CredentialDidVerifier, + private val credentialsByDeepLinkVerifier: CredentialsByDeepLinkVerifier, private val executor: Executor ): FinalizeOffersUseCase { + private val TAG = FinalizeOffersUseCaseImpl::class.simpleName + override fun finalizeOffers( finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, didJwk: VCLDidJwk?, @@ -39,7 +43,7 @@ internal class FinalizeOffersUseCaseImpl( jwtDescriptor = VCLJwtDescriptor( keyId = didJwk?.keyId, iss = didJwk?.did ?: UUID.randomUUID().toString(), - aud = finalizeOffersDescriptor.issuerId + aud = finalizeOffersDescriptor.aud ), remoteCryptoServicesToken = remoteCryptoServicesToken ) { proofJwtResult -> @@ -49,22 +53,33 @@ internal class FinalizeOffersUseCaseImpl( sessionToken = sessionToken, proof = proof, finalizeOffersDescriptor = finalizeOffersDescriptor - ) { encodedJwtCredentialsListResult -> - encodedJwtCredentialsListResult.handleResult( - successHandler = { encodedJwtCredentialsList -> - verifyCredentialsByIssuer( - encodedJwtCredentialsList, + ) { jwtCredentialsListResult -> + jwtCredentialsListResult.handleResult( + successHandler = { jwtCredentials -> + verifyCredentialsByDeepLink( + jwtCredentials, finalizeOffersDescriptor - ) { - it.handleResult( + ) { verifyCredentialsByDeepLinkResult -> + verifyCredentialsByDeepLinkResult.handleResult( successHandler = { - verifyCredentialByDid( - encodedJwtCredentialsList, + verifyCredentialsByIssuer( + jwtCredentials, finalizeOffersDescriptor - ) { jwtVerifiableCredentialsResult -> - executor.runOnMain { - completionBlock(jwtVerifiableCredentialsResult) - } + ) { verifyCredentialsByIssuerResult -> + verifyCredentialsByIssuerResult.handleResult({ + verifyCredentialByDid( + jwtCredentials, + finalizeOffersDescriptor + ) { jwtVerifiableCredentialsResult -> + executor.runOnMain { + completionBlock( + jwtVerifiableCredentialsResult + ) + } + } + }, { error -> + onError(error, completionBlock) + }) } }, errorHandler = { error -> @@ -84,14 +99,37 @@ internal class FinalizeOffersUseCaseImpl( } } } + + private fun verifyCredentialsByDeepLink( + jwtCredentials: List, + finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, + completionBlock: (VCLResult) -> Unit + ) { + finalizeOffersDescriptor.credentialManifest.deepLink?.let { deepLink -> + credentialsByDeepLinkVerifier.verifyCredentials( + jwtCredentials, + deepLink + ) { + it.handleResult({ isVerified -> + VCLLog.d(TAG, "Credentials by deep link verification result: $isVerified") + completionBlock(VCLResult.Success(true)) + }, { error -> + completionBlock(VCLResult.Failure(error)) + }) + } + } ?: run { + VCLLog.d(TAG, "Deep link was not provided => nothing to verify") + completionBlock(VCLResult.Success(true)) + } + } private fun verifyCredentialsByIssuer( - encodedJwtCredentialsList: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) { credentialIssuerVerifier.verifyCredentials( - encodedJwtCredentialsList, + jwtCredentials, finalizeOffersDescriptor ) { credentialIssuerVerifierResult -> credentialIssuerVerifierResult.handleResult( @@ -106,7 +144,7 @@ internal class FinalizeOffersUseCaseImpl( } private fun verifyCredentialByDid( - encodedJwtCredentialsList: List, + encodedJwtCredentialsList: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) { diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/GenerateOffersUseCaseImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/GenerateOffersUseCaseImpl.kt index 076c7dc2..23c08089 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/GenerateOffersUseCaseImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/GenerateOffersUseCaseImpl.kt @@ -4,18 +4,23 @@ * Copyright 2022 Velocity Career Labs inc. * SPDX-License-Identifier: Apache-2.0 */ - package io.velocitycareerlabs.impl.data.usecases import io.velocitycareerlabs.api.entities.* +import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.impl.domain.infrastructure.executors.Executor import io.velocitycareerlabs.impl.domain.repositories.GenerateOffersRepository import io.velocitycareerlabs.impl.domain.usecases.GenerateOffersUseCase +import io.velocitycareerlabs.impl.domain.verifiers.OffersByDeepLinkVerifier +import io.velocitycareerlabs.impl.utils.VCLLog internal class GenerateOffersUseCaseImpl( private val generateOffersRepository: GenerateOffersRepository, + private val offersByDeepLinkVerifier: OffersByDeepLinkVerifier, private val executor: Executor ): GenerateOffersUseCase { + private val TAG = GenerateOffersUseCaseImpl::class.simpleName + override fun generateOffers( generateOffersDescriptor: VCLGenerateOffersDescriptor, sessionToken: VCLToken, @@ -26,10 +31,43 @@ internal class GenerateOffersUseCaseImpl( generateOffersDescriptor, sessionToken ) { - executor.runOnMain { - completionBlock(it) - } + it.handleResult({ offers -> + verifyOffersByDeepLink(offers,generateOffersDescriptor, completionBlock) + },{ error -> + onError(error, completionBlock) + }) } } } + + private fun verifyOffersByDeepLink( + offers: VCLOffers, + generateOffersDescriptor: VCLGenerateOffersDescriptor, + completionBlock: (VCLResult) -> Unit + ) { + generateOffersDescriptor.credentialManifest.deepLink?.let { deepLink -> + offersByDeepLinkVerifier.verifyOffers(offers, deepLink) { + it.handleResult({ isVerified -> + VCLLog.d(TAG, "Offers deep link verification result: $isVerified") + executor.runOnMain { + completionBlock(VCLResult.Success(offers)) + } + }, { error -> + onError(error, completionBlock) + }) + } + } ?: run { + VCLLog.d(TAG, "Deep link was not provided => nothing to verify") + executor.runOnMain { + completionBlock(VCLResult.Success(offers)) + } + } + } + + private fun onError( + error: VCLError, + completionBlock: (VCLResult) -> Unit + ) { + completionBlock(VCLResult.Failure(error)) + } } \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/PresentationRequestUseCaseImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/PresentationRequestUseCaseImpl.kt index d39f819e..4e26b5c2 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/PresentationRequestUseCaseImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/usecases/PresentationRequestUseCaseImpl.kt @@ -4,7 +4,6 @@ * Copyright 2022 Velocity Career Labs inc. * SPDX-License-Identifier: Apache-2.0 */ - package io.velocitycareerlabs.impl.data.usecases import io.velocitycareerlabs.api.entities.* @@ -12,16 +11,21 @@ import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.impl.domain.infrastructure.executors.Executor import io.velocitycareerlabs.impl.domain.repositories.* import io.velocitycareerlabs.impl.domain.usecases.PresentationRequestUseCase +import io.velocitycareerlabs.impl.domain.verifiers.PresentationRequestByDeepLinkVerifier import io.velocitycareerlabs.impl.extensions.encode +import io.velocitycareerlabs.impl.utils.VCLLog import java.lang.Exception internal class PresentationRequestUseCaseImpl( private val presentationRequestRepository: PresentationRequestRepository, private val resolveKidRepository: ResolveKidRepository, private val jwtServiceRepository: JwtServiceRepository, + private val presentationRequestByDeepLinkVerifier: PresentationRequestByDeepLinkVerifier, private val executor: Executor ): PresentationRequestUseCase { + private val TAG = PresentationRequestUseCaseImpl::class.simpleName + override fun getPresentationRequest( presentationRequestDescriptor: VCLPresentationRequestDescriptor, remoteCryptoServicesToken: VCLToken?, @@ -34,7 +38,7 @@ internal class PresentationRequestUseCaseImpl( encodedJwtStrResult.handleResult( { encodedJwtStr -> onGetJwtSuccess( - encodedJwtStr, + VCLJwt(encodedJwtStr), presentationRequestDescriptor, remoteCryptoServicesToken, completionBlock @@ -49,30 +53,6 @@ internal class PresentationRequestUseCaseImpl( } private fun onGetJwtSuccess( - encodedJwtStr: String, - presentationRequestDescriptor: VCLPresentationRequestDescriptor, - remoteCryptoServicesToken: VCLToken?, - completionBlock: (VCLResult) -> Unit - ) { - try { - jwtServiceRepository.decode(encodedJwtStr) { jwtResult -> - jwtResult.handleResult({ jwt -> - onDecodeJwtSuccess( - jwt, - presentationRequestDescriptor, - remoteCryptoServicesToken, - completionBlock - ) - }, { error -> - onError(error, completionBlock) - }) - } - } catch (ex: Exception) { - onError(VCLError(ex), completionBlock) - } - } - - private fun onDecodeJwtSuccess( jwt: VCLJwt, presentationRequestDescriptor: VCLPresentationRequestDescriptor, remoteCryptoServicesToken: VCLToken?, @@ -114,17 +94,26 @@ internal class PresentationRequestUseCaseImpl( presentationRequest.jwt, presentationRequest.publicJwk, remoteCryptoServicesToken, - ) { isVerifiedResult -> - isVerifiedResult.handleResult({ isVerified -> - onVerificationSuccess( - isVerified, + ) { jwtVerificationRes -> + jwtVerificationRes.handleResult({ + presentationRequestByDeepLinkVerifier.verifyPresentationRequest( presentationRequest, - completionBlock - ) - }, - { error -> - onError(error, completionBlock) - }) + presentationRequestDescriptor.deepLink + ) { byDeepLinkVerificationRes -> + byDeepLinkVerificationRes.handleResult({ isVerified -> + VCLLog.d(TAG, "Presentation request by deep link verification result: $isVerified") + onVerificationSuccess( + isVerified, + presentationRequest, + completionBlock + ) + }, { error -> + onError(error, completionBlock) + }) + } + }, { error -> + onError(error, completionBlock) + }) } } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/Utils.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/Utils.kt index aba16209..a70fde6a 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/Utils.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/Utils.kt @@ -8,6 +8,9 @@ package io.velocitycareerlabs.impl.data.utils import io.velocitycareerlabs.api.entities.VCLJwt +import io.velocitycareerlabs.api.entities.VCLOffer +import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl +import org.json.JSONArray internal class Utils { companion object { @@ -79,5 +82,15 @@ internal class Utils { return (credentialSubject as? Map<*, *>)?.get("identifier") as? String ?: (credentialSubject as? Map<*, *>)?.get("id") as? String } + + internal fun offersFromJsonArray(offersJsonArray: JSONArray): List { + val allOffers = mutableListOf() + for (i in 0 until offersJsonArray.length()) { + offersJsonArray.optJSONObject(i)?.let { offerJsonObject -> + allOffers.add(VCLOffer(offerJsonObject)) + } + } + return allOffers + } } } \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialDidVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt similarity index 63% rename from VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialDidVerifierImpl.kt rename to VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt index 4a4e37dc..99760129 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialDidVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt @@ -5,37 +5,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.impl.data.utils +package io.velocitycareerlabs.impl.data.verifiers import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLJwtVerifiableCredentials import io.velocitycareerlabs.api.entities.VCLResult -import io.velocitycareerlabs.impl.domain.utils.CredentialDidVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialDidVerifier import java.util.concurrent.CompletableFuture +import java.util.concurrent.CopyOnWriteArrayList internal class CredentialDidVerifierImpl: CredentialDidVerifier { override fun verifyCredentials( - jwtEncodedCredentials: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) { val passedCredentials = mutableListOf() val failedCredentials = mutableListOf() - val completableFutures = jwtEncodedCredentials.map { jwtEncodedCredential -> - CompletableFuture.supplyAsync { - val jwtCredential = VCLJwt(jwtEncodedCredential) - if (verifyCredential(jwtCredential, finalizeOffersDescriptor)) { - passedCredentials += jwtCredential - } else { - failedCredentials += jwtCredential - } + jwtCredentials.forEach { jwtCredential -> + if (verifyCredential(jwtCredential, finalizeOffersDescriptor)) { + passedCredentials += jwtCredential + } else { + failedCredentials += jwtCredential } } - val allFutures = CompletableFuture.allOf(*completableFutures.toTypedArray()) - allFutures.join() - completionBlock( VCLResult.Success( VCLJwtVerifiableCredentials( @@ -49,5 +44,6 @@ internal class CredentialDidVerifierImpl: CredentialDidVerifier { private fun verifyCredential( jwtCredential: VCLJwt, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor - ) = jwtCredential.payload?.toJSONObject()?.get("iss") as? String == finalizeOffersDescriptor.did + // iss == vc.issuer.id + ) = jwtCredential.payload?.toJSONObject()?.get("iss") as? String == finalizeOffersDescriptor.issuerId } \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierEmptyImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierEmptyImpl.kt similarity index 78% rename from VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierEmptyImpl.kt rename to VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierEmptyImpl.kt index cdc4b66a..52cfefd0 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierEmptyImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierEmptyImpl.kt @@ -5,18 +5,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.impl.data.utils +package io.velocitycareerlabs.impl.data.verifiers import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor +import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLResult -import io.velocitycareerlabs.impl.domain.utils.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier import io.velocitycareerlabs.impl.utils.VCLLog internal class CredentialIssuerVerifierEmptyImpl: CredentialIssuerVerifier { val TAG = CredentialIssuerVerifierEmptyImpl::class.java.simpleName override fun verifyCredentials( - jwtEncodedCredentials: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) { diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierImpl.kt similarity index 95% rename from VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierImpl.kt rename to VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierImpl.kt index 9449fa18..1fb8ef69 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/utils/CredentialIssuerVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialIssuerVerifierImpl.kt @@ -4,8 +4,7 @@ * Copyright 2022 Velocity Career Labs inc. * SPDX-License-Identifier: Apache-2.0 */ - -package io.velocitycareerlabs.impl.data.utils +package io.velocitycareerlabs.impl.data.verifiers import io.velocitycareerlabs.api.entities.VCLCredentialType import io.velocitycareerlabs.api.entities.error.VCLError @@ -19,15 +18,15 @@ import io.velocitycareerlabs.api.entities.handleResult import io.velocitycareerlabs.impl.data.infrastructure.network.Request import io.velocitycareerlabs.impl.data.repositories.HeaderKeys import io.velocitycareerlabs.impl.data.repositories.HeaderValues +import io.velocitycareerlabs.impl.data.utils.Utils import io.velocitycareerlabs.impl.domain.infrastructure.network.NetworkService import io.velocitycareerlabs.impl.domain.models.CredentialTypesModel -import io.velocitycareerlabs.impl.domain.utils.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier import io.velocitycareerlabs.impl.extensions.toJsonObject import io.velocitycareerlabs.impl.extensions.toMap import io.velocitycareerlabs.impl.utils.VCLLog -import org.json.JSONObject import java.util.concurrent.CompletableFuture -import java.util.Stack +import java.util.concurrent.CopyOnWriteArrayList internal class CredentialIssuerVerifierImpl( private val credentialTypesModel: CredentialTypesModel, @@ -36,19 +35,18 @@ internal class CredentialIssuerVerifierImpl( val TAG = CredentialIssuerVerifierImpl::class.java.simpleName override fun verifyCredentials( - jwtEncodedCredentials: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) { - if (jwtEncodedCredentials.isEmpty()) /* nothing to verify */ { + if (jwtCredentials.isEmpty()) /* nothing to verify */ { completionBlock(VCLResult.Success(true)) } else if (finalizeOffersDescriptor.serviceTypes.all.isEmpty()) { completionBlock(VCLResult.Failure(VCLError(errorCode = VCLErrorCode.CredentialTypeNotRegistered.value))) } else { var globalError: VCLError? = null - val completableFutures = jwtEncodedCredentials.map { encodedJwtCredential -> + val completableFutures = jwtCredentials.map { jwtCredential -> CompletableFuture.supplyAsync { - val jwtCredential = VCLJwt(encodedJwt = encodedJwtCredential) Utils.getCredentialType(jwtCredential)?.let { credentialTypeName -> credentialTypesModel.credentialTypeByTypeName(credentialTypeName) ?.let { credentialType -> @@ -194,7 +192,7 @@ internal class CredentialIssuerVerifierImpl( credentialSubjectContexts: List<*>, completionBlock: (VCLResult>>) -> Unit ) { - val completeContexts = mutableListOf>() + val completeContexts = CopyOnWriteArrayList(mutableListOf>()) val completableFutures = credentialSubjectContexts.map { credentialSubjectContext -> CompletableFuture.supplyAsync { networkService.sendRequest( @@ -295,7 +293,8 @@ internal class CredentialIssuerVerifierImpl( activeContext.forEach { (key, value) -> (value as? Map<*, *>)?.let { valueMap -> if (valueMap[KeyId] == ValPrimaryOrganization || - valueMap[KeyId] == ValPrimarySourceProfile) { + valueMap[KeyId] == ValPrimarySourceProfile + ) { return key as? String } } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt new file mode 100644 index 00000000..653474d3 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt @@ -0,0 +1,28 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.data.verifiers + +import io.velocitycareerlabs.api.entities.VCLCredentialManifest +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLResult +import io.velocitycareerlabs.api.entities.error.VCLError +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.impl.domain.verifiers.CredentialManifestByDeepLinkVerifier + +class CredentialManifestByDeepLinkVerifierImpl: CredentialManifestByDeepLinkVerifier { + override fun verifyCredentialManifest( + credentialManifest: VCLCredentialManifest, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) { + if (credentialManifest.issuerId == deepLink.did) { + completionBlock(VCLResult.Success(true)) + } else { + completionBlock((VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedRequestIssuerDid.value)))) + } + } +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt new file mode 100644 index 00000000..f114062d --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt @@ -0,0 +1,30 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.data.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLJwt +import io.velocitycareerlabs.api.entities.VCLResult +import io.velocitycareerlabs.api.entities.error.VCLError +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.impl.domain.verifiers.CredentialsByDeepLinkVerifier +import java.util.concurrent.CompletableFuture + +class CredentialsByDeepLinkVerifierImpl: CredentialsByDeepLinkVerifier { + override fun verifyCredentials( + jwtCredentials: List, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) { + val errorCredential = jwtCredentials.find { it.iss != deepLink.did } + errorCredential?.let { + completionBlock(VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedCredentialIssuerDid.value))) + } ?: run { + completionBlock(VCLResult.Success(true)) + } + } +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt new file mode 100644 index 00000000..a58ed7dd --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt @@ -0,0 +1,29 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.data.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLOffers +import io.velocitycareerlabs.api.entities.VCLResult +import io.velocitycareerlabs.api.entities.error.VCLError +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.impl.domain.verifiers.OffersByDeepLinkVerifier + +class OffersByDeepLinkVerifierImpl: OffersByDeepLinkVerifier { + override fun verifyOffers( + offers: VCLOffers, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) { + val errorOffer = offers.all.find { it.issuerId != deepLink.did } + errorOffer?.let { + completionBlock(VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedOfferIssuerDid.value))) + } ?: run { + completionBlock(VCLResult.Success(true)) + } + } +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt new file mode 100644 index 00000000..75509196 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt @@ -0,0 +1,30 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.data.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLPresentationRequest +import io.velocitycareerlabs.api.entities.VCLResult +import io.velocitycareerlabs.api.entities.error.VCLError +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.impl.domain.verifiers.PresentationRequestByDeepLinkVerifier + +class PresentationRequestByDeepLinkVerifierImpl: PresentationRequestByDeepLinkVerifier { + override fun verifyPresentationRequest( + presentationRequest: VCLPresentationRequest, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) { + if (presentationRequest.iss == deepLink.did) { + completionBlock(VCLResult.Success(true)) + } else { + completionBlock(VCLResult.Failure( + VCLError(errorCode = VCLErrorCode.MismatchedPresentationRequestInspectorDid.value) + )) + } + } +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/repositories/FinalizeOffersRepository.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/repositories/FinalizeOffersRepository.kt index ba2ec505..997512a9 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/repositories/FinalizeOffersRepository.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/repositories/FinalizeOffersRepository.kt @@ -17,6 +17,6 @@ internal interface FinalizeOffersRepository { finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, sessionToken: VCLToken, proof: VCLJwt, - completionBlock: (VCLResult>) -> Unit + completionBlock: (VCLResult>) -> Unit ) } \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialDidVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialDidVerifier.kt similarity index 79% rename from VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialDidVerifier.kt rename to VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialDidVerifier.kt index 017f256f..04d9c119 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialDidVerifier.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialDidVerifier.kt @@ -5,15 +5,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.impl.domain.utils +package io.velocitycareerlabs.impl.domain.verifiers import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor +import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLJwtVerifiableCredentials import io.velocitycareerlabs.api.entities.VCLResult internal interface CredentialDidVerifier { fun verifyCredentials( - jwtEncodedCredentials: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialIssuerVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialIssuerVerifier.kt similarity index 76% rename from VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialIssuerVerifier.kt rename to VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialIssuerVerifier.kt index 849a984c..a2ea2474 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/utils/CredentialIssuerVerifier.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialIssuerVerifier.kt @@ -5,14 +5,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.impl.domain.utils +package io.velocitycareerlabs.impl.domain.verifiers import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor +import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLResult internal interface CredentialIssuerVerifier { fun verifyCredentials( - jwtEncodedCredentials: List, + jwtCredentials: List, finalizeOffersDescriptor: VCLFinalizeOffersDescriptor, completionBlock: (VCLResult) -> Unit ) diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialManifestByDeepLinkVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialManifestByDeepLinkVerifier.kt new file mode 100644 index 00000000..969d6cbe --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialManifestByDeepLinkVerifier.kt @@ -0,0 +1,19 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.domain.verifiers + +import io.velocitycareerlabs.api.entities.VCLCredentialManifest +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLResult + +interface CredentialManifestByDeepLinkVerifier { + fun verifyCredentialManifest( + credentialManifest: VCLCredentialManifest, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialsByDeepLinkVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialsByDeepLinkVerifier.kt new file mode 100644 index 00000000..3451c8e8 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/CredentialsByDeepLinkVerifier.kt @@ -0,0 +1,19 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.domain.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLJwt +import io.velocitycareerlabs.api.entities.VCLResult + +interface CredentialsByDeepLinkVerifier { + fun verifyCredentials( + jwtCredentials: List, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/OffersByDeepLinkVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/OffersByDeepLinkVerifier.kt new file mode 100644 index 00000000..5bff1738 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/OffersByDeepLinkVerifier.kt @@ -0,0 +1,19 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.domain.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLOffers +import io.velocitycareerlabs.api.entities.VCLResult + +interface OffersByDeepLinkVerifier { + fun verifyOffers( + offers: VCLOffers, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/PresentationRequestByDeepLinkVerifier.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/PresentationRequestByDeepLinkVerifier.kt new file mode 100644 index 00000000..966d2a27 --- /dev/null +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/domain/verifiers/PresentationRequestByDeepLinkVerifier.kt @@ -0,0 +1,19 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.impl.domain.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLPresentationRequest +import io.velocitycareerlabs.api.entities.VCLResult + +interface PresentationRequestByDeepLinkVerifier { + fun verifyPresentationRequest( + presentationRequest: VCLPresentationRequest, + deepLink: VCLDeepLink, + completionBlock: (VCLResult) -> Unit + ) +} \ No newline at end of file diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/extensions/StringExtensions.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/extensions/StringExtensions.kt index 00c7df43..748ee0af 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/extensions/StringExtensions.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/extensions/StringExtensions.kt @@ -9,7 +9,10 @@ package io.velocitycareerlabs.impl.extensions import android.util.Base64 import io.velocitycareerlabs.api.entities.VCLDidJwk +import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLPublicJwk +import io.velocitycareerlabs.api.entities.VCLResult +import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.impl.utils.VCLLog import org.json.JSONArray import org.json.JSONObject @@ -19,6 +22,7 @@ import java.net.URLEncoder import java.text.ParseException import java.text.SimpleDateFormat import java.util.* +import java.util.concurrent.CompletableFuture import java.util.regex.Pattern //internal fun String.isUrlEquivalentTo(url: String): Boolean { @@ -128,6 +132,22 @@ internal fun String.toJsonArray(): JSONArray? { internal fun String.toPublicJwk() = VCLPublicJwk(this.removePrefix(VCLDidJwk.DidJwkPrefix).decodeBase64()) +internal fun String.toJwtList(): List? { + this.toJsonArray()?.toList()?.let { encodedCredentialList -> + val jwtCredentials = mutableListOf() + val completableFutures = encodedCredentialList.map { jwtEncodedCredential -> + CompletableFuture.supplyAsync { + jwtCredentials.add(VCLJwt(jwtEncodedCredential as? String ?: "")) + } + } + val allFutures = CompletableFuture.allOf(*completableFutures.toTypedArray()) + allFutures.join() + + return jwtCredentials + } + return null +} + internal fun randomString(length: Int): String = List(length) { (('a'..'z') + ('A'..'Z') + ('0'..'9')).random() diff --git a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt index 5850801f..800fddf0 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt @@ -35,8 +35,8 @@ class VCLCredentialManifestTest { @Test fun testProps() { assert(subject.iss == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") - assert(subject.did == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") - assert(subject.issuerId == "https://devagent.velocitycareerlabs.io/api/holder/v0.6/org/did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") + assert(subject.issuerId == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") + assert(subject.aud == "https://devagent.velocitycareerlabs.io/api/holder/v0.6/org/did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") assert(subject.exchangeId == "645e315309237c760ac022b1") assert(subject.presentationDefinitionId == "645e315309237c760ac022b1.6384a3ad148b1991687f67c9") assert(subject.finalizeOffersUri == "https://devagent.velocitycareerlabs.io/api/holder/v0.6/org/did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA/issue/finalize-offers") diff --git a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLFinalizeOffersDescriptorTest.kt b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLFinalizeOffersDescriptorTest.kt index 1e00410b..d8b4adbd 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLFinalizeOffersDescriptorTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLFinalizeOffersDescriptorTest.kt @@ -38,7 +38,7 @@ class VCLFinalizeOffersDescriptorTest { private val offers = VCLOffers( payload = JSONObject(), - all = JSONArray(), + all = listOf(), responseCode = 200, sessionToken = VCLToken(value = ""), challenge = "" diff --git a/VCL/src/test/java/io/velocitycareerlabs/infrastructure/resources/valid/GenerateOffersMocks.kt b/VCL/src/test/java/io/velocitycareerlabs/infrastructure/resources/valid/GenerateOffersMocks.kt index c5ea1a56..9d22c954 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/infrastructure/resources/valid/GenerateOffersMocks.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/infrastructure/resources/valid/GenerateOffersMocks.kt @@ -9,10 +9,15 @@ package io.velocitycareerlabs.infrastructure.resources.valid class GenerateOffersMocks { companion object { - const val Offers = "[{\"offer1\":\"some offer 1\"},{\"offer2\":\"some offer 2\"}]" + const val Offer1 = "{\"offer1\":\"some offer 1\"}" + const val Offer2 = "{\"offer2\":\"some offer 2\"}" + const val Offers = "[$Offer1,$Offer2]" const val Challenge = "CSASLD10103aa_RW" const val GeneratedOffers = "{\"offers\":$Offers,\"challenge\":\"$Challenge\"}" const val GeneratedOffersEmptyJsonObj = "{}" const val GeneratedOffersEmptyJsonArr = "[]" + + const val RealOffers = + "{\"offers\":[{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"name\":\"Coca Cola\",\"image\":\"https:\\/\\/example.com\\/logo.jpg\"},\"credentialSubject\":{\"@context\":[\"https:\\/\\/lib.velocitynetwork.foundation\\/layer1-context-v1.0.json\"],\"type\":\"EducationDegree\",\"institution\":{\"type\":\"Organization\",\"name\":\"XYZ University with brand\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"type\":\"Place\",\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\"},\"image\":\"https:\\/\\/www.clipartmax.com\\/png\\/small\\/180-1809319_picture-300-x-300-pixel.png\"},\"school\":{\"type\":\"Organization\",\"name\":\"School of nursing\",\"place\":{\"type\":\"Place\",\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\"}},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"EducationDegreeStudyV1.0\",\"degreeMajor\":[\"Nursing\",\"English\"],\"degreeMinor\":[\"Low\",\"Sociology\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"type\":\"AlignmentObject\",\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing,_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\"}],\"startDate\":\"2022-10\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2023-08-27T09:27:15.084Z\",\"offerExpirationDate\":\"2024-08-27T09:27:15.084Z\",\"offerId\":\"6LsoXUY5kT2RZ0tXfuEN-\",\"id\":\"6578897c770790a0fdff7c90\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"f3e9a8bd5800e9c293e3103daeca6cfe27b1646431fd917ad667c23b4bdc8523\"},{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"name\":\"Coca Cola\",\"image\":\"https:\\/\\/example.com\\/logo.jpg\"},\"credentialSubject\":{\"@context\":[\"https:\\/\\/lib.velocitynetwork.foundation\\/layer1-context-v1.0.json\"],\"type\":\"EducationDegree\",\"institution\":{\"type\":\"Organization\",\"name\":\"XYZ University\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"type\":\"Place\",\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\"},\"image\":\"https:\\/\\/www.clipartmax.com\\/png\\/small\\/180-1809319_picture-300-x-300-pixel.png\"},\"school\":{\"type\":\"Organization\",\"name\":\"School of nursing\",\"place\":{\"type\":\"Place\",\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\"}},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"EducationDegreeStudyV1.0\",\"degreeMajor\":[\"Nursing\",\"English\"],\"degreeMinor\":[\"Low\",\"Sociology\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"type\":\"AlignmentObject\",\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing,_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\"}],\"startDate\":\"2022-10\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2023-08-27T09:21:49.729Z\",\"offerExpirationDate\":\"2024-08-27T09:21:49.729Z\",\"offerId\":\"gcid6O7gOOkGnAmqIrcy3\",\"id\":\"6578897c770790a0fdff7c91\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"9cb721e57266f6783158dc7ee68640240929fca8fc6b0299448467ffffa45b68\"},{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"@context\":[\"https:\\/\\/lib.velocitynetwork.foundation\\/layer1-context-v1.0.json\"],\"type\":\"EducationDegree\",\"institution\":{\"type\":\"Organization\",\"name\":\"XYZ University\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"type\":\"Place\",\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\"},\"image\":\"https:\\/\\/www.clipartmax.com\\/png\\/small\\/180-1809319_picture-300-x-300-pixel.png\"},\"school\":{\"type\":\"Organization\",\"name\":\"School of nursing\",\"place\":{\"type\":\"Place\",\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\"}},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"EducationDegreeStudyV1.0\",\"degreeMajor\":[\"Nursing\",\"English\"],\"degreeMinor\":[\"Low\",\"Sociology\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"type\":\"AlignmentObject\",\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing,_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\"}],\"startDate\":\"2022-10\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2023-07-08T20:39:02.076Z\",\"offerExpirationDate\":\"2024-07-08T20:39:02.076Z\",\"offerId\":\"-GJXLBwj50QOM39JIRC4c\",\"id\":\"6578897c770790a0fdff7c92\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"9cb721e57266f6783158dc7ee68640240929fca8fc6b0299448467ffffa45b68\"},{\"type\":[\"OpenBadgeCredential\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"type\":\"AchievementSubject\",\"achievement\":{\"id\":\"VNF0007\",\"type\":\"Achievement\",\"name\":\"I attended the 2023 Velocity Network Foundation General Assembly\",\"achievementType\":\"Badge\",\"criteria\":{\"narrative\":\"Attendance at the 2023 Velocity Network Foundation General Assembly\"},\"description\":\"Badge awarded to individuals who attended the Velocity Network Foundation General Assembly\",\"image\":{\"id\":\"https:\\/\\/assets.velocitynetwork.foundation\\/developers\\/general\\/vnf-general-assembly-2023.png\",\"type\":\"Image\"},\"alignment\":[{\"type\":\"Alignment\",\"targetName\":\"Velocity Network Foundation Website\",\"targetUrl\":\"https:\\/\\/www.velocitynetwork.foundation\\/\",\"targetFramework\":\"Target Framework\"}]},\"source\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"name\":\"University of Massachusetts Amherst ion\",\"type\":\"Profile\"}},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/open-badge-credential.schema.json\"},\"offerCreationDate\":\"2023-06-14T13:00:09.898Z\",\"offerExpirationDate\":\"2030-01-01T00:00:00.000Z\",\"offerId\":\"Adam_OBC_3\",\"id\":\"6578897c770790a0fdff7c93\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"056fdb38b1279d8d3b074ccdd3d35aeff6740c0b9db4aaca6d04433dc2e4da5e\"},{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"@context\":\"https:\\/\\/velocitynetwork.foundation\\/contexts\\/education-degree\",\"institution\":{\"name\":\"Image instead of Logo\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"addressLocality\":\"Cardiff\",\"addressRegion\":\"GB-WLS\",\"addressCountry\":\"GB\",\"type\":\"Place\"},\"image\":\"https:\\/\\/upload.wikimedia.org\\/wikipedia\\/commons\\/8\\/84\\/Mozilla_Firefox_3.5_logo.png\",\"type\":\"Organization\"},\"school\":{\"name\":\"College of Liberal Arts and Sciences\",\"place\":{\"name\":\"diff photo\",\"addressLocality\":\"Barry\",\"addressRegion\":\"GB-WLS\",\"addressCountry\":\"GB\",\"type\":\"Place\"},\"type\":\"Organization\"},\"programName\":\"Undergraduate program in psychology\",\"programType\":\"60 credits full program\",\"degreeName\":\"Image instead of Logo\",\"degreeMajor\":[\"Psychology\"],\"degreeMinor\":[\"English\"],\"description\":\"The program prepares students for graduate study, and so emphasizes practice in the research techniques which are used in graduate school and professionally later on.\",\"alignment\":[{\"targetName\":\"Bachelor of Science (BS) in Psychology - General Psychology\",\"targetUrl\":\"https:\\/\\/nces.ed.gov\\/ipeds\\/cipcode\\/cipdetail.aspx?y=55&cipid=88527\",\"targetDescription\":\"A general program that focuses on the scientific study of individual and collective behavior, the physical and environmental bases of behavior, and the analysis and treatment of behavior problems and disorders. Includes instruction in the principles of the various subfields of psychology, research methods, and psychological assessment and testing methods.\",\"targetCode\":\"42.0101\",\"targetFramework\":\"CIP - Classification of Instructional Programs\",\"type\":\"AlignmentObject\"}],\"grade\":{\"scoreMethod\":{\"scoreMethodDescription\":\"Poor, Fair, Good, Very Good\",\"passingScore\":\"Fair\",\"scoreMethodType\":\"CriterionReferenced\"},\"result\":\"Study\",\"passFail\":\"Pass\",\"scoreValue\":\"1.5\",\"type\":\"ScoreMethod\"},\"registrationDate\":\"2021-05-15\",\"startDate\":\"2021-10-01\",\"type\":\"EducationDegree\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2022-12-06T11:28:43.574Z\",\"offerExpirationDate\":\"2030-01-01T00:00:00.000Z\",\"offerId\":\"XE50THPBfzAYDKmB1GTvwv\",\"id\":\"6578897c770790a0fdff7c94\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"19aa50f902464c25c11458dc19d55a6a45b4232156b5de85443dc922edfc9e64\"},{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"name\":\"Coca Cola\",\"image\":\"https:\\/\\/example.com\\/logo.jpg\"},\"credentialSubject\":{\"@context\":[\"https:\\/\\/lib.velocitynetwork.foundation\\/layer1-context-v1.0.json\"],\"type\":\"EducationDegree\",\"institution\":{\"type\":\"Organization\",\"name\":\"XYZ University with brand\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"type\":\"Place\",\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\"},\"image\":\"https:\\/\\/www.clipartmax.com\\/png\\/small\\/180-1809319_picture-300-x-300-pixel.png\"},\"school\":{\"type\":\"Organization\",\"name\":\"School of nursing\",\"place\":{\"type\":\"Place\",\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\"}},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"EducationDegreeStudyV1.0\",\"degreeMajor\":[\"Nursing\",\"English\"],\"degreeMinor\":[\"Low\",\"Sociology\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"type\":\"AlignmentObject\",\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing,_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\"}],\"startDate\":\"2022-10\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2023-08-28T07:25:45.000Z\",\"offerExpirationDate\":\"2025-01-04T08:34:00.162Z\",\"offerId\":\"Offer-2.1 (push)\",\"id\":\"6578897c770790a0fdff7c95\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"f3e9a8bd5800e9c293e3103daeca6cfe27b1646431fd917ad667c23b4bdc8523\"},{\"type\":[\"EducationDegreeStudyV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"@context\":\"https:\\/\\/velocitynetwork.foundation\\/contexts\\/education-degree\",\"institution\":{\"name\":\"University of Massachusetts Amherst ion\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"addressLocality\":\"Cardiff\",\"addressRegion\":\"GB-WLS\",\"addressCountry\":\"GB\",\"type\":\"Place\"},\"type\":\"Organization\"},\"school\":{\"name\":\"College of Liberal Arts and Sciences\",\"place\":{\"name\":\"Graduate Studies Building\",\"addressLocality\":\"Barry\",\"addressRegion\":\"GB-WLS\",\"addressCountry\":\"GB\",\"type\":\"Place\"},\"type\":\"Organization\"},\"programName\":\"Undergraduate program in psychology\",\"programType\":\"60 credits full program\",\"degreeName\":\"StudyV1.0\",\"degreeMajor\":[\"Psychology\",\"Psychology2\"],\"degreeMinor\":[\"English\",\"Psychology2\"],\"description\":\"The program prepares students for graduate study, and so emphasizes practice in the research techniques which are used in graduate school and professionally later on.\",\"alignment\":[{\"targetName\":\"Bachelor of Science (BS) in Psychology - General Psychology\",\"targetUrl\":\"https:\\/\\/nces.ed.gov\\/ipeds\\/cipcode\\/cipdetail.aspx?y=55&cipid=88527\",\"targetDescription\":\"A general program that focuses on the scientific study of individual and collective behavior, the physical and environmental bases of behavior, and the analysis and treatment of behavior problems and disorders. Includes instruction in the principles of the various subfields of psychology, research methods, and psychological assessment and testing methods.\",\"targetCode\":\"42.0101\",\"targetFramework\":\"CIP - Classification of Instructional Programs\",\"type\":\"AlignmentObject\"}],\"registrationDate\":\"2021-05-15\",\"startDate\":\"2021-10-01\",\"type\":\"EducationDegree\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-study-v1.0.schema.json\"},\"offerCreationDate\":\"2022-12-06T11:28:43.574Z\",\"offerExpirationDate\":\"2030-01-01T00:00:00.000Z\",\"offerId\":\"XE50THPBfzAYDKmB1GTvw\",\"id\":\"6578897c770790a0fdff7c96\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"10b0e97ed421df2e6ff0e8c033eb64dde12bc3327ad797a6909220fbfb9a7e45\"},{\"type\":[\"EducationDegreeRegistrationV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"@context\":\"https:\\/\\/velocitynetwork.foundation\\/contexts\\/education-degree\",\"institution\":{\"name\":\"University of Massachusetts Amherst ion\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\",\"type\":\"Place\"},\"type\":\"Organization\"},\"school\":{\"name\":\"School of nursing\",\"place\":{\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\",\"type\":\"Place\"},\"type\":\"Organization\"},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"Student (RegistrationV1.0)\",\"degreeMajor\":[\"Nursing\",\"Nursing2\"],\"degreeMinor\":[\"Nursing\",\"Nursing\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing,_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\",\"type\":\"AlignmentObject\"}],\"registrationDate\":\"2011-05\",\"startDate\":\"2011-10\",\"type\":\"EducationDegree\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-registration-v1.0.schema.json\"},\"offerCreationDate\":\"2022-12-06T11:25:32.955Z\",\"offerExpirationDate\":\"2030-01-01T00:00:00.000Z\",\"offerId\":\"nH6b5jBMJ6XeL1nEk5qNa\",\"id\":\"6578897c770790a0fdff7c97\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"6adae30b7023c54929961d9c55e5c5c5c54a4022bea03e74cdfacbdf6380be83\"},{\"type\":[\"EducationDegreeGraduationV1.0\"],\"issuer\":{\"id\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\"},\"credentialSubject\":{\"@context\":\"https:\\/\\/velocitynetwork.foundation\\/contexts\\/education-degree\",\"institution\":{\"name\":\"University of Massachusetts Amherst ion\",\"identifier\":\"did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA\",\"place\":{\"addressLocality\":\"Chicago\",\"addressRegion\":\"US-IL\",\"addressCountry\":\"US\",\"type\":\"Place\"},\"type\":\"Organization\"},\"school\":{\"name\":\"School of nursing (GraduationV1.0)\",\"place\":{\"name\":\"Florida Branch\",\"addressLocality\":\"Fort Myers\",\"addressRegion\":\"US-FL\",\"addressCountry\":\"US\",\"type\":\"Place\"},\"type\":\"Organization\"},\"programName\":\"RN to BSN\",\"programType\":\"1 year full time program\",\"programMode\":\"Online\",\"degreeName\":\"Bachelor of Science (GraduationV1.0)\",\"degreeMajor\":[\"Nursing\",\"Nursing2\"],\"degreeMinor\":[\"Nursing\",\"Nursing2\"],\"description\":\"Starfield College’s RN to BSN Online Option allows working nurses to advance your degree in as few as 3 semesters.\\n If you are a registered nurse with an active RN license looking to earn your BSN, Chamberlain's online RN to BSN option can help prepare you for the next step in your career.\\n Our RN to BSN online option allows you to earn your degree while you work.\",\"alignment\":[{\"targetName\":\"Bachelor of Science in Nursing, RN to BSN\",\"targetUrl\":\"https:\\/\\/credentialfinder.org\\/credential\\/5769\\/Bachelor_of_Science_in_Nursing_RN_to_BSN\",\"targetDescription\":\"The RN to BSN completion program has been developed to address the specific needs of working registered nurses who return to the university to earn the BSN.\",\"targetFramework\":\"Credential Engine's Credential Registry\",\"type\":\"AlignmentObject\"}],\"startDate\":\"2011-08\",\"endDate\":\"2013-06\",\"conferredDate\":\"2014-01\",\"honors\":\"cum laude\",\"type\":\"EducationDegree\"},\"credentialSchema\":{\"type\":\"JsonSchemaValidator2018\",\"id\":\"https:\\/\\/devlib.velocitynetwork.foundation\\/schemas\\/education-degree-graduation-v1.0.schema.json\"},\"offerCreationDate\":\"2022-12-06T11:16:20.136Z\",\"offerExpirationDate\":\"2030-01-01T00:00:00.000Z\",\"offerId\":\"h9tpQcpjbJ19faZr_ySaR\",\"id\":\"6578897c770790a0fdff7c98\",\"exchangeId\":\"6578896f770790a0fdff7c8f\",\"hash\":\"854c1328e55387a500988809a6c7022f5098f5953d38a5795ad2ac285b61f5f1\"}],\"challenge\":\"tGQLKQEhvi-tiXr8\"}" } } \ No newline at end of file diff --git a/VCL/src/test/java/io/velocitycareerlabs/usecases/CredentialManifestUseCaseTest.kt b/VCL/src/test/java/io/velocitycareerlabs/usecases/CredentialManifestUseCaseTest.kt index 61b4c264..e805d8e7 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/usecases/CredentialManifestUseCaseTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/usecases/CredentialManifestUseCaseTest.kt @@ -15,6 +15,7 @@ import io.velocitycareerlabs.impl.data.repositories.CredentialManifestRepository import io.velocitycareerlabs.impl.data.repositories.JwtServiceRepositoryImpl import io.velocitycareerlabs.impl.data.repositories.ResolveKidRepositoryImpl import io.velocitycareerlabs.impl.data.usecases.CredentialManifestUseCaseImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialManifestByDeepLinkVerifierImpl import io.velocitycareerlabs.impl.domain.usecases.CredentialManifestUseCase import io.velocitycareerlabs.impl.extensions.toJsonObject import io.velocitycareerlabs.impl.jwt.local.VCLJwtSignServiceLocalImpl @@ -57,6 +58,7 @@ internal class CredentialManifestUseCaseTest { VCLJwtSignServiceLocalImpl(VCLKeyServiceLocalImpl(SecretStoreServiceMock.Instance)), VCLJwtVerifyServiceLocalImpl() ), + CredentialManifestByDeepLinkVerifierImpl(), ExecutorImpl() ) diff --git a/VCL/src/test/java/io/velocitycareerlabs/usecases/FinalizeOffersUseCaseTest.kt b/VCL/src/test/java/io/velocitycareerlabs/usecases/FinalizeOffersUseCaseTest.kt index 379ca0e5..03dd320e 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/usecases/FinalizeOffersUseCaseTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/usecases/FinalizeOffersUseCaseTest.kt @@ -15,8 +15,11 @@ import io.velocitycareerlabs.impl.data.repositories.GenerateOffersRepositoryImpl import io.velocitycareerlabs.impl.data.repositories.JwtServiceRepositoryImpl import io.velocitycareerlabs.impl.data.usecases.FinalizeOffersUseCaseImpl import io.velocitycareerlabs.impl.data.usecases.GenerateOffersUseCaseImpl -import io.velocitycareerlabs.impl.data.utils.CredentialDidVerifierImpl -import io.velocitycareerlabs.impl.data.utils.CredentialIssuerVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialDidVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialManifestByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialsByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.OffersByDeepLinkVerifierImpl import io.velocitycareerlabs.impl.domain.usecases.FinalizeOffersUseCase import io.velocitycareerlabs.impl.extensions.toJsonArray import io.velocitycareerlabs.impl.extensions.toJsonObject @@ -76,6 +79,7 @@ internal class FinalizeOffersUseCaseTest { GenerateOffersRepositoryImpl( NetworkServiceSuccess(validResponse = GenerateOffersMocks.GeneratedOffers) ), + OffersByDeepLinkVerifierImpl(), EmptyExecutor() ).generateOffers( sessionToken = VCLToken(value = ""), @@ -134,6 +138,7 @@ internal class FinalizeOffersUseCaseTest { NetworkServiceSuccess(validResponse = JsonLdMocks.Layer1v10Jsonld), ), CredentialDidVerifierImpl(), + CredentialsByDeepLinkVerifierImpl(), EmptyExecutor() ) @@ -182,6 +187,7 @@ internal class FinalizeOffersUseCaseTest { NetworkServiceSuccess(validResponse = JsonLdMocks.Layer1v10Jsonld), ), CredentialDidVerifierImpl(), + CredentialsByDeepLinkVerifierImpl(), EmptyExecutor() ) @@ -231,6 +237,7 @@ internal class FinalizeOffersUseCaseTest { NetworkServiceSuccess(validResponse = JsonLdMocks.Layer1v10Jsonld), ), CredentialDidVerifierImpl(), + CredentialsByDeepLinkVerifierImpl(), EmptyExecutor() ) diff --git a/VCL/src/test/java/io/velocitycareerlabs/usecases/GenerateOffersUseCaseTest.kt b/VCL/src/test/java/io/velocitycareerlabs/usecases/GenerateOffersUseCaseTest.kt index 6270978e..7f5fb515 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/usecases/GenerateOffersUseCaseTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/usecases/GenerateOffersUseCaseTest.kt @@ -12,6 +12,7 @@ import io.velocitycareerlabs.api.entities.* import io.velocitycareerlabs.impl.data.infrastructure.executors.ExecutorImpl import io.velocitycareerlabs.impl.data.repositories.GenerateOffersRepositoryImpl import io.velocitycareerlabs.impl.data.usecases.GenerateOffersUseCaseImpl +import io.velocitycareerlabs.impl.data.verifiers.OffersByDeepLinkVerifierImpl import io.velocitycareerlabs.impl.domain.usecases.GenerateOffersUseCase import io.velocitycareerlabs.impl.extensions.toJsonArray import io.velocitycareerlabs.impl.extensions.toJsonObject @@ -37,6 +38,7 @@ internal class GenerateOffersUseCaseTest { GenerateOffersRepositoryImpl( NetworkServiceSuccess(validResponse = GenerateOffersMocks.GeneratedOffers) ), + OffersByDeepLinkVerifierImpl(), ExecutorImpl() ) @@ -71,6 +73,7 @@ internal class GenerateOffersUseCaseTest { GenerateOffersRepositoryImpl( NetworkServiceSuccess(validResponse = GenerateOffersMocks.GeneratedOffersEmptyJsonObj) ), + OffersByDeepLinkVerifierImpl(), ExecutorImpl() ) @@ -103,6 +106,7 @@ internal class GenerateOffersUseCaseTest { GenerateOffersRepositoryImpl( NetworkServiceSuccess(validResponse = GenerateOffersMocks.GeneratedOffersEmptyJsonArr) ), + OffersByDeepLinkVerifierImpl(), ExecutorImpl() ) diff --git a/VCL/src/test/java/io/velocitycareerlabs/usecases/PresentationRequestUseCaseTest.kt b/VCL/src/test/java/io/velocitycareerlabs/usecases/PresentationRequestUseCaseTest.kt index 1f20aee9..b6ce1197 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/usecases/PresentationRequestUseCaseTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/usecases/PresentationRequestUseCaseTest.kt @@ -15,6 +15,7 @@ import io.velocitycareerlabs.impl.data.repositories.JwtServiceRepositoryImpl import io.velocitycareerlabs.impl.data.repositories.PresentationRequestRepositoryImpl import io.velocitycareerlabs.impl.data.repositories.ResolveKidRepositoryImpl import io.velocitycareerlabs.impl.data.usecases.PresentationRequestUseCaseImpl +import io.velocitycareerlabs.impl.data.verifiers.PresentationRequestByDeepLinkVerifierImpl import io.velocitycareerlabs.impl.domain.usecases.PresentationRequestUseCase import io.velocitycareerlabs.impl.extensions.toJsonObject import io.velocitycareerlabs.impl.jwt.local.VCLJwtSignServiceLocalImpl @@ -50,9 +51,9 @@ internal class PresentationRequestUseCaseTest { VCLJwtSignServiceLocalImpl(VCLKeyServiceLocalImpl(SecretStoreServiceMock.Instance)), VCLJwtVerifyServiceLocalImpl() ), + PresentationRequestByDeepLinkVerifierImpl(), ExecutorImpl() ) - var result: VCLResult? = null // Action subject.getPresentationRequest( diff --git a/VCL/src/test/java/io/velocitycareerlabs/utils/CredentialDidVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialDidVerifierTest.kt similarity index 89% rename from VCL/src/test/java/io/velocitycareerlabs/utils/CredentialDidVerifierTest.kt rename to VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialDidVerifierTest.kt index 0af852db..5e50bf7a 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/utils/CredentialDidVerifierTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialDidVerifierTest.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.utils +package io.velocitycareerlabs.verifiers import io.velocitycareerlabs.api.entities.VCLCredentialManifest import io.velocitycareerlabs.api.entities.VCLFinalizeOffersDescriptor @@ -14,9 +14,10 @@ import io.velocitycareerlabs.api.entities.VCLOffers import io.velocitycareerlabs.api.entities.VCLToken import io.velocitycareerlabs.api.entities.VCLVerifiedProfile import io.velocitycareerlabs.api.entities.handleResult -import io.velocitycareerlabs.impl.data.utils.CredentialDidVerifierImpl +import io.velocitycareerlabs.impl.data.verifiers.CredentialDidVerifierImpl import io.velocitycareerlabs.impl.extensions.toJsonArray import io.velocitycareerlabs.impl.extensions.toJsonObject +import io.velocitycareerlabs.impl.extensions.toJwtList import io.velocitycareerlabs.impl.extensions.toList import io.velocitycareerlabs.infrastructure.resources.valid.CredentialManifestMocks import io.velocitycareerlabs.infrastructure.resources.valid.CredentialMocks @@ -33,7 +34,7 @@ internal class CredentialDidVerifierTest { CredentialMocks.JwtCredentialsFromNotaryIssuer.toJsonArray()?.length() private val credentialsFromRegularIssuerAmount = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray()?.length() - private val OffersMock = VCLOffers(JSONObject(), JSONArray(), 1, VCLToken(".."), "") + private val OffersMock = VCLOffers(JSONObject(), listOf(), 1, VCLToken(".."), "") lateinit var finalizeOffersDescriptorOfNotaryIssuer: VCLFinalizeOffersDescriptor lateinit var credentialManifestFromNotaryIssuer: VCLCredentialManifest @@ -69,8 +70,7 @@ internal class CredentialDidVerifierTest { @Test fun testVerifyCredentialsSuccess() { subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJsonArray()!! - .toList() as List, + jwtCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer ) { verifiableCredentialsResult -> verifiableCredentialsResult.handleResult( @@ -98,8 +98,7 @@ internal class CredentialDidVerifierTest { @Test fun testVerifyCredentialsFailed() { subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray()!! - .toList() as List, + jwtCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer ) { verifiableCredentialsResult -> verifiableCredentialsResult.handleResult( @@ -127,8 +126,8 @@ internal class CredentialDidVerifierTest { @Test fun testVerifyCredentials1Passed1Failed() { subject.verifyCredentials( - jwtEncodedCredentials = "[\"${CredentialMocks.JwtCredentialEmploymentPastFromNotaryIssuer}\", \"${CredentialMocks.JwtCredentialEmailFromIdentityIssuer}\"]" - .toJsonArray()!!.toList() as List, + jwtCredentials = "[\"${CredentialMocks.JwtCredentialEmploymentPastFromNotaryIssuer}\", \"${CredentialMocks.JwtCredentialEmailFromIdentityIssuer}\"]" + .toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer ) { verifiableCredentialsResult -> verifiableCredentialsResult.handleResult( @@ -157,8 +156,7 @@ internal class CredentialDidVerifierTest { @Test fun testVerifyCredentialsEmpty() { subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtEmptyCredentials.toJsonArray()!! - .toList() as List, + jwtCredentials = CredentialMocks.JwtEmptyCredentials.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer ) { verifiableCredentialsResult -> verifiableCredentialsResult.handleResult( diff --git a/VCL/src/test/java/io/velocitycareerlabs/utils/CredentialIssuerVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialIssuerVerifierTest.kt similarity index 88% rename from VCL/src/test/java/io/velocitycareerlabs/utils/CredentialIssuerVerifierTest.kt rename to VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialIssuerVerifierTest.kt index d4586149..c8251677 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/utils/CredentialIssuerVerifierTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialIssuerVerifierTest.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.utils +package io.velocitycareerlabs.verifiers import io.velocitycareerlabs.api.entities.VCLCredentialManifest import io.velocitycareerlabs.api.entities.error.VCLErrorCode @@ -15,10 +15,11 @@ import io.velocitycareerlabs.api.entities.VCLOffers import io.velocitycareerlabs.api.entities.VCLToken import io.velocitycareerlabs.api.entities.VCLVerifiedProfile import io.velocitycareerlabs.api.entities.handleResult -import io.velocitycareerlabs.impl.data.utils.CredentialIssuerVerifierImpl -import io.velocitycareerlabs.impl.domain.utils.CredentialIssuerVerifier +import io.velocitycareerlabs.impl.data.verifiers.CredentialIssuerVerifierImpl +import io.velocitycareerlabs.impl.domain.verifiers.CredentialIssuerVerifier import io.velocitycareerlabs.impl.extensions.toJsonArray import io.velocitycareerlabs.impl.extensions.toJsonObject +import io.velocitycareerlabs.impl.extensions.toJwtList import io.velocitycareerlabs.impl.extensions.toListOfStrings import io.velocitycareerlabs.infrastructure.network.NetworkServiceSuccess import io.velocitycareerlabs.infrastructure.resources.CredentialTypesModelMock @@ -35,7 +36,7 @@ internal class CredentialIssuerVerifierTest { lateinit var subject: CredentialIssuerVerifier - private val OffersMock = VCLOffers(JSONObject(), JSONArray(), 1, VCLToken(""), "") + private val OffersMock = VCLOffers(JSONObject(), listOf(), 1, VCLToken(""), "") lateinit var finalizeOffersDescriptorWithoutPermittedServices: VCLFinalizeOffersDescriptor lateinit var credentialManifestWithoutPermittedServices: VCLCredentialManifest @@ -106,8 +107,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -131,8 +131,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsWithoutSubject.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsWithoutSubject.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfNotaryIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -156,8 +155,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfRegularIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -181,8 +179,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfRegularIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -206,8 +203,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromNotaryIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorWithoutPermittedServices, ) { verificationResult -> verificationResult.handleResult( @@ -231,8 +227,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsWithoutSubject.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsWithoutSubject.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfRegularIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -256,8 +251,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfIdentityIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -281,8 +275,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtEmptyCredentials.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtEmptyCredentials.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfIdentityIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -306,8 +299,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromIdentityIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromIdentityIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfIdentityIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -331,8 +323,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfRegularIssuer, ) { verificationResult -> verificationResult.handleResult( @@ -356,8 +347,7 @@ internal class CredentialIssuerVerifierTest { ) subject.verifyCredentials( - jwtEncodedCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJsonArray() - !!.toListOfStrings(), + jwtCredentials = CredentialMocks.JwtCredentialsFromRegularIssuer.toJwtList()!!, finalizeOffersDescriptor = finalizeOffersDescriptorOfRegularIssuer, ) { verificationResult -> verificationResult.handleResult( diff --git a/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialManifestByDeepLinkVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialManifestByDeepLinkVerifierTest.kt new file mode 100644 index 00000000..cbcd7872 --- /dev/null +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialManifestByDeepLinkVerifierTest.kt @@ -0,0 +1,59 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.verifiers + +import io.velocitycareerlabs.api.entities.VCLCredentialManifest +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLJwt +import io.velocitycareerlabs.api.entities.VCLVerifiedProfile +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.api.entities.handleResult +import io.velocitycareerlabs.impl.data.verifiers.CredentialManifestByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.extensions.toJsonObject +import io.velocitycareerlabs.infrastructure.resources.valid.CredentialManifestMocks +import io.velocitycareerlabs.infrastructure.resources.valid.DeepLinkMocks +import io.velocitycareerlabs.infrastructure.resources.valid.VerifiedProfileMocks +import org.junit.Test + +class CredentialManifestByDeepLinkVerifierTest { + private val subject = CredentialManifestByDeepLinkVerifierImpl() + private val credentialManifest = VCLCredentialManifest( + jwt = VCLJwt(CredentialManifestMocks.JwtCredentialManifestFromRegularIssuer), + verifiedProfile = VCLVerifiedProfile(VerifiedProfileMocks.VerifiedProfileOfRegularIssuer.toJsonObject()!!) + ) + private val correctDeepLink = + VCLDeepLink("velocity-network-devnet://issue?request_uri=https%3A%2F%2Fdevagent.velocitycareerlabs.io%2Fapi%2Fholder%2Fv0.6%2Forg%2Fdid%3Aion%3AEiBMsw27IKRYIdwUOfDeBd0LnWVeG2fPxxJi9L1fvjM20g%2Fissue%2Fget-credential-manifest%3Fid%3D611b5836e93d08000af6f1bc%26credential_types%3DPastEmploymentPosition%26issuerDid%3Ddid%3Aion%3AEiBMsw27IKRYIdwUOfDeBd0LnWVeG2fPxxJi9L1fvjM20g") + private val wrongDeepLink = DeepLinkMocks.CredentialManifestDeepLinkDevNet + + @Test + fun testVerifyCredentialManifestSuccess() { + subject.verifyCredentialManifest( + credentialManifest, + correctDeepLink + ) { + it.handleResult({ isVerified -> + assert(isVerified) + }, { error -> + assert(false) { "${error.toJsonObject()}" } + }) + } + } + + @Test + fun testVerifyCredentialManifestError() { + subject.verifyCredentialManifest( + credentialManifest, + wrongDeepLink + ) { + it.handleResult({ + assert(false) { "${VCLErrorCode.MismatchedRequestIssuerDid.value} error code is expected" } + }, { error -> + assert(error.errorCode == VCLErrorCode.MismatchedRequestIssuerDid.value) + }) + } + } +} \ No newline at end of file diff --git a/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialsByDeepLinkVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialsByDeepLinkVerifierTest.kt new file mode 100644 index 00000000..4d0f9759 --- /dev/null +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/CredentialsByDeepLinkVerifierTest.kt @@ -0,0 +1,58 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLJwt +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.api.entities.handleResult +import io.velocitycareerlabs.impl.data.verifiers.CredentialsByDeepLinkVerifierImpl +import io.velocitycareerlabs.infrastructure.resources.valid.CredentialMocks +import io.velocitycareerlabs.infrastructure.resources.valid.DeepLinkMocks +import org.junit.Test + +class CredentialsByDeepLinkVerifierTest { + private val subject = CredentialsByDeepLinkVerifierImpl() + + private val correctDeepLink = + VCLDeepLink("velocity-network-devnet://issue?request_uri=https%3A%2F%2Fdevagent.velocitycareerlabs.io%2Fapi%2Fholder%2Fv0.6%2Forg%2Fdid%3Aion%3AEiBMsw27IKRYIdwUOfDeBd0LnWVeG2fPxxJi9L1fvjM20g%2Fissue%2Fget-credential-manifest%3Fid%3D611b5836e93d08000af6f1bc%26credential_types%3DPastEmploymentPosition%26issuerDid%3Ddid%3Aion%3AEiBMsw27IKRYIdwUOfDeBd0LnWVeG2fPxxJi9L1fvjM20g") + private val wrongDeepLink = DeepLinkMocks.CredentialManifestDeepLinkDevNet + + @Test + fun testVerifyCredentialsSuccess() { + subject.verifyCredentials( + listOf( + VCLJwt(CredentialMocks.JwtCredentialEmploymentPastFromRegularIssuer), + VCLJwt(CredentialMocks.JwtCredentialEducationDegreeRegistrationFromRegularIssuer) + ), + correctDeepLink + ) { + it.handleResult({ isVerified -> + assert(isVerified) + }, { error -> + assert(false) { "${error.toJsonObject()}" } + }) + } + } + + @Test + fun testVerifyCredentialsError() { + subject.verifyCredentials( + listOf( + VCLJwt(CredentialMocks.JwtCredentialEmploymentPastFromRegularIssuer), + VCLJwt(CredentialMocks.JwtCredentialEducationDegreeRegistrationFromRegularIssuer) + ), + wrongDeepLink + ) { + it.handleResult({ + assert(false) { "${VCLErrorCode.MismatchedCredentialIssuerDid.value} error code is expected" } + }, { error -> + assert(error.errorCode == VCLErrorCode.MismatchedCredentialIssuerDid.value) + }) + } + } +} \ No newline at end of file diff --git a/VCL/src/test/java/io/velocitycareerlabs/verifiers/OffersByDeepLinkVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/OffersByDeepLinkVerifierTest.kt new file mode 100644 index 00000000..6c035a17 --- /dev/null +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/OffersByDeepLinkVerifierTest.kt @@ -0,0 +1,68 @@ +/** + * Created by Michael Avoyan on 10/12/2023. + * + * Copyright 2022 Velocity Career Labs inc. + * SPDX-License-Identifier: Apache-2.0 + */ +package io.velocitycareerlabs.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.VCLOffer +import io.velocitycareerlabs.api.entities.VCLOffers +import io.velocitycareerlabs.api.entities.VCLToken +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.api.entities.handleResult +import io.velocitycareerlabs.impl.data.utils.Utils +import io.velocitycareerlabs.impl.data.verifiers.OffersByDeepLinkVerifierImpl +import io.velocitycareerlabs.impl.extensions.toJsonObject +import io.velocitycareerlabs.infrastructure.resources.valid.DeepLinkMocks +import io.velocitycareerlabs.infrastructure.resources.valid.GenerateOffersMocks +import org.json.JSONArray +import org.json.JSONObject +import org.junit.Test + +class OffersByDeepLinkVerifierTest { + val subject = OffersByDeepLinkVerifierImpl() + + private val offersPayload = GenerateOffersMocks.RealOffers.toJsonObject() ?: JSONObject() + private val offers = VCLOffers( + payload = offersPayload, + all = Utils.offersFromJsonArray( + offersPayload.optJSONArray(VCLOffers.CodingKeys.KeyOffers) ?: JSONArray() + ), + responseCode = 0, + sessionToken = VCLToken(""), + challenge = "" + ) + private val correctDeepLink = + VCLDeepLink("velocity-network-devnet://issue?request_uri=https%3A%2F%2Fdevagent.velocitycareerlabs.io%2Fapi%2Fholder%2Fv0.6%2Forg%2Fdid%3Aion%3AEiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA%2Fissue%2Fget-credential-manifest%3Fid%3D611b5836e93d08000af6f1bc%26credential_types%3DPastEmploymentPosition%26issuerDid%3Ddid%3Aion%3AEiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") + private val wrongDeepLink = DeepLinkMocks.CredentialManifestDeepLinkDevNet + + @Test + fun verifyOffersSuccess() { + subject.verifyOffers( + offers, + correctDeepLink + ) { + it.handleResult({ isVerified -> + assert(isVerified) + }, { error -> + assert(false) { "${error.toJsonObject()}" } + }) + } + } + + @Test + fun verifyOffersError() { + subject.verifyOffers( + offers, + wrongDeepLink + ) { + it.handleResult({ + assert(false) { "${VCLErrorCode.MismatchedOfferIssuerDid.value} error code is expected" } + }, { error -> + assert(error.errorCode == VCLErrorCode.MismatchedOfferIssuerDid.value) + }) + } + } +} \ No newline at end of file diff --git a/VCL/src/test/java/io/velocitycareerlabs/verifiers/PresentationRequestByDeepLinkVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/PresentationRequestByDeepLinkVerifierTest.kt new file mode 100644 index 00000000..d40d8cfd --- /dev/null +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/PresentationRequestByDeepLinkVerifierTest.kt @@ -0,0 +1,46 @@ +package io.velocitycareerlabs.verifiers + +import io.velocitycareerlabs.api.entities.VCLDeepLink +import io.velocitycareerlabs.api.entities.error.VCLErrorCode +import io.velocitycareerlabs.api.entities.handleResult +import io.velocitycareerlabs.impl.data.verifiers.PresentationRequestByDeepLinkVerifierImpl +import io.velocitycareerlabs.infrastructure.resources.valid.DeepLinkMocks +import io.velocitycareerlabs.infrastructure.resources.valid.PresentationRequestMocks +import org.junit.Test + +class PresentationRequestByDeepLinkVerifierTest { + private val subject = PresentationRequestByDeepLinkVerifierImpl() + private val presentationRequest = PresentationRequestMocks.PresentationRequest + + private val correctDeepLink = + VCLDeepLink("velocity-network-devnet://inspect?request_uri=https%3A%2F%2Fdevagent.velocitycareerlabs.io%2Fapi%2Fholder%2Fv0.6%2Forg%2Fdid%3Avelocity%3A0xd4df29726d500f9b85bc6c7f1b3c021f16305692%2Fissue%2Fget-credential-manifest%3Fid%3D611b5836e93d08000af6f1bc%26credential_types%3DPastEmploymentPosition%26issuerDid%3Ddid%3Avelocity%3A0xd4df29726d500f9b85bc6c7f1b3c021f16305692") + private val wrongDeepLink = DeepLinkMocks.PresentationRequestDeepLinkDevNet + + @Test + fun testVerifyCredentialManifestSuccess() { + subject.verifyPresentationRequest( + presentationRequest, + correctDeepLink + ) { + it.handleResult({ isVerified -> + assert(isVerified) + }, { error -> + assert(false) { "${error.toJsonObject()}" } + }) + } + } + + @Test + fun testVerifyCredentialManifestError() { + subject.verifyPresentationRequest( + presentationRequest, + wrongDeepLink + ) { + it.handleResult({ + assert(false) { "${VCLErrorCode.MismatchedPresentationRequestInspectorDid.value} error code is expected" } + }, { error -> + assert(error.errorCode == VCLErrorCode.MismatchedPresentationRequestInspectorDid.value) + }) + } + } +} \ No newline at end of file diff --git a/VCL/src/test/java/io/velocitycareerlabs/utils/ProfileServiceTypeVerifierTest.kt b/VCL/src/test/java/io/velocitycareerlabs/verifiers/ProfileServiceTypeVerifierTest.kt similarity index 99% rename from VCL/src/test/java/io/velocitycareerlabs/utils/ProfileServiceTypeVerifierTest.kt rename to VCL/src/test/java/io/velocitycareerlabs/verifiers/ProfileServiceTypeVerifierTest.kt index 22057766..4e3febba 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/utils/ProfileServiceTypeVerifierTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/verifiers/ProfileServiceTypeVerifierTest.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.velocitycareerlabs.utils +package io.velocitycareerlabs.verifiers import io.velocitycareerlabs.api.entities.* import io.velocitycareerlabs.api.entities.error.VCLStatusCode diff --git a/app/src/main/java/com/vcl/wallet/Utils.kt b/app/src/main/java/com/vcl/wallet/Utils.kt index 6f4a0be0..ffc2709b 100644 --- a/app/src/main/java/com/vcl/wallet/Utils.kt +++ b/app/src/main/java/com/vcl/wallet/Utils.kt @@ -14,10 +14,10 @@ object Utils { fun getApprovedRejectedOfferIdsMock(offers: VCLOffers): Pair, List> { val approvedOfferIds: List = listOfNotNull( - offers.all.optJSONObject(0)?.optString("id") + offers.all[0].id ) val rejectedOfferIds: List = listOfNotNull( - offers.all.optJSONObject(1)?.optString("id") + offers.all[1].id ) return Pair(approvedOfferIds, rejectedOfferIds) } From bdcf57b1af611bc921005f00663fe1d7b6fa228b Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Mon, 18 Dec 2023 12:55:12 +0200 Subject: [PATCH 2/7] fix version --- VCL/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index 8a7b28a5..fd133c6d 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.22.0" + versionName "1.21.0" versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" From e31a14972a014f29e98733b76b1c81b78da8a0a9 Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Mon, 18 Dec 2023 16:01:52 +0200 Subject: [PATCH 3/7] fix publishing singing --- VCL/build.gradle | 24 +++++++------------ .../api/entities/VCLCredentialManifest.kt | 1 + .../entities/VCLCredentialManifestTest.kt | 1 + 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index fd133c6d..efb2b10d 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -150,14 +150,6 @@ afterEvaluate { url = 'https://github.com/velocitycareerlabs/WalletAndroid' } } - signing { - useInMemoryPgpKeys( - rootProject.ext.signingKeyId, - rootProject.ext.signingPrivateKey, - rootProject.ext.signingPassword, - ) - // sign publishing.publications - } } release(MavenPublication) { groupId getGroupId() @@ -202,17 +194,17 @@ afterEvaluate { url = 'https://github.com/velocitycareerlabs/WalletAndroid' } } - signing { - useInMemoryPgpKeys( - rootProject.ext.signingKeyId, - rootProject.ext.signingPrivateKey, - rootProject.ext.signingPassword, - ) - // sign publishing.publications - } } } } + signing { + useInMemoryPgpKeys( + rootProject.ext.signingKeyId, + rootProject.ext.signingPrivateKey, + rootProject.ext.signingPassword, + ) + sign publishing.publications + } } repositories { diff --git a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt index 4dd896a6..02c4a3a0 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/api/entities/VCLCredentialManifest.kt @@ -14,6 +14,7 @@ data class VCLCredentialManifest( val deepLink: VCLDeepLink? = null ) { val iss: String get() = jwt.payload?.toJSONObject()?.get(KeyIss) as? String ?: "" + val did: String get() = iss val aud: String get() = retrieveAud() val issuerId: String get() = jwt.payload?.toJSONObject()?.get(CodingKeys.KeyIssuer) as? String ?: (jwt.payload?.toJSONObject()?.get(CodingKeys.KeyIssuer) as? Map<*, *>)?.get(CodingKeys.KeyId) as? String diff --git a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt index 800fddf0..c8f2712e 100644 --- a/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt +++ b/VCL/src/test/java/io/velocitycareerlabs/entities/VCLCredentialManifestTest.kt @@ -35,6 +35,7 @@ class VCLCredentialManifestTest { @Test fun testProps() { assert(subject.iss == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") + assert(subject.did == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") assert(subject.issuerId == "did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") assert(subject.aud == "https://devagent.velocitycareerlabs.io/api/holder/v0.6/org/did:ion:EiApMLdMb4NPb8sae9-hXGHP79W1gisApVSE80USPEbtJA") assert(subject.exchangeId == "645e315309237c760ac022b1") From 1d42f7e6e443fddabc7f88f15ee2b04774d5174d Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Tue, 19 Dec 2023 16:23:57 +0200 Subject: [PATCH 4/7] logs --- VCL/build.gradle | 2 +- .../impl/data/verifiers/CredentialDidVerifierImpl.kt | 2 -- .../verifiers/CredentialManifestByDeepLinkVerifierImpl.kt | 4 ++++ .../data/verifiers/CredentialsByDeepLinkVerifierImpl.kt | 8 +++++--- .../impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt | 7 +++++-- .../PresentationRequestByDeepLinkVerifierImpl.kt | 4 ++++ 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index efb2b10d..0b7b1a7e 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.21.0" + versionName "1.21.1" versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt index 99760129..2b818d46 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialDidVerifierImpl.kt @@ -12,8 +12,6 @@ import io.velocitycareerlabs.api.entities.VCLJwt import io.velocitycareerlabs.api.entities.VCLJwtVerifiableCredentials import io.velocitycareerlabs.api.entities.VCLResult import io.velocitycareerlabs.impl.domain.verifiers.CredentialDidVerifier -import java.util.concurrent.CompletableFuture -import java.util.concurrent.CopyOnWriteArrayList internal class CredentialDidVerifierImpl: CredentialDidVerifier { diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt index 653474d3..a4177df5 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialManifestByDeepLinkVerifierImpl.kt @@ -12,8 +12,11 @@ import io.velocitycareerlabs.api.entities.VCLResult import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.api.entities.error.VCLErrorCode import io.velocitycareerlabs.impl.domain.verifiers.CredentialManifestByDeepLinkVerifier +import io.velocitycareerlabs.impl.utils.VCLLog class CredentialManifestByDeepLinkVerifierImpl: CredentialManifestByDeepLinkVerifier { + private val TAG = CredentialManifestByDeepLinkVerifierImpl::class.simpleName + override fun verifyCredentialManifest( credentialManifest: VCLCredentialManifest, deepLink: VCLDeepLink, @@ -22,6 +25,7 @@ class CredentialManifestByDeepLinkVerifierImpl: CredentialManifestByDeepLinkVeri if (credentialManifest.issuerId == deepLink.did) { completionBlock(VCLResult.Success(true)) } else { + VCLLog.e(TAG, "credential manifest: ${credentialManifest.jwt.encodedJwt} \ndeepLink: ${deepLink.value}") completionBlock((VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedRequestIssuerDid.value)))) } } diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt index f114062d..22591f92 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/CredentialsByDeepLinkVerifierImpl.kt @@ -12,16 +12,18 @@ import io.velocitycareerlabs.api.entities.VCLResult import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.api.entities.error.VCLErrorCode import io.velocitycareerlabs.impl.domain.verifiers.CredentialsByDeepLinkVerifier -import java.util.concurrent.CompletableFuture +import io.velocitycareerlabs.impl.utils.VCLLog class CredentialsByDeepLinkVerifierImpl: CredentialsByDeepLinkVerifier { + private val TAG = CredentialsByDeepLinkVerifierImpl::class.simpleName + override fun verifyCredentials( jwtCredentials: List, deepLink: VCLDeepLink, completionBlock: (VCLResult) -> Unit ) { - val errorCredential = jwtCredentials.find { it.iss != deepLink.did } - errorCredential?.let { + jwtCredentials.find { it.iss != deepLink.did }?.let { mismatchedCredential -> + VCLLog.e(TAG, "mismatched credential: ${mismatchedCredential.encodedJwt} \ndeepLink: ${deepLink.value}") completionBlock(VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedCredentialIssuerDid.value))) } ?: run { completionBlock(VCLResult.Success(true)) diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt index a58ed7dd..aaca3e5e 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/OffersByDeepLinkVerifierImpl.kt @@ -12,15 +12,18 @@ import io.velocitycareerlabs.api.entities.VCLResult import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.api.entities.error.VCLErrorCode import io.velocitycareerlabs.impl.domain.verifiers.OffersByDeepLinkVerifier +import io.velocitycareerlabs.impl.utils.VCLLog class OffersByDeepLinkVerifierImpl: OffersByDeepLinkVerifier { + private val TAG = OffersByDeepLinkVerifierImpl::class.simpleName + override fun verifyOffers( offers: VCLOffers, deepLink: VCLDeepLink, completionBlock: (VCLResult) -> Unit ) { - val errorOffer = offers.all.find { it.issuerId != deepLink.did } - errorOffer?.let { + offers.all.find { it.issuerId != deepLink.did }?.let { mismatchedOffer -> + VCLLog.e(TAG, "mismatched offer: ${mismatchedOffer.payload} \ndeepLink: ${deepLink.value}") completionBlock(VCLResult.Failure(VCLError(errorCode = VCLErrorCode.MismatchedOfferIssuerDid.value))) } ?: run { completionBlock(VCLResult.Success(true)) diff --git a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt index 75509196..25b846c5 100644 --- a/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt +++ b/VCL/src/main/java/io/velocitycareerlabs/impl/data/verifiers/PresentationRequestByDeepLinkVerifierImpl.kt @@ -12,8 +12,11 @@ import io.velocitycareerlabs.api.entities.VCLResult import io.velocitycareerlabs.api.entities.error.VCLError import io.velocitycareerlabs.api.entities.error.VCLErrorCode import io.velocitycareerlabs.impl.domain.verifiers.PresentationRequestByDeepLinkVerifier +import io.velocitycareerlabs.impl.utils.VCLLog class PresentationRequestByDeepLinkVerifierImpl: PresentationRequestByDeepLinkVerifier { + private val TAG = PresentationRequestByDeepLinkVerifierImpl::class.simpleName + override fun verifyPresentationRequest( presentationRequest: VCLPresentationRequest, deepLink: VCLDeepLink, @@ -22,6 +25,7 @@ class PresentationRequestByDeepLinkVerifierImpl: PresentationRequestByDeepLinkVe if (presentationRequest.iss == deepLink.did) { completionBlock(VCLResult.Success(true)) } else { + VCLLog.e(TAG, "presentation request: ${presentationRequest.jwt.encodedJwt} \ndeepLink: ${deepLink.value}") completionBlock(VCLResult.Failure( VCLError(errorCode = VCLErrorCode.MismatchedPresentationRequestInspectorDid.value) )) From 5790aed2b3de3356cd7306dc07f3fc49a0e6fb09 Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Wed, 20 Dec 2023 17:00:02 +0200 Subject: [PATCH 5/7] sdk v1.21.3 --- VCL/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index 0b7b1a7e..209e638f 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.21.1" + versionName "1.21.3" versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" From 105266b77484850098148bd56bf40cbda04a0ebe Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Wed, 20 Dec 2023 21:10:42 +0200 Subject: [PATCH 6/7] sdk v1.21.4 --- VCL/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index 209e638f..4e456bc5 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.21.3" + versionName "1.21.4" versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" From 5619e6423b7a6c7bd6d2ff928812963ee8acd5d4 Mon Sep 17 00:00:00 2001 From: Michael Avoyan Date: Wed, 20 Dec 2023 22:39:52 +0200 Subject: [PATCH 7/7] sdk v1.21.5 --- VCL/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VCL/build.gradle b/VCL/build.gradle index 4e456bc5..0e2970d0 100644 --- a/VCL/build.gradle +++ b/VCL/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { minSdk 24 targetSdk 33 - versionName "1.21.4" + versionName "1.21.5" versionCode 117 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro"