Skip to content

Commit 2a46975

Browse files
authored
Merge pull request eu-digital-identity-wallet#462 from niscy-eudiw/main
OpenID4VCI V1 Support
2 parents 1b0c6bb + e67b2dc commit 2a46975

File tree

9 files changed

+65
-48
lines changed

9 files changed

+65
-48
lines changed

core-logic/src/demo/java/eu/europa/ec/corelogic/config/WalletCoreConfigImpl.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager
2323
import eu.europa.ec.eudi.wallet.transfer.openId4vp.ClientIdScheme
2424
import eu.europa.ec.eudi.wallet.transfer.openId4vp.Format
2525
import eu.europa.ec.resourceslogic.R
26+
import kotlin.time.Duration.Companion.seconds
2627

2728
internal class WalletCoreConfigImpl(
2829
private val context: Context
@@ -36,7 +37,7 @@ internal class WalletCoreConfigImpl(
3637
_config = EudiWalletConfig {
3738
configureDocumentKeyCreation(
3839
userAuthenticationRequired = false,
39-
userAuthenticationTimeout = 30_000L,
40+
userAuthenticationTimeout = 30.seconds,
4041
useStrongBoxForKeys = true
4142
)
4243
configureOpenId4Vp {
@@ -81,14 +82,14 @@ internal class WalletCoreConfigImpl(
8182
.withClientId(clientId = "wallet-dev")
8283
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
8384
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
84-
.withUseDPoPIfSupported(true)
85+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
8586
.build(),
8687
OpenId4VciManager.Config.Builder()
8788
.withIssuerUrl(issuerUrl = "https://issuer-backend.eudiw.dev")
8889
.withClientId(clientId = "wallet-dev")
8990
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
9091
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
91-
.withUseDPoPIfSupported(true)
92+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
9293
.build()
9394
)
9495
}

core-logic/src/dev/java/eu/europa/ec/corelogic/config/WalletCoreConfigImpl.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager
2323
import eu.europa.ec.eudi.wallet.transfer.openId4vp.ClientIdScheme
2424
import eu.europa.ec.eudi.wallet.transfer.openId4vp.Format
2525
import eu.europa.ec.resourceslogic.R
26+
import kotlin.time.Duration.Companion.seconds
2627

2728
internal class WalletCoreConfigImpl(
2829
private val context: Context
@@ -36,7 +37,7 @@ internal class WalletCoreConfigImpl(
3637
_config = EudiWalletConfig {
3738
configureDocumentKeyCreation(
3839
userAuthenticationRequired = false,
39-
userAuthenticationTimeout = 30_000L,
40+
userAuthenticationTimeout = 30.seconds,
4041
useStrongBoxForKeys = true
4142
)
4243
configureOpenId4Vp {
@@ -81,14 +82,14 @@ internal class WalletCoreConfigImpl(
8182
.withClientId(clientId = "wallet-dev")
8283
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
8384
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
84-
.withUseDPoPIfSupported(true)
85+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
8586
.build(),
8687
OpenId4VciManager.Config.Builder()
8788
.withIssuerUrl(issuerUrl = "https://dev.issuer-backend.eudiw.dev")
8889
.withClientId(clientId = "wallet-dev")
8990
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
9091
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
91-
.withUseDPoPIfSupported(true)
92+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
9293
.build()
9394
)
9495
}

core-logic/src/main/java/eu/europa/ec/corelogic/controller/WalletCoreDocumentsController.kt

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class WalletCoreDocumentsControllerImpl(
251251
metadata.flatMap { (issuer, meta) ->
252252
meta.credentialConfigurationsSupported.map { (id, config) ->
253253

254-
val name = config.display.getLocalizedDisplayName(
254+
val name: String = config.credentialMetadata.getLocalizedDisplayName(
255255
userLocale = locale,
256256
fallback = id.value
257257
)
@@ -372,7 +372,14 @@ class WalletCoreDocumentsControllerImpl(
372372
callbackFlow {
373373
resolveDocumentOffer(offerUri).collect {
374374
when (it) {
375-
is ResolveDocumentOfferPartialState.Failure -> throw Throwable(it.errorMessage)
375+
is ResolveDocumentOfferPartialState.Failure -> {
376+
trySendBlocking(
377+
IssueDocumentsPartialState.Failure(
378+
errorMessage = it.errorMessage
379+
)
380+
)
381+
}
382+
376383
is ResolveDocumentOfferPartialState.Success -> {
377384

378385
val issuerId = it
@@ -496,9 +503,13 @@ class WalletCoreDocumentsControllerImpl(
496503

497504
manager.resolveDocumentOffer(offerUri) { result ->
498505
when (result) {
499-
is OfferResult.Failure -> throw Throwable(
500-
result.cause.localizedMessage ?: genericErrorMessage
501-
)
506+
is OfferResult.Failure -> {
507+
trySendBlocking(
508+
ResolveDocumentOfferPartialState.Failure(
509+
result.cause.localizedMessage ?: genericErrorMessage
510+
)
511+
)
512+
}
502513

503514
is OfferResult.Success -> {
504515
trySendBlocking(
@@ -783,10 +794,11 @@ class WalletCoreDocumentsControllerImpl(
783794
return listener
784795
}
785796

786-
private fun extractCredentialIssuerFromOfferUri(offerUri: String): Result<String> = runCatching {
787-
val credentialOffer = offerUri.toUri().getQueryParameter("credential_offer")
788-
val decoded = URLDecoder.decode(credentialOffer, "UTF-8")
789-
val json = JSONObject(decoded)
790-
json.getString("credential_issuer")
791-
}
797+
private fun extractCredentialIssuerFromOfferUri(offerUri: String): Result<String> =
798+
runCatching {
799+
val credentialOffer = offerUri.toUri().getQueryParameter("credential_offer")
800+
val decoded = URLDecoder.decode(credentialOffer, "UTF-8")
801+
val json = JSONObject(decoded)
802+
json.getString("credential_issuer")
803+
}
792804
}

core-logic/src/main/java/eu/europa/ec/corelogic/extension/DisplayExtensions.kt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
package eu.europa.ec.corelogic.extension
1818

1919
import eu.europa.ec.businesslogic.extension.getLocalizedString
20-
import eu.europa.ec.eudi.openid4vci.Display
20+
import eu.europa.ec.eudi.openid4vci.CredentialMetadata
2121
import eu.europa.ec.eudi.wallet.document.metadata.IssuerMetadata
22-
2322
import java.util.Locale
2423

2524
/**
@@ -49,23 +48,25 @@ fun List<IssuerMetadata.Claim.Display>?.getLocalizedClaimName(
4948
}
5049

5150
/**
52-
* Retrieves the localized display name from a list of [Display] objects based on the user's locale.
51+
* Retrieves the localized display name of a document based on the user's locale.
5352
*
54-
* This function searches through a list of [Display] objects to find a display name that matches
55-
* the provided [userLocale]. If a matching locale is found, the corresponding name is returned.
56-
* If no matching locale is found, the provided [fallback] string is returned.
53+
* This function attempts to find a localized version of the document's name
54+
* within the [CredentialMetadata.display] property of the [CredentialMetadata] object. If a localized
55+
* version matching the user's locale is found, it is returned. If no matching
56+
* localized version is found, a fallback string is returned instead.
5757
*
58-
* @param userLocale The user's locale to match against.
59-
* @param fallback The fallback string to use if no match is found.
60-
* @return The localized display name if found, otherwise the [fallback] string.
58+
* @param userLocale The user's locale, used to find a matching localized name.
59+
* @param fallback The string to return if no matching localized name is found.
60+
* @return The localized document name, or the fallback string if no matching localized name is available.
61+
* If [CredentialMetadata] or its display is null, it will return the [fallback].
6162
*
6263
* @see getLocalizedString
6364
*/
64-
fun List<Display>.getLocalizedDisplayName(
65+
fun CredentialMetadata?.getLocalizedDisplayName(
6566
userLocale: Locale,
6667
fallback: String,
6768
): String {
68-
return this.getLocalizedString(
69+
return this?.display.getLocalizedString(
6970
userLocale = userLocale,
7071
localeExtractor = { it.locale },
7172
stringExtractor = { it.name },

core-logic/src/main/java/eu/europa/ec/corelogic/extension/OfferExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ val Offer.OfferedDocument.documentIdentifier: DocumentIdentifier?
5252
}
5353

5454
fun Offer.OfferedDocument.getName(locale: Locale): String? {
55-
return configuration.display.getLocalizedValue(
55+
return configuration.credentialMetadata?.display.getLocalizedValue(
5656
userLocale = locale,
5757
localeExtractor = { it.locale },
5858
valueExtractor = { it.name },

gradle/libs.versions.toml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ androidGradlePlugin = "8.13.0"
55
androidxActivity = "1.11.0"
66
androidxAppCompat = "1.7.1"
77
androidxBrowser = "1.9.0"
8-
androidxComposeBom = "2025.10.00"
9-
androidxComposeRuntimeTracing = "1.9.3"
8+
androidxComposeBom = "2025.10.01"
9+
androidxComposeRuntimeTracing = "1.9.4"
1010
androidxCore = "1.17.0"
1111
androidxCoreSplashscreen = "1.0.1"
1212
androidxDataStore = "1.1.7"
@@ -24,47 +24,47 @@ androidxTestOrchestrator = "1.3.0"
2424
androidxTracing = "1.3.0"
2525
androidxUiAutomator = "2.3.0"
2626
androidxWindowManager = "1.5.0"
27-
androidxWork = "2.10.5"
27+
androidxWork = "2.11.0"
2828
androidxBiometric = "1.2.0-alpha05"
2929
androidxAppAuth = "1.0.0"
3030
coil = "3.3.0"
3131
constraintlayoutVersion = "1.1.1"
3232
gmsPlugin = "4.4.4"
3333
junit4 = "4.13.2"
34-
kotlin = "2.2.20"
34+
kotlin = "2.2.21"
3535
kotlinxCoroutines = "1.10.2"
3636
kotlinxDatetime = "0.7.1"
3737
kotlinxSerializationJson = "1.9.0"
3838
ksp = "2.2.20-2.0.3"
3939
lint = "31.13.0"
40-
okhttp = "5.2.1"
41-
protobuf = "4.32.1"
40+
okhttp = "5.3.0"
41+
protobuf = "4.33.0"
4242
protobufPlugin = "0.9.5"
4343
retrofit = "3.0.0"
4444
robolectric = "4.16"
4545
secrets = "2.0.1"
4646
turbine = "1.2.1"
4747
koin = "4.1.1"
48-
koinAnnotations = "2.2.0"
48+
koinAnnotations = "2.3.0"
4949
material = "1.13.0"
5050
mockito = "5.20.0"
5151
mockitoKotlin = "6.1.0"
5252
ktor = "3.3.1"
5353
slf4j = "2.0.17"
5454
gson = "2.13.2"
55-
googlePhoneNumber = "9.0.16"
55+
googlePhoneNumber = "9.0.17"
5656
zxing = "3.5.3"
57-
eudiWalletCore = "0.20.0"
57+
eudiWalletCore = "0.21.0"
5858
cameraCore = "1.5.1"
5959
owaspDependencyCheck = "12.1.8"
6060
material3 = "1.4.0"
61-
kover = "0.9.2"
62-
sonar = "7.0.0.6105"
61+
kover = "0.9.3"
62+
sonar = "7.0.1.6134"
6363
baselineprofile = "1.4.1"
6464
timber = "5.0.1"
6565
treessence = "1.1.2"
6666
rqesUiSDK = "0.3.4"
67-
androidxRoom = "2.8.2"
67+
androidxRoom = "2.8.3"
6868
cloudy = "0.2.7"
6969

7070
[libraries]

issuance-feature/src/test/java/eu/europa/ec/issuancefeature/interactor/TestDocumentOfferInteractor.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import eu.europa.ec.eudi.openid4vci.CredentialConfigurationIdentifier
3131
import eu.europa.ec.eudi.openid4vci.CredentialIssuerEndpoint
3232
import eu.europa.ec.eudi.openid4vci.CredentialIssuerId
3333
import eu.europa.ec.eudi.openid4vci.CredentialIssuerMetadata
34+
import eu.europa.ec.eudi.openid4vci.CredentialMetadata
3435
import eu.europa.ec.eudi.openid4vci.Display
3536
import eu.europa.ec.eudi.openid4vci.MsoMdocCredential
3637
import eu.europa.ec.eudi.openid4vci.TxCode
@@ -1094,7 +1095,8 @@ class TestDocumentOfferInteractor {
10941095
credentialConfigurationsSupported = mapOf(
10951096
CredentialConfigurationIdentifier("identifier") to MsoMdocCredential(
10961097
docType = docType,
1097-
isoPolicy = null
1098+
isoPolicy = null,
1099+
credentialMetadata = null
10981100
)
10991101
),
11001102
display = listOf(
@@ -1122,7 +1124,7 @@ class TestDocumentOfferInteractor {
11221124
MsoMdocCredential(
11231125
docType = mockedOfferedDocumentDocType,
11241126
isoPolicy = null,
1125-
display = display
1127+
credentialMetadata = CredentialMetadata(display = display)
11261128
)
11271129
)
11281130
}

wiki/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ override val vciConfig: List<OpenId4VciManager.Config>
3434
.withClientId(clientId = "wallet-dev")
3535
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
3636
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
37-
.withUseDPoPIfSupported(true)
37+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
3838
.build()
3939
)
4040
```

wiki/how_to_build.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ override val vciConfig: List<OpenId4VciManager.Config>
4545
.withClientId(clientId = "wallet-dev")
4646
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
4747
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
48-
.withUseDPoPIfSupported(true)
48+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
4949
.build()
5050
)
5151
```
@@ -68,7 +68,7 @@ override val vciConfig: List<OpenId4VciManager.Config>
6868
.withClientId(clientId = "wallet-dev")
6969
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
7070
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
71-
.withUseDPoPIfSupported(true)
71+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
7272
.build()
7373
)
7474
```
@@ -81,7 +81,7 @@ override val vciConfig: List<OpenId4VciManager.Config>
8181
.withClientId(clientId = "wallet-dev")
8282
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
8383
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
84-
.withUseDPoPIfSupported(true)
84+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
8585
.build()
8686
)
8787
```
@@ -95,7 +95,7 @@ override val vciConfig: List<OpenId4VciManager.Config>
9595
.withClientId(clientId = "wallet-dev")
9696
.withAuthFlowRedirectionURI(BuildConfig.ISSUE_AUTHORIZATION_DEEPLINK)
9797
.withParUsage(OpenId4VciManager.Config.ParUsage.IF_SUPPORTED)
98-
.withUseDPoPIfSupported(true)
98+
.withDPoPUsage(OpenId4VciManager.Config.DPoPUsage.IfSupported())
9999
.build()
100100
)
101101
```

0 commit comments

Comments
 (0)