diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet-config/configure-document-key-creation.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet-config/configure-document-key-creation.md index eed9cc8e..d2625c7e 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet-config/configure-document-key-creation.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet-config/configure-document-key-creation.md @@ -17,6 +17,13 @@ values are used to create the eu.europa.ec.eudi.wallet.document.CreateDocumentSe using [eu.europa.ec.eudi.wallet.document.DocumentExtensions.getDefaultCreateDocumentSettings](../../eu.europa.ec.eudi.wallet.document/-document-extensions/get-default-create-document-settings.md) method. +If user authentication is required, the user authentication timeout must be greater than 0. + +**Note**: when setting userAuthenticationRequired to true, device must be secured with a PIN, +pattern or password. + +**Note**: when setting useStrongBoxForKeys to true, the device must support the StrongBox. + The default values are: - @@ -24,7 +31,7 @@ userAuthenticationRequired: false - userAuthenticationTimeout: 0 - -useStrongBoxForKeys: true +useStrongBoxForKeys: true if supported by the device #### Parameters diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/-builder/build.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/-builder/build.md index 3626ef5d..5e2a9e63 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/-builder/build.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/-builder/build.md @@ -7,12 +7,42 @@ fun [build](build.md)(): [EudiWallet](../index.md) Build the [EudiWallet](../index.md) instance -#### Return +The [EudiWallet](../index.md) instance will be created based on the configuration provided in +the [Builder](index.md) class. -[EudiWallet](../index.md) +The [EudiWallet](../index.md) instance will be created with the following default implementations if +not set: + +- +AndroidStorageEngine for storing/retrieving documents +- +AndroidKeystoreSecureArea for managing documents' keys +- +DocumentManagerImpl for managing documents +- +[PresentationManagerImpl](../../../eu.europa.ec.eudi.wallet.presentation/-presentation-manager-impl/index.md) +for both proximity and remote presentation +- +[OpenId4VpManager](../../../eu.europa.ec.eudi.wallet.transfer.openId4vp/-open-id4-vp-manager/index.md) +for remote presentation +- +TransferManagerImpl for proximity presentation + +**Note**: +The [EudiWalletConfig.documentsStorageDir](../../-eudi-wallet-config/documents-storage-dir.md) is +not set, the default storage directory will be used which is the application's no backup files +directory. -#### Throws +**Note**: +The [EudiWalletConfig.userAuthenticationRequired](../../-eudi-wallet-config/user-authentication-required.md) +is set to true and the device is not secured with a PIN, pattern, or password, the configuration +will be updated to set the user authentication required to false. -| | | -|------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [IllegalStateException](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-state-exception/index.html) | if [EudiWalletConfig.documentsStorageDir](../../-eudi-wallet-config/documents-storage-dir.md) is not set and and the default DocumentManager is going to be used | +**Note**: +The [EudiWalletConfig.useStrongBoxForKeys](../../-eudi-wallet-config/use-strong-box-for-keys.md) is +set to true and the device does not support StrongBox, the configuration will be updated to set the +use StrongBox for keys to false. + +#### Return + +[EudiWallet](../index.md) diff --git a/gradle.properties b/gradle.properties index b1b8cfad..21adb88e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,7 +42,7 @@ systemProp.sonar.host.url=https://sonarcloud.io systemProp.sonar.gradle.skipCompile=true systemProp.sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/testDebugUnitTestCoverage/testDebugUnitTestCoverage.xml,build/reports/jacoco/testReleaseUnitTestCoverage/testReleaseUnitTestCoverage.xml systemProp.sonar.projectName=eudi-lib-android-wallet-core -VERSION_NAME=0.12.0 +VERSION_NAME=0.12.1-SNAPSHOT SONATYPE_HOST=S01 SONATYPE_AUTOMATIC_RELEASE=false diff --git a/licenses.md b/licenses.md index 3221a7a3..a219c495 100644 --- a/licenses.md +++ b/licenses.md @@ -2,7 +2,7 @@ # EUDI Wallet Core library for Android ## Dependency License Report -_2024-11-20 17:38:59 EET_ +_2024-11-22 13:51:07 EET_ ## Apache License, Version 2.0 **1** **Group:** `androidx.appcompat` **Name:** `appcompat` **Version:** `1.6.1` diff --git a/wallet-core/build.gradle.kts b/wallet-core/build.gradle.kts index 313a1525..963182c7 100644 --- a/wallet-core/build.gradle.kts +++ b/wallet-core/build.gradle.kts @@ -106,50 +106,40 @@ android { dependencies { - implementation(libs.appcompat) - // EUDI libs api(libs.eudi.document.manager) api(libs.eudi.iso18013.data.transfer) + // Identity android library + api(libs.google.identity.android) { + exclude(group = "org.bouncycastle") + } + implementation(libs.appcompat) // OpenID4VCI implementation(libs.eudi.lib.jvm.openid4vci.kt) implementation(libs.nimbus.oauth2.oidc.sdk) - // Siop-Openid4VP library implementation(libs.eudi.lib.jvm.siop.openid4vp.kt) { exclude(group = "org.bouncycastle") } - - // Identity android library - api(libs.google.identity.android) { - exclude(group = "org.bouncycastle") - } - implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.io.core) implementation(libs.kotlinx.io.bytestring) - // CBOR implementation(libs.cbor) - - testImplementation(libs.testng) - + implementation(libs.upokecenter.cbor) + implementation(libs.cose.java) // Ktor Android Engine - runtimeOnly(libs.ktor.client.android) implementation(libs.ktor.client.logging) - // Bouncy Castle implementation(libs.bouncy.castle.prov) implementation(libs.bouncy.castle.pkix) - implementation(libs.upokecenter.cbor) - implementation(libs.cose.java) + runtimeOnly(libs.ktor.client.android) testImplementation(kotlin("test")) testImplementation(libs.mockk) testImplementation(libs.json) - testImplementation(libs.junit.jupiter.params) testImplementation(libs.kotlin.coroutines.test) testImplementation(libs.biometric.ktx) diff --git a/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/EudiWalletTest.kt b/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/EudiWalletTest.kt index 4609e7f0..8630b190 100644 --- a/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/EudiWalletTest.kt +++ b/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/EudiWalletTest.kt @@ -54,8 +54,9 @@ class EudiWalletTest { fun testLoadSampleDocuments() { walletConfig = EudiWalletConfig() .configureDocumentKeyCreation( - userAuthenticationRequired = false, - useStrongBoxForKeys = false, + userAuthenticationRequired = true, + userAuthenticationTimeout = 30_000L, + useStrongBoxForKeys = true, ) val result = wallet.loadMdocSampleDocuments( diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt index 53842ff6..ae0129f0 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt @@ -24,11 +24,13 @@ import com.android.identity.securearea.SecureArea import com.android.identity.securearea.SecureAreaRepository import com.android.identity.storage.StorageEngine import eu.europa.ec.eudi.iso18013.transfer.TransferManager +import eu.europa.ec.eudi.iso18013.transfer.TransferManagerImpl import eu.europa.ec.eudi.iso18013.transfer.engagement.BleRetrievalMethod import eu.europa.ec.eudi.iso18013.transfer.readerauth.ReaderTrustStore import eu.europa.ec.eudi.wallet.document.* import eu.europa.ec.eudi.wallet.document.sample.SampleDocumentManager import eu.europa.ec.eudi.wallet.internal.LogPrinterImpl +import eu.europa.ec.eudi.wallet.internal.i import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager import eu.europa.ec.eudi.wallet.logging.Logger import eu.europa.ec.eudi.wallet.presentation.PresentationManager @@ -108,6 +110,8 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { companion object { + private const val TAG = "EudiWallet" + /** * Create an instance of [EudiWallet] with the given configuration and additional configuration * using the [Builder] class @@ -235,16 +239,31 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { /** * Build the [EudiWallet] instance * - * @throws IllegalStateException if [setConfig] is not set - * @throws IllegalStateException if [EudiWalletConfig.documentsStorageDir] is not set and - * and the default [DocumentManager] is going to be used + * The [EudiWallet] instance will be created based on the configuration provided in the [Builder] class. + * + * The [EudiWallet] instance will be created with the following default implementations if not set: + * - [AndroidStorageEngine] for storing/retrieving documents + * - [AndroidKeystoreSecureArea] for managing documents' keys + * - [DocumentManagerImpl] for managing documents + * - [PresentationManagerImpl] for both proximity and remote presentation + * - [OpenId4VpManager] for remote presentation + * - [TransferManagerImpl] for proximity presentation + * + * **Note**: The [EudiWalletConfig.documentsStorageDir] is not set, the default storage directory + * will be used which is the application's no backup files directory. + * + * **Note**: The [EudiWalletConfig.userAuthenticationRequired] is set to true and the device is not secured with a PIN, + * pattern, or password, the configuration will be updated to set the user authentication required to false. + * + * **Note**: The [EudiWalletConfig.useStrongBoxForKeys] is set to true and the device does not support StrongBox, + * the configuration will be updated to set the use StrongBox for keys to false. + * * @return [EudiWallet] */ fun build(): EudiWallet { - val loggerToUse = (logger ?: Logger(config)).also { - IdentityLogger.setLogPrinter(LogPrinterImpl(it)) - } + ensureStrongBoxIsSupported() + ensureUserAuthIsSupported() val documentManagerToUse = documentManager ?: getDefaultDocumentManager(storageEngine, secureAreas) @@ -253,31 +272,18 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { val transferManager = getTransferManager(documentManagerToUse, readerTrustStoreToUse) - val presentationManagerToUse = presentationManager ?: run { - val openId4vpManager = config.openId4VpConfig?.let { openId4VpConfig -> - OpenId4VpManager( - config = openId4VpConfig, - requestProcessor = OpenId4VpRequestProcessor( - documentManagerToUse, - readerTrustStoreToUse - ), - logger = loggerToUse, - ktorHttpClientFactory = ktorHttpClientFactory - ) - } - PresentationManagerImpl( - transferManager = transferManager, - openId4vpManager = openId4vpManager, - nfcEngagementServiceClass = config.nfcEngagementServiceClass, - ) - } + val presentationManagerToUse = presentationManager ?: getDefaultPresentationManager( + documentManager = documentManagerToUse, + transferManager = transferManager, + readerTrustStore = readerTrustStoreToUse + ) val openId4vpManagerFactory = { config.openId4VciConfig?.let { openId4VciConfig -> OpenId4VciManager(context) { documentManager(documentManagerToUse) config(openId4VciConfig) - logger(loggerToUse) + logger(loggerObj) ktorHttpClientFactory?.let { ktorHttpClientFactory(it) } } } ?: throw IllegalStateException("OpenId4Vp configuration is missing") @@ -289,12 +295,47 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { documentManager = documentManagerToUse, presentationManager = presentationManagerToUse, transferManager = transferManager, - logger = loggerToUse, + logger = loggerObj, readerTrustStoreConsumer = { presentationManagerToUse.readerTrustStore = it }, openId4VciManagerFactory = openId4vpManagerFactory, ) } + /** + * Get the default [PresentationManagerImpl] instance based on the [DocumentManager] and [TransferManager] implementations + * @param documentManager the document manager + * @param transferManager the transfer manager + * @param readerTrustStore the reader trust store + * @return the default [PresentationManagerImpl] instance + */ + @JvmSynthetic + internal fun getDefaultPresentationManager( + documentManager: DocumentManager, + transferManager: TransferManager, + readerTrustStore: ReaderTrustStore?, + ): PresentationManagerImpl { + val openId4vpManager = config.openId4VpConfig?.let { openId4VpConfig -> + OpenId4VpManager( + config = openId4VpConfig, + requestProcessor = OpenId4VpRequestProcessor(documentManager, readerTrustStore), + logger = loggerObj, + ktorHttpClientFactory = ktorHttpClientFactory + ) + } + return PresentationManagerImpl( + transferManager = transferManager, + openId4vpManager = openId4vpManager, + nfcEngagementServiceClass = config.nfcEngagementServiceClass, + ) + } + + @get:JvmSynthetic + internal val loggerObj: Logger by lazy { + (logger ?: Logger(config)).also { + IdentityLogger.setLogPrinter(LogPrinterImpl(it)) + } + } + @get:JvmSynthetic internal val defaultStorageDir: Path get() = Path( @@ -336,9 +377,9 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { return AndroidStorageEngine.Builder( context = context, storageFile = documentsStorageDirToUse - ).apply { - setUseEncryption(config.encryptDocumentsInStorage) - }.build() + ) + .setUseEncryption(config.encryptDocumentsInStorage) + .build() } /** @@ -400,5 +441,44 @@ interface EudiWallet : SampleDocumentManager, PresentationManager { ) ) ) + + /** + * Returns the capabilities of the Android Keystore Secure Area + */ + @get:JvmSynthetic + internal val capabilities: AndroidKeystoreSecureArea.Capabilities by lazy { + AndroidKeystoreSecureArea.Capabilities(context) + } + + /** + * Check if user authentication is required and update the configuration + * if the device is not secure and the configuration is set to require user authentication + */ + @JvmSynthetic + internal fun ensureUserAuthIsSupported() { + if (capabilities.secureLockScreenSetup.not() && config.userAuthenticationRequired) { + loggerObj.i( + TAG, + """User authentication is required but the device is not secured with a PIN, pattern, or password. + | Setting EudiWalletConfig.userAuthenticationRequired to false.""".trimMargin() + ) + config.userAuthenticationRequired = false + } + } + + /** + * Check if StrongBox is supported on the device and update the configuration + * if it is not supported and the configuration is set to use StrongBox + */ + @JvmSynthetic + internal fun ensureStrongBoxIsSupported() { + if (capabilities.strongBoxSupported.not() && config.useStrongBoxForKeys) { + loggerObj.i( + TAG, """StrongBox is not supported on this device. + | Setting EudiWalletConfig.useStrongBoxForKeys to false.""".trimMargin() + ) + config.useStrongBoxForKeys = false + } + } } } \ No newline at end of file diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt index abe5ec21..ea7c03a5 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt @@ -299,11 +299,11 @@ class EudiWalletConfig { } var userAuthenticationRequired: Boolean = false - private set + internal set // internal for setting the default value from the builder var userAuthenticationTimeout: Long = 0L private set var useStrongBoxForKeys: Boolean = true - private set + internal set // internal for setting the default value from the builder /** * Configure the document key creation. This allows to configure if user authentication is @@ -313,10 +313,17 @@ class EudiWalletConfig { * using [eu.europa.ec.eudi.wallet.document.DocumentExtensions.getDefaultCreateDocumentSettings] * method. * + * If user authentication is required, the user authentication timeout must be greater than 0. + * + * **Note**: when setting userAuthenticationRequired to true, device must be secured with a PIN, pattern + * or password. + * + * **Note**: when setting useStrongBoxForKeys to true, the device must support the StrongBox. + * * The default values are: * - userAuthenticationRequired: false * - userAuthenticationTimeout: 0 - * - useStrongBoxForKeys: true + * - useStrongBoxForKeys: true if supported by the device * * @param userAuthenticationRequired whether user authentication is required * @param userAuthenticationTimeout the user authentication timeout. If user authentication diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/internal/Extensions.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/internal/Extensions.kt index 37164c8b..f98ff731 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/internal/Extensions.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/internal/Extensions.kt @@ -1,31 +1,25 @@ /* - * Copyright (c) 2023-2024 European Commission + * Copyright (c) 2023-2024 European Commission * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package eu.europa.ec.eudi.wallet.internal -import COSE.OneKey import android.content.Context -import android.content.pm.PackageManager.GET_META_DATA import android.os.Build import androidx.annotation.RawRes import androidx.core.content.ContextCompat -import kotlinx.coroutines.runBlocking -import org.bouncycastle.util.encoders.Hex -import java.net.URI -import java.security.PublicKey import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.util.concurrent.Executor @@ -45,40 +39,4 @@ internal fun Context.mainExecutor(): Executor { } else { ContextCompat.getMainExecutor(applicationContext) } -} - -@JvmSynthetic -internal fun Context.executeOnMain(block: suspend () -> Unit) { - mainExecutor().execute { - runBlocking { block() } - } -} - -@get:JvmSynthetic -@get:Suppress("DEPRECATION") -/** - * Keep deprecation for Xiaomi compatibility - */ -internal val Context.openId4VciAuthorizationRedirectUri: URI - get() = with( - packageManager.getApplicationInfo(packageName, GET_META_DATA).metaData - ) { - URI.create( - getString("openid4vciAuthorizeScheme", "https") + "://" - + getString("openid4vciAuthorizeHost", "localhost") - + getString("openid4vciAuthorizePath", "/authorize") - ) - - } - -@get:JvmSynthetic -internal val PublicKey.cose: OneKey - get() = OneKey(this, null) - -@get:JvmSynthetic -internal val PublicKey.coseBytes: String - get() = Hex.toHexString(cose.EncodeToBytes()) - -@get:JvmSynthetic -internal val PublicKey.coseDebug: String - get() = cose.AsCBOR().ToJSONString() \ No newline at end of file +} \ No newline at end of file diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/EudiWalletBuilderDeviceCapabilitiesTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/EudiWalletBuilderDeviceCapabilitiesTest.kt new file mode 100644 index 00000000..8f1262a3 --- /dev/null +++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/EudiWalletBuilderDeviceCapabilitiesTest.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 European Commission + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.europa.ec.eudi.wallet + +import android.content.Context +import eu.europa.ec.eudi.wallet.logging.Logger +import io.mockk.every +import io.mockk.mockk +import io.mockk.spyk +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import kotlin.test.Test +import kotlin.test.assertEquals + +@RunWith(value = Parameterized::class) +class EudiWalletBuilderDeviceCapabilitiesTest( + private val configUserAuthenticationRequired: Boolean, + private val configUseStrongBoxForKeys: Boolean, + private val deviceSecureLockScreenSetup: Boolean, + private val deviceStrongBoxSupported: Boolean, + private val expectedUserAuthenticationRequired: Boolean, + private val expectedUseStrongBoxForKeys: Boolean, +) { + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "{index}: config(ua={0},sb={1}), device(ua={2},sb={3}), expected(ua={4},sb={5})") + fun data() = arrayListOf( + arrayOf(true, true, false, false, false, false), + arrayOf(true, true, true, false, true, false), + arrayOf(true, true, false, true, false, true), + arrayOf(true, true, true, true, true, true), + arrayOf(false, false, false, false, false, false), + arrayOf(false, false, true, false, false, false), + arrayOf(false, false, false, true, false, false), + arrayOf(false, false, true, true, false, false), + ) + } + + @Test + fun `EudiWalletConfig userAuthenticationRequired and useStrongBoxForKeys should be reverted to false if not supported by device`() { + val config = EudiWalletConfig() + .configureDocumentKeyCreation( + userAuthenticationRequired = configUserAuthenticationRequired, + userAuthenticationTimeout = 30_000L, + useStrongBoxForKeys = configUseStrongBoxForKeys + ) + + val context: Context = mockk { + every { applicationContext } returns this + } + + val builder = spyk( + EudiWallet.Builder(context, config) + .withLogger(Logger { record -> + println(record.message) + }) + ) { + every { capabilities } returns mockk { + every { secureLockScreenSetup } returns deviceSecureLockScreenSetup + every { strongBoxSupported } returns deviceStrongBoxSupported + } + } + + builder.ensureUserAuthIsSupported() + builder.ensureStrongBoxIsSupported() + + assertEquals(expectedUserAuthenticationRequired, config.userAuthenticationRequired) + assertEquals(expectedUseStrongBoxForKeys, config.useStrongBoxForKeys) + + } +} \ No newline at end of file diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderParUsageTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderParUsageTest.kt new file mode 100644 index 00000000..72c1c4c8 --- /dev/null +++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderParUsageTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 European Commission + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package eu.europa.ec.eudi.wallet.issue.openid4vci + +import org.junit.Assert.assertEquals +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import kotlin.test.Test + +@RunWith(value = Parameterized::class) +class OpenId4VciManagerConfigBuilderParUsageTest( + private val parUsage: Int, +) { + + @Test + fun `ConfigBuilder set the parUsage property correctly`() { + val builder = OpenId4VciManager.Config.Builder() + .withIssuerUrl("https://issuer.example.com") + .withClientId("testClientId") + .withAuthFlowRedirectionURI("app://redirect") + .withParUsage(parUsage) + + val config = builder.build() + + assertEquals(parUsage, config.parUsage) + } + + companion object { + + @Parameterized.Parameters(name = "{index}: parUsage={0}") + @JvmStatic + fun parUsageArgs() = arrayListOf( + OpenId4VciManager.Config.ParUsage.IF_SUPPORTED, + OpenId4VciManager.Config.ParUsage.REQUIRED, + OpenId4VciManager.Config.ParUsage.NEVER + ) + } + +} diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderTest.kt index 6df0f35f..64b96810 100644 --- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderTest.kt +++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManagerConfigBuilderTest.kt @@ -20,9 +20,6 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource import kotlin.test.Test @@ -100,28 +97,4 @@ class OpenId4VciManagerConfigBuilderTest { assertTrue(config.useDPoPIfSupported) } - - @ParameterizedTest(name = "parUsage: {0}") - @MethodSource("parUsageArgs") - fun `ConfigBuilder set the parUsage property correctly`(parUsage: Int) { - val builder = OpenId4VciManager.Config.Builder() - .withIssuerUrl("https://issuer.example.com") - .withClientId("testClientId") - .withAuthFlowRedirectionURI("app://redirect") - .withParUsage(parUsage) - - val config = builder.build() - - assertEquals(parUsage, config.parUsage) - } - - companion object { - - @JvmStatic - fun parUsageArgs() = listOf( - OpenId4VciManager.Config.ParUsage.IF_SUPPORTED, - OpenId4VciManager.Config.ParUsage.REQUIRED, - OpenId4VciManager.Config.ParUsage.NEVER - ).map { Arguments.of(it) } - } } \ No newline at end of file