diff --git a/src/main/kotlin/id/walt/auditor/Auditor.kt b/src/main/kotlin/id/walt/auditor/Auditor.kt index a9f1a7e5..1d3f132c 100644 --- a/src/main/kotlin/id/walt/auditor/Auditor.kt +++ b/src/main/kotlin/id/walt/auditor/Auditor.kt @@ -41,14 +41,14 @@ class WaltIdAuditor : Auditor() { log.debug { "Verifying vc with ${policy.id} ..." } val vcResult = policy.verify(vc) - val success = AtomicBoolean(vcResult.outcome) + val success = AtomicBoolean(vcResult.result) val allErrors = vcResult.errors.toMutableList() if (allErrors.isEmpty() && vc is VerifiablePresentation) { vc.verifiableCredential?.forEach { cred -> log.debug { "Verifying ${cred.type.last()} in VP with ${policy.id}..." } val vpResult = policy.verify(cred) allErrors.addAll(vpResult.errors) - success.compareAndSet(true, vpResult.outcome) + success.compareAndSet(true, vpResult.result) } } allErrors.forEach { log.error { "${policy.id}: $it" } } diff --git a/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt b/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt index c95e316b..10d49423 100644 --- a/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt +++ b/src/main/kotlin/id/walt/auditor/VerificationPolicy.kt @@ -36,19 +36,27 @@ data class VerificationPolicyMetadata( val isMutable: Boolean ) -class VerificationPolicyResult(val outcome: Boolean, val errors: List = listOf()) { +data class VerificationPolicyResult(val result: Boolean, val errors: List = listOf()) { companion object { fun success() = VerificationPolicyResult(true) - fun failure(error: Any) = VerificationPolicyResult(false, listOf(error)) - fun failure(errors: List = listOf()) = VerificationPolicyResult(false, errors.toList()) + fun failure(error: Throwable): VerificationPolicyResult { + log.debug { "VerificationPolicy failed: ${error.stackTraceToString()}" } + return VerificationPolicyResult(false, listOf(error)) + } + fun failure(errors: List = listOf()) = VerificationPolicyResult(false, errors.toList()) } - val isSuccess = outcome - val isFailure = !outcome + + val isSuccess = result + val isFailure = !result + + fun getErrorString() = errors.mapIndexed { index, throwable -> + "#${index + 1}: ${throwable::class.simpleName ?: "Error"} - ${throwable.message}" + }.joinToString() override fun toString(): String { - return when(outcome) { - true -> "true" - false -> "false $errors" + return when (result) { + true -> "passed" + false -> "failed: ${getErrorString()}" } } } @@ -81,13 +89,15 @@ class SignaturePolicy : SimpleVerificationPolicy() { override val description: String = "Verify by signature" override fun doVerify(vc: VerifiableCredential) = runCatching { log.debug { "is jwt: ${vc.jwt != null}" } - VerificationPolicyResult(when (vc.jwt) { - null -> jsonLdCredentialService.verify(vc.encode()).verified - else -> jwtCredentialService.verify(vc.encode()).verified - }) - }.onFailure { - log.error(it.localizedMessage) - }.getOrDefault(VerificationPolicyResult.failure()) + VerificationPolicyResult( + when (vc.jwt) { + null -> jsonLdCredentialService.verify(vc.encode()).verified + else -> jwtCredentialService.verify(vc.encode()).verified + } + ) + }.getOrElse { + VerificationPolicyResult.failure(it) + } } /** @@ -95,14 +105,15 @@ class SignaturePolicy : SimpleVerificationPolicy() { */ data class JsonSchemaPolicyArg(val schema: String) -class JsonSchemaPolicy(schemaPolicyArg: JsonSchemaPolicyArg?) : OptionalParameterizedVerificationPolicy(schemaPolicyArg) { +class JsonSchemaPolicy(schemaPolicyArg: JsonSchemaPolicyArg?) : + OptionalParameterizedVerificationPolicy(schemaPolicyArg) { constructor() : this(null) override val description: String = "Verify by JSON schema" override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { return (argument?.schema ?: vc.credentialSchema?.id)?.let { SchemaValidatorFactory.get(it).validate(vc.toJson()) - } ?: VerificationPolicyResult.failure() + } ?: VerificationPolicyResult.failure(IllegalArgumentException("No \"argument.schema\" or \"credentialSchema.id\" supplied.")) } override val applyToVP: Boolean @@ -123,8 +134,11 @@ class TrustedIssuerDidPolicy : SimpleVerificationPolicy() { return try { VerificationPolicyResult(DidService.loadOrResolveAnyDid(vc.issuerId!!) != null) } catch (e: ClientRequestException) { - if (!e.message.contains("did must be a valid DID") && !e.message.contains("Identifier Not Found")) throw e - VerificationPolicyResult.failure() + VerificationPolicyResult.failure(IllegalArgumentException(when { + "did must be a valid DID" in e.message -> "did must be a valid DID" + "Identifier Not Found" in e.message -> "Identifier Not Found" + else -> throw e + })) } } } @@ -153,11 +167,10 @@ class TrustedIssuerRegistryPolicy(registryArg: TrustedIssuerRegistryPolicyArg) : val issuerDid = vc.issuerId!! val resolvedIssuerDid = DidService.loadOrResolveAnyDid(issuerDid) - ?: throw Exception("Could not resolve issuer DID $issuerDid") + ?: throw IllegalArgumentException("Could not resolve issuer DID $issuerDid") if (resolvedIssuerDid.id != issuerDid) { - log.debug { "Resolved DID ${resolvedIssuerDid.id} does not match the issuer DID $issuerDid" } - return VerificationPolicyResult.failure() + return VerificationPolicyResult.failure(IllegalArgumentException("Resolved DID ${resolvedIssuerDid.id} does not match the issuer DID $issuerDid")) } var tirRecord: TrustedIssuer @@ -249,17 +262,17 @@ class CredentialStatusPolicy : SimpleVerificationPolicy() { override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { val cs = Klaxon().parse(vc.toJson())!!.credentialStatus!! - return VerificationPolicyResult(when (cs.type) { + fun revocationVerificationPolicy(revoked: Boolean, timeOfRevocation: Long?) = + if (!revoked) VerificationPolicyResult.success() else VerificationPolicyResult.failure(IllegalArgumentException("CredentialStatus (type ${cs.type}) was REVOKED at timestamp $timeOfRevocation for id ${cs.id}.")) + + return when (cs.type) { "SimpleCredentialStatus2022" -> { val rs = RevocationClientService.getService() val result = rs.checkRevoked(cs.id) - !result.isRevoked - } - - else -> { - throw IllegalArgumentException("CredentialStatus type \"\"") + revocationVerificationPolicy(result.isRevoked, result.timeOfRevocation) } - }) + else -> VerificationPolicyResult.failure(UnsupportedOperationException("CredentialStatus type \"${cs.type}\" is not yet supported.")) + } } } @@ -345,12 +358,12 @@ data class VerificationResult( /*** * Validation status over all policy results. */ - val outcome: Boolean = false, + val result: Boolean = false, val policyResults: Map ) { - @Deprecated("Deprecated in favour of: outcome") - val valid: Boolean = outcome + @Deprecated("Deprecated in favour of: result") + val valid: Boolean = result override fun toString() = - "VerificationResult(outcome=$outcome, policyResults={${policyResults.entries.joinToString { it.key + "=" + it.value }}})" + "VerificationResult(result=$result, policyResults={${policyResults.entries.joinToString { it.key + "=" + it.value }}})" } diff --git a/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt b/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt index acdfa12f..43c8ba8c 100644 --- a/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt +++ b/src/main/kotlin/id/walt/auditor/dynamic/OPAPolicyEngine.kt @@ -22,7 +22,7 @@ object OPAPolicyEngine : PolicyEngine { try { ProcessBuilder("opa").start() } catch (e: Exception) { - return VerificationPolicyResult.failure("Executable for OPA policy engine not installed. See https://www.openpolicyagent.org/docs/#running-opa") + return VerificationPolicyResult.failure(IllegalStateException("Executable for OPA policy engine not installed. See https://www.openpolicyagent.org/docs/#running-opa")) } val regoFile = resolveContentToFile(policy, tempPrefix = TEMP_PREFIX, tempPostfix = ".rego") val dataFile = File.createTempFile("data", ".json") diff --git a/src/main/kotlin/id/walt/cli/EssifCommand.kt b/src/main/kotlin/id/walt/cli/EssifCommand.kt index 35d1d8c6..4daa8170 100644 --- a/src/main/kotlin/id/walt/cli/EssifCommand.kt +++ b/src/main/kotlin/id/walt/cli/EssifCommand.kt @@ -18,6 +18,7 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import java.io.File import java.util.* +import kotlin.NoSuchElementException class EssifCommand : CliktCommand( name = "essif", @@ -119,7 +120,7 @@ class EssifTimestampCreateCommand : CliktCommand( override fun run() { echo("Creating timestamp") - if (!dataFile.exists()) throw Exception("File ${dataFile.absoluteFile} not found.") + if (!dataFile.exists()) throw NoSuchElementException("File ${dataFile.absoluteFile} not found.") val transactionHash = WaltIdTimestampService().createTimestamp(did, ethKeyAlias ?: did, "{\"test\": \"${UUID.randomUUID()}\"}") @@ -146,7 +147,7 @@ class EssifTimestampGetCommand : CliktCommand( when { id != null -> WaltIdTimestampService().getByTimestampId(id!!) txhash != null -> WaltIdTimestampService().getByTransactionHash(txhash!!) - else -> throw Exception("Either timestamp ID or transaction hash need to be specified") + else -> throw IllegalArgumentException("Either timestamp ID or transaction hash need to be specified") } } diff --git a/src/main/kotlin/id/walt/cli/VcCommand.kt b/src/main/kotlin/id/walt/cli/VcCommand.kt index 7248f6fd..3c56147c 100644 --- a/src/main/kotlin/id/walt/cli/VcCommand.kt +++ b/src/main/kotlin/id/walt/cli/VcCommand.kt @@ -201,8 +201,8 @@ class VerifyVcCommand : CliktCommand( echo("Verifying from file \"$src\"...\n") when { - !src.exists() -> throw Exception("Could not load file: \"$src\".") - usedPolicies.keys.any { !PolicyRegistry.contains(it) } -> throw Exception( + !src.exists() -> throw NoSuchElementException("Could not load file: \"$src\".") + usedPolicies.keys.any { !PolicyRegistry.contains(it) } -> throw NoSuchElementException( "Unknown verification policy specified: ${ usedPolicies.keys.minus(PolicyRegistry.listPolicies().toSet()).joinToString() }" @@ -219,7 +219,7 @@ class VerifyVcCommand : CliktCommand( verificationResult.policyResults.forEach { (policy, result) -> echo("$policy:\t $result") } - echo("Verified:\t\t ${verificationResult.outcome}") + echo("Verified:\t\t ${verificationResult.result}") } } diff --git a/src/main/kotlin/id/walt/common/FileFun.kt b/src/main/kotlin/id/walt/common/FileFun.kt index 86916ec8..833544d2 100644 --- a/src/main/kotlin/id/walt/common/FileFun.kt +++ b/src/main/kotlin/id/walt/common/FileFun.kt @@ -15,7 +15,7 @@ fun readWhenContent(file: File, errorMessage: String? = null) = readWhenContent( fun readWhenContent(file: Path, errorMessage: String? = null) = when { file.exists() && file.fileSize() > 0 -> file.readText() - else -> throw Exception(errorMessage ?: "Expecting file with content at: ${file.absolutePathString()}") + else -> throw NoSuchElementException(errorMessage ?: "Expecting file with content at: ${file.absolutePathString()}") } fun readEssifBearerToken(): String = readWhenContent( diff --git a/src/main/kotlin/id/walt/common/OidcUtil.kt b/src/main/kotlin/id/walt/common/OidcUtil.kt index 37963a2f..f0e39129 100644 --- a/src/main/kotlin/id/walt/common/OidcUtil.kt +++ b/src/main/kotlin/id/walt/common/OidcUtil.kt @@ -106,7 +106,7 @@ object OidcUtil { if (jwtService.verify(authRequestJwt)) { log.debug { "Successfully verified signature of JWT" } } else { - throw Exception("Could not verify JWT $authRequestJwt") + throw IllegalArgumentException("Could not verify JWT $authRequestJwt") } //val didAuthRequestStr = String(decBase64(authRequestJwt)) @@ -115,15 +115,15 @@ object OidcUtil { val request = Klaxon().parse(jwt.payload.toString())!! if (oidcAuthReq.callback != request.callback) { - throw Exception("Callbacks in OidcRequest data structure are not matching we got: ${oidcAuthReq.callback} & ${request.callback}") + throw IllegalArgumentException("Callbacks in OidcRequest data structure are not matching we got: ${oidcAuthReq.callback} & ${request.callback}") } if (scope != request.scope) { - throw Exception("Scopes in OidcRequest data structure are not matching we got: $scope & ${request.scope}") + throw IllegalArgumentException("Scopes in OidcRequest data structure are not matching we got: $scope & ${request.scope}") } if (responseType != request.response_type) { - throw Exception("Scopes in OidcRequest data structure are not matching we got: $responseType & ${request.response_type}") + throw IllegalArgumentException("Scopes in OidcRequest data structure are not matching we got: $responseType & ${request.response_type}") } return request diff --git a/src/main/kotlin/id/walt/common/SerializationUtils.kt b/src/main/kotlin/id/walt/common/SerializationUtils.kt index e1bcc477..b7f7809f 100644 --- a/src/main/kotlin/id/walt/common/SerializationUtils.kt +++ b/src/main/kotlin/id/walt/common/SerializationUtils.kt @@ -108,7 +108,7 @@ val didVerificationRelationshipsConverter = object : Converter { when (item) { is String -> VerificationMethod.Reference(item) is JsonObject -> Klaxon().parseFromJsonObject(item) - else -> throw Exception("Verification relationship must be either String or JsonObject") + else -> throw IllegalArgumentException("Verification relationship must be either String or JsonObject") } } } diff --git a/src/main/kotlin/id/walt/credentials/w3c/JsonConverter.kt b/src/main/kotlin/id/walt/credentials/w3c/JsonConverter.kt index a919b3c0..bd45ef27 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/JsonConverter.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/JsonConverter.kt @@ -18,7 +18,7 @@ object JsonConverter { is JsonElement -> value //else -> JsonNull - else -> throw Exception("Json values can only be Number, String, Boolean, Null, List or Map, not \"${value::class.jvmName}\": toString = $value") + else -> throw IllegalArgumentException("Json values can only be Number, String, Boolean, Null, List or Map, not \"${value::class.jvmName}\": toString = $value") } } diff --git a/src/main/kotlin/id/walt/credentials/w3c/VerifiablePresentation.kt b/src/main/kotlin/id/walt/credentials/w3c/VerifiablePresentation.kt index 42e1babc..cf2338c4 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/VerifiablePresentation.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/VerifiablePresentation.kt @@ -15,7 +15,7 @@ class VerifiablePresentation internal constructor(jsonObject: JsonObject) : Veri when (it) { is JsonPrimitive -> VerifiableCredential.fromString(it.content) is JsonObject -> VerifiableCredential.fromJsonObject(it) - else -> throw Exception("Invalid type of verifiableCredential item") + else -> throw IllegalArgumentException("Invalid type of verifiableCredential item") } } diff --git a/src/main/kotlin/id/walt/credentials/w3c/W3CCredentialSchema.kt b/src/main/kotlin/id/walt/credentials/w3c/W3CCredentialSchema.kt index 9c996637..8156a177 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/W3CCredentialSchema.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/W3CCredentialSchema.kt @@ -26,8 +26,8 @@ class W3CCredentialSchema( fun fromJsonObject(jsonObject: JsonObject): W3CCredentialSchema { return W3CCredentialSchema( - id = jsonObject["id"]?.jsonPrimitive?.content ?: throw Exception("Missing id property in CredentialSchema"), - type = jsonObject["type"]?.jsonPrimitive?.content ?: throw Exception("Missing id property in CredentialSchema"), + id = jsonObject["id"]?.jsonPrimitive?.content ?: throw IllegalArgumentException("Missing id property in CredentialSchema"), + type = jsonObject["type"]?.jsonPrimitive?.content ?: throw IllegalArgumentException("Missing id property in CredentialSchema"), properties = jsonObject.filterKeys { k -> !W3CProof.PREDEFINED_PROPERTY_KEYS.contains(k) } .mapValues { entry -> JsonConverter.fromJsonElement(entry.value) } ) diff --git a/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt b/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt index 35b8deeb..c8ef7ce7 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/schema/NetworkntSchemaValidator.kt @@ -5,6 +5,7 @@ import com.networknt.schema.JsonSchemaFactory import com.networknt.schema.SpecVersion import id.walt.auditor.VerificationPolicyResult import mu.KotlinLogging +import javax.naming.directory.SchemaViolationException class NetworkntSchemaValidator(versionFlag: SpecVersion.VersionFlag, schema: String) : SchemaValidator { private val log = KotlinLogging.logger {} @@ -18,6 +19,6 @@ class NetworkntSchemaValidator(versionFlag: SpecVersion.VersionFlag, schema: Str log.debug { "Could not validate vc against schema. The validation errors are:" } errors.forEach { log.debug { it } } } - return VerificationPolicyResult(errors.isEmpty(), errors) + return VerificationPolicyResult(errors.isEmpty(), errors.map { SchemaViolationException(it.toString()) }) } } diff --git a/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt b/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt index 72a72714..d376c4a2 100644 --- a/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt +++ b/src/main/kotlin/id/walt/credentials/w3c/schema/PWallSchemaValidator.kt @@ -3,6 +3,7 @@ package id.walt.credentials.w3c.schema import id.walt.auditor.VerificationPolicyResult import mu.KotlinLogging import net.pwall.json.schema.JSONSchema +import javax.naming.directory.SchemaViolationException class PWallSchemaValidator(schema: String) : SchemaValidator { private val log = KotlinLogging.logger {} @@ -15,6 +16,8 @@ class PWallSchemaValidator(schema: String) : SchemaValidator { log.debug { "Could not validate vc against schema. The validation errors are:" } errors.forEach { log.debug { it } } } - return VerificationPolicyResult(errors.isEmpty(), errors) + return VerificationPolicyResult(errors.isEmpty(), errors.map { + SchemaViolationException(it.error) + }) } } diff --git a/src/main/kotlin/id/walt/crypto/Key.kt b/src/main/kotlin/id/walt/crypto/Key.kt index c8773a54..fd3712c6 100644 --- a/src/main/kotlin/id/walt/crypto/Key.kt +++ b/src/main/kotlin/id/walt/crypto/Key.kt @@ -19,7 +19,7 @@ data class Key(val keyId: KeyId, val algorithm: KeyAlgorithm, val cryptoProvider fun getPublicKey(): PublicKey = when { keyPair != null -> keyPair!!.public keysetHandle != null -> TinkKeyStoreService().loadPublicKey(this) as ECPublicKey - else -> throw Exception("No public key for $keyId") + else -> throw NoSuchElementException("No public key for $keyId") } fun getPublicKeyBytes(): ByteArray { diff --git a/src/main/kotlin/id/walt/crypto/UVarInt.kt b/src/main/kotlin/id/walt/crypto/UVarInt.kt index ffc38953..6c154545 100644 --- a/src/main/kotlin/id/walt/crypto/UVarInt.kt +++ b/src/main/kotlin/id/walt/crypto/UVarInt.kt @@ -28,7 +28,7 @@ class UVarInt(val value: UInt) { fun fromBytes(bytes: ByteArray): UVarInt { if (bytes.isEmpty()) - throw Exception("Empty byte array") + throw IllegalArgumentException("Empty byte array") var idx = 0 var value = (bytes[idx].toUInt() and LSB) diff --git a/src/main/kotlin/id/walt/model/oidc/IDToken.kt b/src/main/kotlin/id/walt/model/oidc/IDToken.kt index a4c96635..c08a8fb2 100644 --- a/src/main/kotlin/id/walt/model/oidc/IDToken.kt +++ b/src/main/kotlin/id/walt/model/oidc/IDToken.kt @@ -21,7 +21,7 @@ data class IDToken( ) { fun sign(): String { return subject?.let {JwtService.getService().sign(it, Klaxon().toJsonString(this)) } ?: - throw Exception("No subject specified") + throw IllegalArgumentException("No subject specified") } fun verify(): Boolean { diff --git a/src/main/kotlin/id/walt/model/oidc/IssuanceInitiationRequest.kt b/src/main/kotlin/id/walt/model/oidc/IssuanceInitiationRequest.kt index cb2a91b9..95f81a01 100644 --- a/src/main/kotlin/id/walt/model/oidc/IssuanceInitiationRequest.kt +++ b/src/main/kotlin/id/walt/model/oidc/IssuanceInitiationRequest.kt @@ -40,8 +40,8 @@ data class IssuanceInitiationRequest( companion object { fun fromQueryParams(params: Map>): IssuanceInitiationRequest { return IssuanceInitiationRequest( - issuer_url = params["issuer"]?.firstOrNull() ?: throw Exception("Missing parameter 'issuer'"), - credential_types = params["credential_type"] ?: throw Exception("Missing parameter(s) 'credential_type'"), + issuer_url = params["issuer"]?.firstOrNull() ?: throw IllegalArgumentException("Missing parameter 'issuer'"), + credential_types = params["credential_type"] ?: throw IllegalArgumentException("Missing parameter(s) 'credential_type'"), pre_authorized_code = params["pre-authorized_code"]?.firstOrNull(), user_pin_required = params["user_pin_required"]?.map { it.toBoolean() }?.firstOrNull() ?: false, op_state = params["op_state"]?.firstOrNull() diff --git a/src/main/kotlin/id/walt/model/oidc/SIOPv2Response.kt b/src/main/kotlin/id/walt/model/oidc/SIOPv2Response.kt index 56c95d82..612d2f83 100644 --- a/src/main/kotlin/id/walt/model/oidc/SIOPv2Response.kt +++ b/src/main/kotlin/id/walt/model/oidc/SIOPv2Response.kt @@ -53,14 +53,14 @@ data class SIOPv2Response( companion object { fun fromFormParams(params: Map): SIOPv2Response { - val vpTokenStr = params["vp_token"] ?: throw Exception("vp_token parameter must be set") + val vpTokenStr = params["vp_token"] ?: throw IllegalArgumentException("vp_token parameter must be set") val idToken = params["id_token"] val presentationSubmissionStr = params["presentation_submission"] return SIOPv2Response( vp_token = OIDCUtils.fromVpToken(vpTokenStr), presentation_submission = presentationSubmissionStr?.let { KlaxonWithConverters().parse(it) } ?: idToken?.let { IDToken.parse(it)?.vpTokenRef?.presentation_submission } - ?: throw Exception("Could not parse presentation_submission parameter"), + ?: throw IllegalArgumentException("Could not parse presentation_submission parameter"), id_token = idToken, state = params["state"] ) diff --git a/src/main/kotlin/id/walt/rest/auditor/AuditorRestController.kt b/src/main/kotlin/id/walt/rest/auditor/AuditorRestController.kt index e29c5ef5..e1bece63 100644 --- a/src/main/kotlin/id/walt/rest/auditor/AuditorRestController.kt +++ b/src/main/kotlin/id/walt/rest/auditor/AuditorRestController.kt @@ -33,7 +33,7 @@ object AuditorRestController { Auditor.getService().verify(cred, policies) } - ctx.json(VerificationResponse(valid = results.all { it.outcome }, results = results)) + ctx.json(VerificationResponse(valid = results.all { it.result }, results = results)) } fun verifyVPDocs() = document() diff --git a/src/main/kotlin/id/walt/rest/custodian/CustodianAPI.kt b/src/main/kotlin/id/walt/rest/custodian/CustodianAPI.kt index 8aeb065b..dc9b0739 100644 --- a/src/main/kotlin/id/walt/rest/custodian/CustodianAPI.kt +++ b/src/main/kotlin/id/walt/rest/custodian/CustodianAPI.kt @@ -3,6 +3,9 @@ package id.walt.rest.custodian import cc.vileda.openapi.dsl.externalDocs import cc.vileda.openapi.dsl.info import com.beust.klaxon.Klaxon +import com.beust.klaxon.KlaxonException +import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.nimbusds.oauth2.sdk.ParseException import id.walt.Values import id.walt.rest.ErrorResponse import id.walt.rest.OpenAPIUtils @@ -153,11 +156,55 @@ object CustodianAPI { } }.exception(IllegalArgumentException::class.java) { e, ctx -> log.error { e.stackTraceToString() } - ctx.json(ErrorResponse(e.message ?: " Illegal argument exception", 400)) + ctx.json(ErrorResponse(e.message ?: "Illegal argument exception", 400)) ctx.status(400) + }.exception(IllegalStateException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "Illegal state exception", 400)) + ctx.status(400) + }.exception(NoSuchElementException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "No such element", 400)) + ctx.status(404) + + // JSON + }.exception(MismatchedInputException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "Mismatched input", 400)) + ctx.status(404) + }.exception(com.fasterxml.jackson.core.JsonParseException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "JsonParseException", 400)) + ctx.status(404) + }.exception(com.google.gson.JsonParseException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "JsonParseException", 400)) + ctx.status(404) + }.exception(com.nimbusds.jose.shaded.gson.JsonParseException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "JsonParseException", 400)) + ctx.status(404) + }.exception(KlaxonException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "JsonParseException", 400)) + ctx.status(404) + + }.exception(ParseException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "OAuth2 parse exception", 400)) + ctx.status(404) + + + // Misc + }.exception(UnsupportedOperationException::class.java) { e, ctx -> + log.error { e.stackTraceToString() } + ctx.json(ErrorResponse(e.message ?: "Unsupported operation", 400)) + ctx.status(404) + + // Catch-all }.exception(Exception::class.java) { e, ctx -> log.error { e.stackTraceToString() } - ctx.json(ErrorResponse(e.message ?: " Unknown application error", 500)) + ctx.json(ErrorResponse(e.message ?: "Unknown application error", 500)) ctx.status(500) }.start(bindAddress, port) } diff --git a/src/main/kotlin/id/walt/services/did/DidService.kt b/src/main/kotlin/id/walt/services/did/DidService.kt index 057a0701..83cc3c7e 100644 --- a/src/main/kotlin/id/walt/services/did/DidService.kt +++ b/src/main/kotlin/id/walt/services/did/DidService.kt @@ -90,7 +90,7 @@ object DidService { DidMethod.iota -> createDidIota(keyAlias) DidMethod.jwk -> createDidJwk(keyAlias) DidMethod.cheqd -> createDidCheqd(keyAlias, options as? DidCheqdOptions) - else -> throw Exception("DID method $method not supported") + else -> throw UnsupportedOperationException("DID method $method not supported") } return didUrl @@ -112,7 +112,7 @@ object DidService { DidMethod.web.name -> resolveDidWeb(didUrl) DidMethod.ebsi.name -> resolveDidEbsi(didUrl) DidMethod.jwk.name -> resolveDidJwk(didUrl) - DidMethod.iota.name -> IotaService.resolveDid(didUrl.did) ?: throw Exception("Could not resolve $didUrl") + DidMethod.iota.name -> IotaService.resolveDid(didUrl.did) ?: throw IllegalArgumentException("Could not resolve $didUrl") DidMethod.cheqd.name -> CheqdService.resolveDid(didUrl.did) else -> TODO("did:${didUrl.method} not implemented yet") } @@ -151,7 +151,7 @@ object DidService { return when (version) { 1 -> resolveDidEbsiV1(didUrl) 2 -> resolveDidEbsiV2(didUrl) - else -> throw Exception("did:ebsi must have version 1 or 2") + else -> throw IllegalArgumentException("did:ebsi must have version 1 or 2") } } @@ -183,7 +183,7 @@ object DidService { val jwk = keyService.toJwk(didUrl.did) val vmId = "${didUrl.did}#${jwk.computeThumbprint()}" if (DidUrl.generateDidEbsiV2DidUrl(jwk.computeThumbprint().decode()).identifier != didUrl.identifier) { - throw Exception("Public key doesn't match with DID identifier") + throw IllegalArgumentException("Public key doesn't match with DID identifier") } return DidEbsi( context = listOf("https://w3id.org/did/v1"), @@ -211,7 +211,7 @@ object DidService { return when (version) { 1 -> createDidEbsiV1(keyAlias) 2 -> createDidEbsiV2(keyAlias) - else -> throw Exception("Did ebsi version must be 1 or 2") + else -> throw IllegalArgumentException("Did ebsi version must be 1 or 2") } } @@ -322,7 +322,7 @@ object DidService { private fun createDidWeb(keyAlias: String?, options: DidWebOptions?): String { - options ?: throw Exception("DidWebOptions are mandatory") + options ?: throw IllegalArgumentException("DidWebOptions are mandatory") if (options.domain.isNullOrEmpty()) throw IllegalArgumentException("Missing 'domain' parameter for creating did:web") @@ -408,7 +408,7 @@ object DidService { fun importDidFromFile(file: File): String { if (!file.exists()) - throw Exception("DID doc file not found") + throw NoSuchElementException("DID doc file not found") val doc = file.readText(StandardCharsets.UTF_8) val did = Did.decode(doc) storeDid(did!!.id, doc) @@ -569,7 +569,7 @@ object DidService { val vmType = if (algorithm == ECDSA_Secp256k1) EcdsaSecp256k1VerificationKey2019.name else EcdsaSecp256r1VerificationKey2019.name - val uncompressedPubKey = uncompressSecp256k1(pubKey, curve) ?: throw Exception("Error uncompressing public key bytes") + val uncompressedPubKey = uncompressSecp256k1(pubKey, curve) ?: throw IllegalArgumentException("Error uncompressing public key bytes") val key = Key(newKeyId(), algorithm, CryptoProvider.SUN, KeyPair(uncompressedPubKey.toECPublicKey(), null)) val pubKeyId = didUrl.did + "#" + didUrl.identifier @@ -636,7 +636,7 @@ object DidService { } fun importKeys(didUrl: String): Boolean { - val did = loadOrResolveAnyDid(didUrl) ?: throw Exception("Could not load or resolve $didUrl") + val did = loadOrResolveAnyDid(didUrl) ?: throw IllegalArgumentException("Could not load or resolve $didUrl") return (did.verificationMethod ?: listOf()) .asSequence() @@ -738,12 +738,12 @@ object DidService { fun importKeyForDidEbsiV2(did: String, key: JWK) { if (!isDidEbsiV2(did)) { - throw Exception("Specified DID is not did:ebsi version 2") + throw IllegalArgumentException("Specified DID is not did:ebsi version 2") } val thumbprint = key.computeThumbprint() val generatedDid = DidUrl.generateDidEbsiV2DidUrl(thumbprint.decode()) if (generatedDid.did != did) { - throw Exception("did doesn't match specified key") + throw IllegalArgumentException("did doesn't match specified key") } val vmId = "$did#$thumbprint" if (!keyService.hasKey(vmId)) { diff --git a/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt b/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt index e546e19b..ed5b85d2 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/cheqd/CheqdService.kt @@ -51,7 +51,7 @@ object CheqdService { // step#2. onboard did with cheqd registrar KlaxonWithConverters().parse(response)?.let { // step#2a. initialize - val job = initiateDidOnboarding(it.didDoc) ?: throw Exception("Failed to initialize the did onboarding process") + val job = initiateDidOnboarding(it.didDoc) ?: throw IllegalArgumentException("Failed to initialize the did onboarding process") val state = (job.didState as? ActionDidState) ?: throw IllegalArgumentException("Unexpected did state") // step#2b. sign the serialized payload val payloads = state.signingRequest.map { @@ -65,10 +65,10 @@ object CheqdService { it.didDoc.verificationMethod.first().id, // TODO: associate verificationMethodId with signature signatures )?.didState as? FinishedDidState)?.didDocument - ?: throw Exception("Failed to finalize the did onboarding process") + ?: throw IllegalArgumentException("Failed to finalize the did onboarding process") Did.decode(KlaxonWithConverters().toJsonString(didDocument)) as DidCheqd - } ?: throw Exception("Failed to fetch the did document from cheqd registrar helper") + } ?: throw IllegalArgumentException("Failed to fetch the did document from cheqd registrar helper") } fun resolveDid(did: String): DidCheqd { diff --git a/src/main/kotlin/id/walt/services/ecosystems/essif/EssifClient.kt b/src/main/kotlin/id/walt/services/ecosystems/essif/EssifClient.kt index 175aed10..496de378 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/essif/EssifClient.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/essif/EssifClient.kt @@ -269,7 +269,7 @@ object EssifClient { } } - throw Exception("Could not register DID (after $maxTries tries to contact EBSI)!") + throw IllegalStateException("Could not register DID (after $maxTries tries to contact EBSI)!") } // https://ec.europa.eu/cefdigital/wiki/display/BLOCKCHAININT/VC-Issuance+Flow diff --git a/src/main/kotlin/id/walt/services/ecosystems/essif/jsonrpc/WaltIdJsonRpcService.kt b/src/main/kotlin/id/walt/services/ecosystems/essif/jsonrpc/WaltIdJsonRpcService.kt index c4e42806..68fe8ff3 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/essif/jsonrpc/WaltIdJsonRpcService.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/essif/jsonrpc/WaltIdJsonRpcService.kt @@ -19,6 +19,7 @@ import org.web3j.rlp.RlpList import org.web3j.utils.Numeric import java.math.BigInteger import java.util.* +import kotlin.NoSuchElementException class WaltIdJsonRpcService : JsonRpcService() { @@ -39,7 +40,7 @@ class WaltIdJsonRpcService : JsonRpcService() { val token = ContextManager.hkvStore.getAsString( HKVKey("ebsi", did.substringAfterLast(":"), EssifClient.ebsiAccessTokenFile) ) - ?: throw Exception("Could not load EBSI access token. Make sure that the ESSIF onboarding flow is performed correctly.") + ?: throw NoSuchElementException("Could not load EBSI access token. Make sure that the ESSIF onboarding flow is performed correctly.") val unsignedTx = post(token, urlString, method, unsignedTransactionParams).result log.debug { "Unsigned transaction: $unsignedTx" } diff --git a/src/main/kotlin/id/walt/services/ecosystems/essif/userwallet/UserWalletService.kt b/src/main/kotlin/id/walt/services/ecosystems/essif/userwallet/UserWalletService.kt index e3743350..f1d1a1f8 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/essif/userwallet/UserWalletService.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/essif/userwallet/UserWalletService.kt @@ -300,10 +300,10 @@ object UserWalletService { /////////////////////////////////////////////////////////////////////////// // Validated nonce - if (nonce != decAccesTokenResp.nonce) throw Exception("Nonce in Access Token response not valid") + if (nonce != decAccesTokenResp.nonce) throw IllegalArgumentException("Nonce in Access Token response not valid") // Compare DID of EOS - if (accessTokenResponse.did != decAccesTokenResp.did) throw Exception("Decrypted DID does not match the DID of the siop response") + if (accessTokenResponse.did != decAccesTokenResp.did) throw IllegalArgumentException("Decrypted DID does not match the DID of the siop response") // TODO load MAC + validate payload @@ -451,7 +451,7 @@ object UserWalletService { // // if (false) {//!jwtService.verify(oidcReqUri.request)) { // log.error { "Could not verify Authentication Request Token signature: " + oidcReqUri.request } -// throw Exception("Could not verify Authentication Request Token signature: " + oidcReqUri.request) +// throw IllegalArgumentException("Could not verify Authentication Request Token signature: " + oidcReqUri.request) // } else { // println("\nJWT signature of Authentication Request Token Verified successfully ✔\n") // } @@ -495,7 +495,7 @@ object UserWalletService { log.debug { "Validating Authentication Request $authReq" } // if (authReq.claims.id_token.verified_claims.verification.trust_framework != "EBSI") { -// throw Exception("Trust framework needs to be: EBSI") +// throw IllegalArgumentException("Trust framework needs to be: EBSI") // } //TODO add further validations and validation based on the JSON schema diff --git a/src/main/kotlin/id/walt/services/ecosystems/iota/IotaService.kt b/src/main/kotlin/id/walt/services/ecosystems/iota/IotaService.kt index 3838856e..b4dfeadc 100644 --- a/src/main/kotlin/id/walt/services/ecosystems/iota/IotaService.kt +++ b/src/main/kotlin/id/walt/services/ecosystems/iota/IotaService.kt @@ -14,19 +14,19 @@ object IotaService { // TODO: implement iota key store interface, to avoid exposing private key! val privKey = KeyService.getService().load(keyId, KeyType.PRIVATE) if (privKey.algorithm != KeyAlgorithm.EdDSA_Ed25519) { - throw Exception("did:iota only supports keys of type ${KeyAlgorithm.EdDSA_Ed25519}") + throw UnsupportedOperationException("did:iota only supports keys of type ${KeyAlgorithm.EdDSA_Ed25519}") } val privKeyBytes = privKey.keyPair?.private?.let { (it as EdECPrivateKey).bytes.orElse(null) - } ?: throw Exception("Couldn't get private key bytes") + } ?: throw IllegalArgumentException("Couldn't get private key bytes") val ptr = iotaWrapper.create_did(privKeyBytes, privKeyBytes.size.toLong()) if (ptr.address() != 0L) { val doc = ptr.getString(0) iotaWrapper.free_str(ptr) - return (Did.decode(doc) ?: throw Exception("Error parsing did:iota document")) as DidIota + return (Did.decode(doc) ?: throw IllegalArgumentException("Error parsing did:iota document")) as DidIota } else { - throw Exception("Error creating did:iota") + throw IllegalStateException("Error creating did:iota") } } diff --git a/src/main/kotlin/id/walt/services/jwt/JwtService.kt b/src/main/kotlin/id/walt/services/jwt/JwtService.kt index 56f43e5a..63fec507 100644 --- a/src/main/kotlin/id/walt/services/jwt/JwtService.kt +++ b/src/main/kotlin/id/walt/services/jwt/JwtService.kt @@ -12,7 +12,7 @@ open class JwtService : WaltIdService() { // val recipientJWK = KeyManagementService.loadKeys(keyAlias) // if (recipientJWK == null) { // log.error { "Could not load verifying key for $keyAlias" } - // throw Exception("Could not load verifying key for $keyAlias") + // throw NoSuchElementException("Could not load verifying key for $keyAlias") // } open fun encrypt( diff --git a/src/main/kotlin/id/walt/services/jwt/WaltIdJwtService.kt b/src/main/kotlin/id/walt/services/jwt/WaltIdJwtService.kt index cdec53df..743a7af4 100644 --- a/src/main/kotlin/id/walt/services/jwt/WaltIdJwtService.kt +++ b/src/main/kotlin/id/walt/services/jwt/WaltIdJwtService.kt @@ -56,7 +56,7 @@ open class WaltIdJwtService : JwtService() { //val encKey = KeyManagementService.load(keyId) if (encKey == null) { log.error { "Could not load verifying key for $keyId" } - throw Exception("Could not load verifying key for $keyId") + throw IllegalArgumentException("Could not load verifying key for $keyId") } val decrypter = X25519Decrypter(encKey) decrypter.jcaContext.provider = provider @@ -99,7 +99,7 @@ open class WaltIdJwtService : JwtService() { val issuerKey = keyService.load(keyAlias) if (issuerKey == null) { log.error { "Could not load signing key for $keyAlias" } - throw Exception("Could not load signing key for $keyAlias") + throw IllegalArgumentException("Could not load signing key for $keyAlias") } log.debug { "Signing JWT with algorithm: ${issuerKey.algorithm}" } @@ -138,7 +138,7 @@ open class WaltIdJwtService : JwtService() { else -> { log.error { "Algorithm ${issuerKey.algorithm} not supported" } - throw Exception("Algorithm ${issuerKey.algorithm} not supported") + throw UnsupportedOperationException("Algorithm ${issuerKey.algorithm} not supported") } } @@ -156,7 +156,7 @@ open class WaltIdJwtService : JwtService() { if (DidService.isDidEbsiV2(keyAlias) && jwt.header.jwk != null) { DidService.importKeyForDidEbsiV2(DidUrl.from(keyAlias).did, jwt.header.jwk) } else if (!DidService.importKeys(DidUrl.from(keyAlias).did)) { - throw Exception("Could not resolve verification keys") + throw IllegalArgumentException("Could not resolve verification keys") } } @@ -178,7 +178,7 @@ open class WaltIdJwtService : JwtService() { else -> { log.error { "Algorithm ${verifierKey.algorithm} not supported" } - throw Exception("Algorithm ${verifierKey.algorithm} not supported") + throw UnsupportedOperationException("Algorithm ${verifierKey.algorithm} not supported") } } diff --git a/src/main/kotlin/id/walt/services/key/Keys.kt b/src/main/kotlin/id/walt/services/key/Keys.kt index 96983c8b..5521b4ca 100644 --- a/src/main/kotlin/id/walt/services/key/Keys.kt +++ b/src/main/kotlin/id/walt/services/key/Keys.kt @@ -134,10 +134,10 @@ data class Keys(val keyId: String, val pair: KeyPair, val provider: String) { return when (algorithm) { "ed" -> toOctetKeyPair().toJSONString() "sec" -> toEcKey().toJSONString() - else -> throw Exception("Export of algo: $algorithm not supported") + else -> throw UnsupportedOperationException("Export of algo: $algorithm not supported") } } - throw Exception("Export of for provider: $provider not supported") + throw UnsupportedOperationException("Export of for provider: $provider not supported") } } diff --git a/src/main/kotlin/id/walt/services/key/WaltIdKeyService.kt b/src/main/kotlin/id/walt/services/key/WaltIdKeyService.kt index d4e7ed9c..399b02b8 100644 --- a/src/main/kotlin/id/walt/services/key/WaltIdKeyService.kt +++ b/src/main/kotlin/id/walt/services/key/WaltIdKeyService.kt @@ -81,7 +81,7 @@ open class WaltIdKeyService : KeyService() { when (curve) { Curve.SECP256K1 -> JWSAlgorithm.ES256K Curve.P_256 -> JWSAlgorithm.ES256 - else -> throw Exception("Unsupported curve for Secp256Jwk: $curve") + else -> throw UnsupportedOperationException("Unsupported curve for Secp256Jwk: $curve") } ) .keyID(jwkKeyId ?: key.keyId.id) diff --git a/src/main/kotlin/id/walt/services/keystore/FileSystemKeyStoreService.kt b/src/main/kotlin/id/walt/services/keystore/FileSystemKeyStoreService.kt index 389be130..ccc350b8 100644 --- a/src/main/kotlin/id/walt/services/keystore/FileSystemKeyStoreService.kt +++ b/src/main/kotlin/id/walt/services/keystore/FileSystemKeyStoreService.kt @@ -150,7 +150,7 @@ open class FileSystemKeyStoreService : KeyStoreService() { //// return Key(KeyId(keyId), algorithm, provider, keyPair) //// } // } -// throw Exception("Could not load key: $keyId") +// throw NoSuchElementException("Could not load key: $keyId") // } diff --git a/src/main/kotlin/id/walt/services/keystore/HKVKeyStoreService.kt b/src/main/kotlin/id/walt/services/keystore/HKVKeyStoreService.kt index 95c3c574..59930b58 100644 --- a/src/main/kotlin/id/walt/services/keystore/HKVKeyStoreService.kt +++ b/src/main/kotlin/id/walt/services/keystore/HKVKeyStoreService.kt @@ -96,5 +96,5 @@ open class HKVKeyStoreService : KeyStoreService() { private fun loadKey(keyId: String, suffix: String): ByteArray = HKVKey.combine(KEYS_ROOT, keyId, suffix) - .let { hkvStore.getAsByteArray(it) ?: throw Exception("Could not load key '$it' from HKV store") } + .let { hkvStore.getAsByteArray(it) ?: throw NoSuchElementException("Could not load key '$it' from HKV store") } } diff --git a/src/main/kotlin/id/walt/services/keystore/TinkKeyStoreService.kt b/src/main/kotlin/id/walt/services/keystore/TinkKeyStoreService.kt index 05acd656..0e30d064 100644 --- a/src/main/kotlin/id/walt/services/keystore/TinkKeyStoreService.kt +++ b/src/main/kotlin/id/walt/services/keystore/TinkKeyStoreService.kt @@ -52,7 +52,7 @@ open class TinkKeyStoreService : KeyStoreService() { "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey" -> KeyAlgorithm.EdDSA_Ed25519 "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey" -> KeyAlgorithm.ECDSA_Secp256k1 "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey" -> KeyAlgorithm.ECDSA_Secp256r1 - else -> throw Exception("Could not determine KeyAlgorithm") + else -> throw IllegalArgumentException("Could not determine KeyAlgorithm") } return Key(KeyId(alias), algorithm, CryptoProvider.TINK, keysetHandle) diff --git a/src/main/kotlin/id/walt/services/oidc/OIDC4VPService.kt b/src/main/kotlin/id/walt/services/oidc/OIDC4VPService.kt index d77bd316..4c3952e5 100644 --- a/src/main/kotlin/id/walt/services/oidc/OIDC4VPService.kt +++ b/src/main/kotlin/id/walt/services/oidc/OIDC4VPService.kt @@ -66,7 +66,7 @@ object OIDC4VPService { presentation_definition_uri != null ).count { it } != 1 ) { - throw Exception("One and only one parameter of [single-scope, presentation_definition, presentation_definition_url] MUST be given.") + throw IllegalArgumentException("One and only one parameter of [single-scope, presentation_definition, presentation_definition_url] MUST be given.") } val customParams = mutableMapOf("nonce" to listOf(nonce.value)) if (!presentationByScope) { @@ -107,7 +107,7 @@ object OIDC4VPService { presentationDefinitionUri ).filter { it != null && !(it is String && it.isEmpty()) }.size != 1 ) { - throw Exception("One and only one parameter of [scope, presentation_definition, presentation_definition_url] MUST be given.") + throw IllegalArgumentException("One and only one parameter of [scope, presentation_definition, presentation_definition_url] MUST be given.") } if (!scope.isNullOrEmpty()) { TODO("How to find pre-definied presentation definition by scope") @@ -118,9 +118,9 @@ object OIDC4VPService { val response = HTTPRequest(HTTPRequest.Method.GET, URI.create(presentationDefinitionUri!!)).send() if (response.indicatesSuccess()) { return KlaxonWithConverters().parse(response.content) - ?: throw Exception("Error parsing presentation_definition_url response as PresentationDefinition object") + ?: throw IllegalArgumentException("Error parsing presentation_definition_url response as PresentationDefinition object") } - throw Exception("Error fetching presentation definition from presentation_definition_uri") + throw IllegalArgumentException("Error fetching presentation definition from presentation_definition_uri") } private fun authRequest2OIDC4VPRequest(authReq: AuthorizationRequest): AuthorizationRequest { diff --git a/src/main/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialService.kt b/src/main/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialService.kt index b10e8c0a..ac9196fc 100644 --- a/src/main/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialService.kt +++ b/src/main/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialService.kt @@ -172,11 +172,11 @@ open class WaltIdJsonLdCredentialService : JsonLdCredentialService() { override fun verify(vcOrVp: String): VerificationResult { val vcObj = vcOrVp.toVerifiableCredential() - val issuer = vcObj.issuerId ?: throw Exception("No issuer DID found for VC or VP") + val issuer = vcObj.issuerId ?: throw NoSuchElementException("No issuer DID found for VC or VP") val vm = vcObj.proof?.verificationMethod ?: issuer if (!DidService.importKeys(issuer)) { - throw Exception("Could not resolve verification keys") + throw IllegalArgumentException("Could not resolve verification keys") } log.debug { "Loading verification key for: $vm" } @@ -201,7 +201,7 @@ open class WaltIdJsonLdCredentialService : JsonLdCredentialService() { val ldProof = LdProof.getFromJsonLDObject(jsonLdObject) if (ldProof == null) { log.info { "No LD proof found on VC" } - throw Exception("No LD proof found on VC") + throw NoSuchElementException("No LD proof found on VC") } val ldSignatureType = LdSignatureType.valueOf(ldProof.type) @@ -284,19 +284,11 @@ open class WaltIdJsonLdCredentialService : JsonLdCredentialService() { return VerificationPolicyResult.success() val credentialSchemaUrl = it.credentialSchema?.id - - if (credentialSchemaUrl == null) { - log.debug { "Credential has no associated credentialSchema property" } - return VerificationPolicyResult.failure() - } + ?: return VerificationPolicyResult.failure(IllegalArgumentException("Credential has no associated credentialSchema property")) return validateSchema(it, URI.create(credentialSchemaUrl)) } } catch (e: Exception) { - if (log.isDebugEnabled) { - log.debug { "Could not validate schema" } - e.printStackTrace() - } - VerificationPolicyResult.failure() + VerificationPolicyResult.failure(e) } } diff --git a/src/main/kotlin/id/walt/services/vc/WaltIdJwtCredentialService.kt b/src/main/kotlin/id/walt/services/vc/WaltIdJwtCredentialService.kt index deef060a..7234c0e9 100644 --- a/src/main/kotlin/id/walt/services/vc/WaltIdJwtCredentialService.kt +++ b/src/main/kotlin/id/walt/services/vc/WaltIdJwtCredentialService.kt @@ -131,7 +131,6 @@ open class WaltIdJwtCredentialService : JwtCredentialService() { return validateSchema(it, URI.create(credentialSchema.id)) } } catch (e: Exception) { - e.printStackTrace() - VerificationPolicyResult.failure() + VerificationPolicyResult.failure(e) } } diff --git a/src/main/kotlin/id/walt/signatory/WaltIdSignatory.kt b/src/main/kotlin/id/walt/signatory/WaltIdSignatory.kt index fd1c298e..ee5fc966 100644 --- a/src/main/kotlin/id/walt/signatory/WaltIdSignatory.kt +++ b/src/main/kotlin/id/walt/signatory/WaltIdSignatory.kt @@ -19,6 +19,7 @@ import java.nio.file.Files import java.nio.file.Path import java.time.Instant import java.util.* +import kotlin.NoSuchElementException private val log = KotlinLogging.logger {} @@ -80,7 +81,7 @@ class WaltIdSignatory(configurationPath: String) : Signatory() { true -> Files.readString(Path.of(templateIdOrFilename)).toVerifiableCredential() else -> VcTemplateManager.getTemplate(templateIdOrFilename, true, configuration.templatesFolder).template }?.let { W3CCredentialBuilder.fromPartial(it) } - ?: throw Exception("Template could not be loaded: $templateIdOrFilename") + ?: throw NoSuchElementException("Template could not be loaded: $templateIdOrFilename") return issue(dataProvider?.populate(credentialBuilder, config) ?: credentialBuilder, config, issuer, storeCredential) } @@ -139,7 +140,7 @@ class WaltIdSignatory(configurationPath: String) : Signatory() { if (template.mutable) { VcTemplateManager.unregisterTemplate(templateId) } else { - throw Exception("Template is immutable and cannot be removed. Use import to override existing templates.") + throw IllegalArgumentException("Template is immutable and cannot be removed. Use import to override existing templates.") } } diff --git a/src/test/kotlin/id/walt/auditor/AuditorTest.kt b/src/test/kotlin/id/walt/auditor/AuditorTest.kt index 0d5c6a8e..663af288 100644 --- a/src/test/kotlin/id/walt/auditor/AuditorTest.kt +++ b/src/test/kotlin/id/walt/auditor/AuditorTest.kt @@ -76,48 +76,48 @@ class AuditorCommandTest : StringSpec() { val policyList = listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy()) val res = Auditor.getService().verify(vpStr, policyList) - res.outcome shouldBe true + res.result shouldBe true res.policyResults.keys shouldBeSameSizeAs policyList res.policyResults.keys shouldContainAll policyList.map { it.id } - res.policyResults.values.forEach { it.outcome shouldBe true } + res.policyResults.values.forEach { it.result shouldBe true } } "2. verify vc" { val res = Auditor.getService().verify(vcStr, listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy())) - res.outcome shouldBe true + res.result shouldBe true res.policyResults.keys shouldBeSameSizeAs listOf( SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy() ) res.policyResults.keys shouldContainAll listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy()).map { it.id } - res.policyResults.values.forEach { it.outcome shouldBe true } + res.policyResults.values.forEach { it.result shouldBe true } } "3. verify vc jwt" { val res = Auditor.getService().verify(vcJwt, listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy())) - res.outcome shouldBe true + res.result shouldBe true res.policyResults.keys shouldBeSameSizeAs listOf( SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy() ) res.policyResults.keys shouldContainAll listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy()).map { it.id } - res.policyResults.values.forEach { it.outcome shouldBe true } + res.policyResults.values.forEach { it.result shouldBe true } } "4. verify vp jwt" { val res = Auditor.getService().verify(vpJwt, listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy())) - res.outcome shouldBe true + res.result shouldBe true res.policyResults.keys shouldBeSameSizeAs listOf( SignaturePolicy(), TrustedSchemaRegistryPolicy(), JsonSchemaPolicy() @@ -125,7 +125,7 @@ class AuditorCommandTest : StringSpec() { res.policyResults.keys shouldContainAll listOf(SignaturePolicy(), TrustedSchemaRegistryPolicy()).map { it.id } - res.policyResults.values.forEach { it.outcome shouldBe true } + res.policyResults.values.forEach { it.result shouldBe true } } // CLI call for testing VerifiableMandatePolicy @@ -157,7 +157,7 @@ class AuditorCommandTest : StringSpec() { println("Testing query: $query") val verificationResult = Auditor.getService() .verify(mandate, listOf(PolicyRegistry.getPolicy("VerifiableMandatePolicy", JsonObject(query)))) - verificationResult.outcome shouldBe true + verificationResult.result shouldBe true } // CLI call for testing RegoPolicy @@ -177,7 +177,7 @@ class AuditorCommandTest : StringSpec() { ) ) ) - verificationResult.outcome shouldBe true + verificationResult.result shouldBe true // Successful testcase with Rego Policy Arg str val verificationResultStr = Auditor.getService().verify( @@ -188,7 +188,7 @@ class AuditorCommandTest : StringSpec() { "{\"dataPath\" : \"\$.credentialSubject\", \"input\" : {\"user\": \"$did\" }, \"policy\" : \"src/test/resources/rego/subject-policy.rego\"}" ) ) - ).outcome + ).result verificationResultStr shouldBe true // Unsuccessful testcase @@ -204,26 +204,26 @@ class AuditorCommandTest : StringSpec() { ) ) ) - negResult.outcome shouldBe false + negResult.result shouldBe false } "7. test JsonSchemaPolicy" { // test schema from credentialSchema.id property of credential - Auditor.getService().verify(vcStr, listOf(JsonSchemaPolicy())).outcome shouldBe true + Auditor.getService().verify(vcStr, listOf(JsonSchemaPolicy())).result shouldBe true // test VerifiableDiploma schema from vclib Auditor.getService().verify( vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg("https://raw.githubusercontent.com/walt-id/waltid-ssikit-vclib/master/src/test/resources/schemas/VerifiableDiploma.json"))) ) - .outcome shouldBe true + .result shouldBe true // test VerifiableId schema from vclib (should not validate) Auditor.getService().verify( vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg("https://raw.githubusercontent.com/walt-id/waltid-ssikit-vclib/master/src/test/resources/schemas/VerifiableId.json"))) ) - .outcome shouldBe false + .result shouldBe false // this is a VerifiableDiploma (EUROPASS) schema, which our VerifiableDiploma template does NOT comply with: // https://ec.europa.eu/digital-building-blocks/wikis/display/EBSIDOC/Data+Models+and+Schemas @@ -233,21 +233,21 @@ class AuditorCommandTest : StringSpec() { Auditor.getService().verify( vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(verifiableDiplomaUrl.toExternalForm()))) - ).outcome shouldBe false + ).result shouldBe false } // test passing schema by value val schemaContent = URI.create("https://raw.githubusercontent.com/walt-id/waltid-ssikit-vclib/master/src/test/resources/schemas/VerifiableDiploma.json") .toURL().readText() - Auditor.getService().verify(vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(schemaContent)))).outcome shouldBe true + Auditor.getService().verify(vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(schemaContent)))).result shouldBe true // test passing schema by file path val tempFile = File.createTempFile("schema", ".json") tempFile.writeText(schemaContent) shouldNotThrowAny { Auditor.getService() - .verify(vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(tempFile.absolutePath)))).outcome shouldBe true + .verify(vcStr, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(tempFile.absolutePath)))).result shouldBe true } tempFile.delete() } @@ -257,10 +257,10 @@ class AuditorCommandTest : StringSpec() { VerifiableCredential.fromString(File("$credentialFile").readText()) if (schemaFile.isNullOrBlank()) { - Auditor.getService().verify(credential, listOf(JsonSchemaPolicy())).outcome shouldBe true + Auditor.getService().verify(credential, listOf(JsonSchemaPolicy())).result shouldBe true } else { Auditor.getService() - .verify(credential, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(schemaFile)))).outcome shouldBe true + .verify(credential, listOf(JsonSchemaPolicy(JsonSchemaPolicyArg(schemaFile)))).result shouldBe true } } diff --git a/src/test/kotlin/id/walt/cli/EssifCommandTest.kt b/src/test/kotlin/id/walt/cli/EssifCommandTest.kt index d84876bf..1a0acc9f 100644 --- a/src/test/kotlin/id/walt/cli/EssifCommandTest.kt +++ b/src/test/kotlin/id/walt/cli/EssifCommandTest.kt @@ -75,7 +75,7 @@ class EssifCommandTest : StringSpec({ * The token can be retrieved from https://app-pilot.ebsi.eu/users-onboarding/v2/ */ "2. onboard --did".config(enabled = enableTests) { - if (!bearerToken.exists()) throw Exception("Bearer Token from https://app-pilot.ebsi.eu/users-onboarding/v2/ should be placed in file data/ebsi/bearer-token.txt") + if (!bearerToken.exists()) throw NoSuchElementException("Bearer Token from https://app-pilot.ebsi.eu/users-onboarding/v2/ should be placed in file data/ebsi/bearer-token.txt") println("Generating verifiable authorization...") EssifOnboardingCommand().parse(listOf("--did", did, File("data/ebsi/bearer-token.txt").absolutePath)) diff --git a/src/test/kotlin/id/walt/context/WaltContextTest.kt b/src/test/kotlin/id/walt/context/WaltContextTest.kt index a04c84c7..4c7a8b36 100644 --- a/src/test/kotlin/id/walt/context/WaltContextTest.kt +++ b/src/test/kotlin/id/walt/context/WaltContextTest.kt @@ -67,7 +67,7 @@ class WaltContextTest : AnnotationSpec() { ContextManager.runWith(userBContext) { // verify credential in user B context, importing key from did on the fly val result = Auditor.getService().verify(cred, listOf(SignaturePolicy())) - result.outcome shouldBe true + result.result shouldBe true } } } diff --git a/src/test/kotlin/id/walt/essif/EssifIntTest.kt b/src/test/kotlin/id/walt/essif/EssifIntTest.kt index f2c9ad75..7c96323c 100644 --- a/src/test/kotlin/id/walt/essif/EssifIntTest.kt +++ b/src/test/kotlin/id/walt/essif/EssifIntTest.kt @@ -53,7 +53,7 @@ class EssifIntTest : StringSpec({ println("Checking for bearer token...") if (!Path(bearerTokenFile).exists()) { if (!Path("bearer-token.txt").exists()) { - throw Exception("Place token from https://app-pilot.ebsi.eu/users-onboarding in file bearer-token.txt") + throw NoSuchElementException("Place token from https://app-pilot.ebsi.eu/users-onboarding in file bearer-token.txt") } Path("bearer-token.txt").copyTo(Path(bearerTokenFile)) } @@ -225,7 +225,7 @@ class EssifIntTest : StringSpec({ private fun resetDataDir() { SqlDbManager.stop() - if (!File("data").deleteRecursively()) throw Exception("Could not delete data-dir!") + if (!File("data").deleteRecursively()) throw IllegalStateException("Could not delete data-dir!") File("data").mkdir() SqlDbManager.start() } @@ -236,8 +236,8 @@ private fun verifyCredential(src: File) { println("Verifying from file \"$src\"...\n") when { - !src.exists() -> throw Exception("Could not load file: \"$src\".") - policies.any { !PolicyRegistry.contains(it) } -> throw Exception( + !src.exists() -> throw NoSuchElementException("Could not load file: \"$src\".") + policies.any { !PolicyRegistry.contains(it) } -> throw NoSuchElementException( "Unknown verification policy specified: ${policies.minus(PolicyRegistry.listPolicies()).joinToString()}" ) } @@ -248,9 +248,9 @@ private fun verifyCredential(src: File) { println("$policy:\t\t $result") result shouldBe true } - println("Verified:\t\t ${verificationResult.outcome}") + println("Verified:\t\t ${verificationResult.result}") - verificationResult.outcome shouldBe true + verificationResult.result shouldBe true } private fun privateKeyExists(keyAlias: String) = diff --git a/src/test/kotlin/id/walt/rest/CustodianApiTest.kt b/src/test/kotlin/id/walt/rest/CustodianApiTest.kt index e4fddef7..84a6b444 100644 --- a/src/test/kotlin/id/walt/rest/CustodianApiTest.kt +++ b/src/test/kotlin/id/walt/rest/CustodianApiTest.kt @@ -81,7 +81,7 @@ class CustodianApiTest : StringSpec({ println("VP Response: $response") - Auditor.getService().verify(response, listOf(SignaturePolicy())).outcome shouldBe true + Auditor.getService().verify(response, listOf(SignaturePolicy())).result shouldBe true } "Check Custodian Presentation generation JWT" { @@ -110,7 +110,7 @@ class CustodianApiTest : StringSpec({ println("VP Response: $response") - Auditor.getService().verify(response, listOf(SignaturePolicy())).outcome shouldBe true + Auditor.getService().verify(response, listOf(SignaturePolicy())).result shouldBe true } "Test export key" { diff --git a/src/test/kotlin/id/walt/services/oidc/OIDCTestProvider.kt b/src/test/kotlin/id/walt/services/oidc/OIDCTestProvider.kt index 3d98e6f5..7de06754 100644 --- a/src/test/kotlin/id/walt/services/oidc/OIDCTestProvider.kt +++ b/src/test/kotlin/id/walt/services/oidc/OIDCTestProvider.kt @@ -139,7 +139,7 @@ object OIDCTestProvider { siopResponse shouldNotBe null siopResponse.vp_token shouldNot beEmpty() siopResponse.vp_token.forEach { vp -> - Auditor.getService().verify(vp.encode(), listOf(SignaturePolicy())).outcome shouldBe true + Auditor.getService().verify(vp.encode(), listOf(SignaturePolicy())).result shouldBe true } ctx.result(siopResponse.toFormBody()) } diff --git a/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt b/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt index 6f3b97ae..8a3ab233 100644 --- a/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt +++ b/src/test/kotlin/id/walt/services/vc/WaltIdJsonLdCredentialServiceTest.kt @@ -234,10 +234,10 @@ class WaltIdJsonLdCredentialServiceTest : AnnotationSpec() { ) val notParsableVc = "" - credentialService.validateSchemaTsr(noSchemaVc).outcome shouldBe false - credentialService.validateSchemaTsr(validVc).outcome shouldBe true - credentialService.validateSchemaTsr(invalidDataVc).outcome shouldBe false - credentialService.validateSchemaTsr(notParsableVc).outcome shouldBe false + credentialService.validateSchemaTsr(noSchemaVc).result shouldBe false + credentialService.validateSchemaTsr(validVc).result shouldBe true + credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false + credentialService.validateSchemaTsr(notParsableVc).result shouldBe false } /*@Test diff --git a/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt b/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt index eabc4e4a..e480f6f4 100644 --- a/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt +++ b/src/test/kotlin/id/walt/services/vc/WaltIdJwtCredentialServiceTest.kt @@ -141,10 +141,10 @@ class WaltIdJwtCredentialServiceTest : AnnotationSpec() { ) val notParsableVc = "" - credentialService.validateSchemaTsr(noSchemaVc).outcome shouldBe true - credentialService.validateSchemaTsr(validVc).outcome shouldBe true - credentialService.validateSchemaTsr(invalidDataVc).outcome shouldBe false - credentialService.validateSchemaTsr(notParsableVc).outcome shouldBe false + credentialService.validateSchemaTsr(noSchemaVc).result shouldBe true + credentialService.validateSchemaTsr(validVc).result shouldBe true + credentialService.validateSchemaTsr(invalidDataVc).result shouldBe false + credentialService.validateSchemaTsr(notParsableVc).result shouldBe false } @Test @@ -169,7 +169,7 @@ class WaltIdJwtCredentialServiceTest : AnnotationSpec() { KeyService.getService().hasKey(didV2) shouldBe false // verify presentation JWT val verificationResult = Auditor.getService().verify(presentation, listOf(SignaturePolicy())) - verificationResult.outcome shouldBe true + verificationResult.result shouldBe true // verify key has been resolved KeyService.getService().hasKey(didV2) shouldBe true } diff --git a/src/test/kotlin/id/walt/signatory/SignatoryServiceTest.kt b/src/test/kotlin/id/walt/signatory/SignatoryServiceTest.kt index bcd88b1a..ebff0a06 100644 --- a/src/test/kotlin/id/walt/signatory/SignatoryServiceTest.kt +++ b/src/test/kotlin/id/walt/signatory/SignatoryServiceTest.kt @@ -182,7 +182,7 @@ class SignatoryServiceTest : StringSpec({ parsedVC.credentialSubject?.properties?.get("familyName") shouldBe "GNITO" signedVC shouldMatchJson parsedVC.toJson() - Auditor.getService().verify(parsedVC, listOf(SignaturePolicy())).outcome shouldBe true + Auditor.getService().verify(parsedVC, listOf(SignaturePolicy())).result shouldBe true } "sign any credential with user data from subject builder" { @@ -206,7 +206,7 @@ class SignatoryServiceTest : StringSpec({ parsedVC.issuer?.properties?.get("name") shouldBe "Test Issuer" signedVC shouldMatchJson parsedVC.toJson() - Auditor.getService().verify(parsedVC, listOf(SignaturePolicy())).outcome shouldBe true + Auditor.getService().verify(parsedVC, listOf(SignaturePolicy())).result shouldBe true } /*"sign verifiable id credential with typed builder" {