diff --git a/README.md b/README.md
index 45546a9a..c439ad90 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ The library provides the following functionality:
- [x] Support credential offer
- [x] Support for DPoP JWT in authorization
- [x] Support for JWT and CWT proof types
- - [ ] Support for deferred issuing
+ - [x] Support for deferred issuing
- Proximity document presentation
- [x] Support for ISO-18013-5 device retrieval
- [x] QR device engagement
@@ -293,12 +293,12 @@ val attestationChallenge = byteArrayOf(
)
val result = EudiWallet.createDocument(docType, hardwareBacked, attestationChallenge)
when (result) {
- is CreateIssuanceRequestResult.Failure -> {
+ is CreateDocumentResult.Failure -> {
val error = result.throwable
// handle error
}
- is CreateIssuanceRequestResult.Success -> {
+ is CreateDocumentResult.Success -> {
val unsignedDocument = result.issuanceRequest
val docType = unsignedDocument.docType
// the device certificate that will be used in the signing of the document
@@ -341,11 +341,11 @@ when (result) {
val storeResult = EudiWallet.storeIssuedDocument(unsignedDocument, issuerData)
when (storeResult) {
- is AddDocumentResult.Failure -> {
+ is StoreDocumentResult.Failure -> {
val error = storeResult.throwable
// handle error while adding document
}
- is AddDocumentResult.Success -> {
+ is StoreDocumentResult.Success -> {
val documentId = storeResult.documentId
// the documentId of the newly added document
// use the documentId to retrieve the document
@@ -545,6 +545,14 @@ val onIssueEvent = OnIssueEvent { event ->
// or cancel the issuance process by calling
event.cancel()
}
+
+ is IssueEvent.DocumentDeferred -> {
+ // triggered when the document issuance is deferred
+ // and holds the documentId of the deferred document
+ val documentId: String = event.documentId
+ val documentName: String = event.name
+ val docType: String = event.docType
+ }
}
}
@@ -581,7 +589,7 @@ EudiWallet.issueDocumentByDocType(
}
```
-##### Authorization code flow
+#### Authorization code flow
For the authorization code flow to work, the application must handle the redirect URI. The redirect URI is the URI that
the Issuer will redirect the user to after the user has authenticated and authorized. The redirect URI must be handled
@@ -638,7 +646,7 @@ class SomeActivity : AppCompatActivity() {
}
```
-##### Pre-Authorization code flow
+#### Pre-Authorization code flow
When Issuer supports the pre-authorization code flow, the resolved offer will also contain the corresponding
information. Specifically, the `txCodeSpec` field in the `Offer` object will contain:
@@ -657,6 +665,30 @@ When the transaction code is provided, the issuance process can be resumed by ca
passing the transaction code as in the `txCode` parameter.
+#### Deferred Issuance
+
+When the document issuance is deferred, the `IssueEvent.DocumentDeferred` event is triggered. The deferred document can
+be issued later by calling the `EudiWallet.issueDeferredDocument` method.
+
+```kotlin
+val documentId = "documentId"
+
+EudiWallet.issueDeferredDocument(documentId) { result ->
+ when (result) {
+ is DeferredIssueResult.DocumentIssued -> {
+ // document issued
+ }
+ is DeferredIssueResult.DocumentFailed -> {
+ // error
+ val cause = result.throwable
+ }
+ is DeferredIssueResult.DocumentNotReady -> {
+ // document is not issued yet
+ }
+ }
+}
+```
+
### Transfer documents
The library supports the following 3 ways to transfer documents:
diff --git a/changelog.md b/changelog.md
index 4e43a884..e837c062 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,17 @@
# Changelog
+## [0.10.0-SNAPSHOT]
+
+__27 Jun 2024__
+
+- Bump eudi-lib-jvm-openid4vci-kt to v0.3.2
+- Bump eudi-lib-android-wallet-document-manager to v0.4.0-SNAPSHOT
+- Support for OpenId4VCI pre-authorization flow
+- Support for OpenId4VCI deferred issuance
+- Extensive logging for OpenId4VCI and OpenId4VP
+- Allow overriding ktor client for OpenId4VCI and OpenId4VP
+- Bug fixes in OpenId4VCI
+
## [0.9.5-SNAPSHOT]
__14 Jun 2024__
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/-document-failed.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/-document-failed.md
new file mode 100644
index 00000000..24d02838
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/-document-failed.md
@@ -0,0 +1,7 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentFailed](index.md)/[DocumentFailed](-document-failed.md)
+
+# DocumentFailed
+
+[androidJvm]\
+constructor(documentId: DocumentId,
+cause: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html))
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/cause.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/cause.md
new file mode 100644
index 00000000..0d173165
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/cause.md
@@ -0,0 +1,7 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentFailed](index.md)/[cause](cause.md)
+
+# cause
+
+[androidJvm]\
+open override
+val [cause](cause.md): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/document-id.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/document-id.md
new file mode 100644
index 00000000..31d60787
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/document-id.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentFailed](index.md)/[documentId](document-id.md)
+
+# documentId
+
+[androidJvm]\
+val [documentId](document-id.md): DocumentId
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/index.md
new file mode 100644
index 00000000..a36d6ee9
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/index.md
@@ -0,0 +1,22 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentFailed](index.md)
+
+# DocumentFailed
+
+[androidJvm]\
+data class [DocumentFailed](index.md)(val documentId: DocumentId, val
+cause: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)) : [DeferredIssueResult](../index.md), [OpenId4VciResult.Erroneous](../../-open-id4-vci-result/-erroneous/index.md)
+
+Document issuance failed.
+
+## Constructors
+
+| | |
+|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
+| [DocumentFailed](-document-failed.md) | [androidJvm]
constructor(documentId: DocumentId, cause: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)) |
+
+## Properties
+
+| Name | Summary |
+|------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [cause](cause.md) | [androidJvm]
open override val [cause](cause.md): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)
the error that caused the failure |
+| [documentId](document-id.md) | [androidJvm]
val [documentId](document-id.md): DocumentId |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/-document-issued.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/-document-issued.md
new file mode 100644
index 00000000..5a05d8d0
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/-document-issued.md
@@ -0,0 +1,8 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentIssued](index.md)/[DocumentIssued](-document-issued.md)
+
+# DocumentIssued
+
+[androidJvm]\
+constructor(documentId: DocumentId,
+name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html),
+docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html))
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/doc-type.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/doc-type.md
new file mode 100644
index 00000000..a13c7589
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/doc-type.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentIssued](index.md)/[docType](doc-type.md)
+
+# docType
+
+[androidJvm]\
+val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/document-id.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/document-id.md
new file mode 100644
index 00000000..dd0fee36
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/document-id.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentIssued](index.md)/[documentId](document-id.md)
+
+# documentId
+
+[androidJvm]\
+val [documentId](document-id.md): DocumentId
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/index.md
new file mode 100644
index 00000000..087cc0a5
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/index.md
@@ -0,0 +1,29 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentIssued](index.md)
+
+# DocumentIssued
+
+data class [DocumentIssued](index.md)(val documentId: DocumentId, val
+name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val
+docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) : [DeferredIssueResult](../index.md)
+
+Document issued successfully.
+
+#### See also
+
+| | |
+|------------|---------------------|
+| DocumentId | for the document id |
+
+## Constructors
+
+| | |
+|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [DocumentIssued](-document-issued.md) | [androidJvm]
constructor(documentId: DocumentId, name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) |
+
+## Properties
+
+| Name | Summary |
+|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
+| [docType](doc-type.md) | [androidJvm]
val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the document type |
+| [documentId](document-id.md) | [androidJvm]
val [documentId](document-id.md): DocumentId
the id of the issued document |
+| [name](name.md) | [androidJvm]
val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the name of the document |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/name.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/name.md
new file mode 100644
index 00000000..359bb829
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/name.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentIssued](index.md)/[name](name.md)
+
+# name
+
+[androidJvm]\
+val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/-document-not-ready.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/-document-not-ready.md
new file mode 100644
index 00000000..8459c003
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/-document-not-ready.md
@@ -0,0 +1,8 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentNotReady](index.md)/[DocumentNotReady](-document-not-ready.md)
+
+# DocumentNotReady
+
+[androidJvm]\
+constructor(documentId: DocumentId,
+name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html),
+docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html))
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/doc-type.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/doc-type.md
new file mode 100644
index 00000000..77ada789
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/doc-type.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentNotReady](index.md)/[docType](doc-type.md)
+
+# docType
+
+[androidJvm]\
+val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/document-id.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/document-id.md
new file mode 100644
index 00000000..042f8e10
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/document-id.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentNotReady](index.md)/[documentId](document-id.md)
+
+# documentId
+
+[androidJvm]\
+val [documentId](document-id.md): DocumentId
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/index.md
new file mode 100644
index 00000000..fd326a49
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/index.md
@@ -0,0 +1,24 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentNotReady](index.md)
+
+# DocumentNotReady
+
+[androidJvm]\
+data class [DocumentNotReady](index.md)(val documentId: DocumentId, val
+name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val
+docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) : [DeferredIssueResult](../index.md)
+
+Document issuance deferred.
+
+## Constructors
+
+| | |
+|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [DocumentNotReady](-document-not-ready.md) | [androidJvm]
constructor(documentId: DocumentId, name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) |
+
+## Properties
+
+| Name | Summary |
+|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
+| [docType](doc-type.md) | [androidJvm]
val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the document type |
+| [documentId](document-id.md) | [androidJvm]
val [documentId](document-id.md): DocumentId
the id of the deferred document |
+| [name](name.md) | [androidJvm]
val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the name of the document |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/name.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/name.md
new file mode 100644
index 00000000..42fdb883
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/name.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[DeferredIssueResult](../index.md)/[DocumentNotReady](index.md)/[name](name.md)
+
+# name
+
+[androidJvm]\
+val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/index.md
new file mode 100644
index 00000000..becfca6a
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/index.md
@@ -0,0 +1,21 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[DeferredIssueResult](index.md)
+
+# DeferredIssueResult
+
+interface [DeferredIssueResult](index.md) : [OpenId4VciResult](../-open-id4-vci-result/index.md)
+
+#### Inheritors
+
+| |
+|--------------------------------------------------|
+| [DocumentIssued](-document-issued/index.md) |
+| [DocumentFailed](-document-failed/index.md) |
+| [DocumentNotReady](-document-not-ready/index.md) |
+
+## Types
+
+| Name | Summary |
+|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [DocumentFailed](-document-failed/index.md) | [androidJvm]
data class [DocumentFailed](-document-failed/index.md)(val documentId: DocumentId, val cause: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)) : [DeferredIssueResult](index.md), [OpenId4VciResult.Erroneous](../-open-id4-vci-result/-erroneous/index.md)
Document issuance failed. |
+| [DocumentIssued](-document-issued/index.md) | [androidJvm]
data class [DocumentIssued](-document-issued/index.md)(val documentId: DocumentId, val name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) : [DeferredIssueResult](index.md)
Document issued successfully. |
+| [DocumentNotReady](-document-not-ready/index.md) | [androidJvm]
data class [DocumentNotReady](-document-not-ready/index.md)(val documentId: DocumentId, val name: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)) : [DeferredIssueResult](index.md)
Document issuance deferred. |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md
index f98d9408..94ab617e 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md
@@ -3,6 +3,6 @@
# TxCodeSpec
[androidJvm]\
-constructor(inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = InputMode.NUMERIC,
+constructor(inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = NUMERIC,
length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?,
description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null)
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md
index 2c8ff9ca..672474f0 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md
@@ -3,17 +3,17 @@
# TxCodeSpec
[androidJvm]\
-data class [TxCodeSpec](index.md)(val inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = InputMode.NUMERIC,
-val length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, val
+data class [TxCodeSpec](index.md)(val inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = NUMERIC, val
+length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, val
description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null)
Specification for a transaction code.
## Constructors
-| | |
-|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [TxCodeSpec](-tx-code-spec.md) | [androidJvm]
constructor(inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = InputMode.NUMERIC, length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null) |
+| | |
+|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [TxCodeSpec](-tx-code-spec.md) | [androidJvm]
constructor(inputMode: [Offer.TxCodeSpec.InputMode](-input-mode/index.md) = NUMERIC, length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null) |
## Types
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md
index ef8c770f..ba05a853 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md
@@ -9,10 +9,10 @@ An offer of credentials to be issued.
## Types
-| Name | Summary |
-|-----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [OfferedDocument](-offered-document/index.md) | [androidJvm]
interface [OfferedDocument](-offered-document/index.md)
An item to be issued. |
-| [TxCodeSpec](-tx-code-spec/index.md) | [androidJvm]
data class [TxCodeSpec](-tx-code-spec/index.md)(val inputMode: [Offer.TxCodeSpec.InputMode](-tx-code-spec/-input-mode/index.md) = InputMode.NUMERIC, val length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, val description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null)
Specification for a transaction code. |
+| Name | Summary |
+|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [OfferedDocument](-offered-document/index.md) | [androidJvm]
interface [OfferedDocument](-offered-document/index.md)
An item to be issued. |
+| [TxCodeSpec](-tx-code-spec/index.md) | [androidJvm]
data class [TxCodeSpec](-tx-code-spec/index.md)(val inputMode: [Offer.TxCodeSpec.InputMode](-tx-code-spec/-input-mode/index.md) = NUMERIC, val length: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?, val description: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null)
Specification for a transaction code. |
## Properties
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md
new file mode 100644
index 00000000..f51266c6
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md
@@ -0,0 +1,16 @@
+//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[OpenId4VciManager](../index.md)/[OnDeferredIssueResult](index.md)
+
+# OnDeferredIssueResult
+
+[androidJvm]\
+fun interface [OnDeferredIssueResult](index.md) : [OpenId4VciManager.OnResult](../-on-result/index.md)
+<[DeferredIssueResult](../../-deferred-issue-result/index.md)>
+
+Callback to be called when a deferred document is issued
+
+## Functions
+
+| Name | Summary |
+|-----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [invoke](index.md#1649133642%2FFunctions%2F1615067946) | [androidJvm]
open operator fun [invoke](index.md#1649133642%2FFunctions%2F1615067946)(result: [DeferredIssueResult](../../-deferred-issue-result/index.md)) |
+| [onResult](index.md#-1418783954%2FFunctions%2F1615067946) | [androidJvm]
abstract fun [onResult](index.md#-1418783954%2FFunctions%2F1615067946)(result: [DeferredIssueResult](../../-deferred-issue-result/index.md)) |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/index.md
index 37d0509a..a83e7af5 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/index.md
@@ -10,10 +10,11 @@ and [OpenId4VciManager.resolveDocumentOffer](../resolve-document-offer.md) metho
#### Inheritors
-| |
-|---------------------------------------------------|
-| [OnIssueEvent](../-on-issue-event/index.md) |
-| [OnResolvedOffer](../-on-resolved-offer/index.md) |
+| |
+|----------------------------------------------------------------|
+| [OnIssueEvent](../-on-issue-event/index.md) |
+| [OnResolvedOffer](../-on-resolved-offer/index.md) |
+| [OnDeferredIssueResult](../-on-deferred-issue-result/index.md) |
## Functions
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/index.md
index 4344b457..43fb910f 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/index.md
@@ -15,20 +15,21 @@ documents using a document type or an offer, and to resolve an offer
## Types
-| Name | Summary |
-|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Builder](-builder/index.md) | [androidJvm]
class [Builder](-builder/index.md)(context: [Context](https://developer.android.com/reference/kotlin/android/content/Context.html))
Builder to create an instance of [OpenId4VciManager](index.md) |
-| [Companion](-companion/index.md) | [androidJvm]
object [Companion](-companion/index.md) |
-| [Config](-config/index.md) | [androidJvm]
data class [Config](-config/index.md)(val issuerUrl: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val clientId: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val authFlowRedirectionURI: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val useStrongBoxIfSupported: [Boolean](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html), val useDPoPIfSupported: [Boolean](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html), val parUsage: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html), val proofTypes: [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<[OpenId4VciManager.Config.ProofType](-config/-proof-type/index.md)>)
Configuration for the OpenId4Vci issuer |
-| [OnIssueEvent](-on-issue-event/index.md) | [androidJvm]
fun interface [OnIssueEvent](-on-issue-event/index.md) : [OpenId4VciManager.OnResult](-on-result/index.md)<[IssueEvent](../-issue-event/index.md)>
Callback to be called when a document is issued |
-| [OnResolvedOffer](-on-resolved-offer/index.md) | [androidJvm]
fun interface [OnResolvedOffer](-on-resolved-offer/index.md) : [OpenId4VciManager.OnResult](-on-result/index.md)<[OfferResult](../-offer-result/index.md)>
Callback to be called when an offer is resolved |
-| [OnResult](-on-result/index.md) | [androidJvm]
fun interface [OnResult](-on-result/index.md)<[T](-on-result/index.md) : [OpenId4VciResult](../-open-id4-vci-result/index.md)>
Callback to be called for [OpenId4VciManager.issueDocumentByDocType](issue-document-by-doc-type.md), [OpenId4VciManager.issueDocumentByOffer](issue-document-by-offer.md), [OpenId4VciManager.issueDocumentByOfferUri](issue-document-by-offer-uri.md) and [OpenId4VciManager.resolveDocumentOffer](resolve-document-offer.md) methods |
+| Name | Summary |
+|-------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Builder](-builder/index.md) | [androidJvm]
class [Builder](-builder/index.md)(context: [Context](https://developer.android.com/reference/kotlin/android/content/Context.html))
Builder to create an instance of [OpenId4VciManager](index.md) |
+| [Companion](-companion/index.md) | [androidJvm]
object [Companion](-companion/index.md) |
+| [Config](-config/index.md) | [androidJvm]
data class [Config](-config/index.md)(val issuerUrl: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val clientId: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val authFlowRedirectionURI: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val useStrongBoxIfSupported: [Boolean](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html), val useDPoPIfSupported: [Boolean](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/index.html), val parUsage: [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html), val proofTypes: [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<[OpenId4VciManager.Config.ProofType](-config/-proof-type/index.md)>)
Configuration for the OpenId4Vci issuer |
+| [OnDeferredIssueResult](-on-deferred-issue-result/index.md) | [androidJvm]
fun interface [OnDeferredIssueResult](-on-deferred-issue-result/index.md) : [OpenId4VciManager.OnResult](-on-result/index.md)<[DeferredIssueResult](../-deferred-issue-result/index.md)>
Callback to be called when a deferred document is issued |
+| [OnIssueEvent](-on-issue-event/index.md) | [androidJvm]
fun interface [OnIssueEvent](-on-issue-event/index.md) : [OpenId4VciManager.OnResult](-on-result/index.md)<[IssueEvent](../-issue-event/index.md)>
Callback to be called when a document is issued |
+| [OnResolvedOffer](-on-resolved-offer/index.md) | [androidJvm]
fun interface [OnResolvedOffer](-on-resolved-offer/index.md) : [OpenId4VciManager.OnResult](-on-result/index.md)<[OfferResult](../-offer-result/index.md)>
Callback to be called when an offer is resolved |
+| [OnResult](-on-result/index.md) | [androidJvm]
fun interface [OnResult](-on-result/index.md)<[T](-on-result/index.md) : [OpenId4VciResult](../-open-id4-vci-result/index.md)>
Callback to be called for [OpenId4VciManager.issueDocumentByDocType](issue-document-by-doc-type.md), [OpenId4VciManager.issueDocumentByOffer](issue-document-by-offer.md), [OpenId4VciManager.issueDocumentByOfferUri](issue-document-by-offer-uri.md) and [OpenId4VciManager.resolveDocumentOffer](resolve-document-offer.md) methods |
## Functions
| Name | Summary |
|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [issueDeferredDocument](issue-deferred-document.md) | [androidJvm]
abstract fun [issueDeferredDocument](issue-deferred-document.md)(deferredDocument: DeferredDocument, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)?, onIssueEvent: [OpenId4VciManager.OnIssueEvent](-on-issue-event/index.md))
Issue a deferred document |
+| [issueDeferredDocument](issue-deferred-document.md) | [androidJvm]
abstract fun [issueDeferredDocument](issue-deferred-document.md)(deferredDocument: DeferredDocument, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)?, onIssueEvent: [OpenId4VciManager.OnDeferredIssueResult](-on-deferred-issue-result/index.md))
Issue a deferred document |
| [issueDocumentByDocType](issue-document-by-doc-type.md) | [androidJvm]
abstract fun [issueDocumentByDocType](issue-document-by-doc-type.md)(docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onIssueEvent: [OpenId4VciManager.OnIssueEvent](-on-issue-event/index.md))
Issue a document using a document type |
| [issueDocumentByOffer](issue-document-by-offer.md) | [androidJvm]
abstract fun [issueDocumentByOffer](issue-document-by-offer.md)(offer: [Offer](../-offer/index.md), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onIssueEvent: [OpenId4VciManager.OnIssueEvent](-on-issue-event/index.md))
Issue a document using an offer |
| [issueDocumentByOfferUri](issue-document-by-offer-uri.md) | [androidJvm]
abstract fun [issueDocumentByOfferUri](issue-document-by-offer-uri.md)(offerUri: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onIssueEvent: [OpenId4VciManager.OnIssueEvent](-on-issue-event/index.md))
Issue a document using an offer URI |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md
index 07869bfd..22118966 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md
@@ -5,7 +5,7 @@
[androidJvm]\
abstract fun [issueDeferredDocument](issue-deferred-document.md)(deferredDocument: DeferredDocument,
executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)?,
-onIssueEvent: [OpenId4VciManager.OnIssueEvent](-on-issue-event/index.md))
+onIssueEvent: [OpenId4VciManager.OnDeferredIssueResult](-on-deferred-issue-result/index.md))
Issue a deferred document
@@ -21,6 +21,6 @@ androidJvm
#### See also
-| | |
-|----------------------------------------|-----------------------------|
-| [IssueEvent](../-issue-event/index.md) | on how to handle the result |
+| | |
+|-------------------------------------------------------------------------------|-----------------------------|
+| [OpenId4VciManager.OnDeferredIssueResult](-on-deferred-issue-result/index.md) | on how to handle the result |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/-erroneous/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/-erroneous/index.md
index 95da9b90..dfed6565 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/-erroneous/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/-erroneous/index.md
@@ -6,11 +6,12 @@ interface [Erroneous](index.md)
#### Inheritors
-| |
-|----------------------------------------------------------------|
-| [Failure](../../-issue-event/-failure/index.md) |
-| [DocumentFailed](../../-issue-event/-document-failed/index.md) |
-| [Failure](../../-offer-result/-failure/index.md) |
+| |
+|--------------------------------------------------------------------------|
+| [DocumentFailed](../../-deferred-issue-result/-document-failed/index.md) |
+| [Failure](../../-issue-event/-failure/index.md) |
+| [DocumentFailed](../../-issue-event/-document-failed/index.md) |
+| [Failure](../../-offer-result/-failure/index.md) |
## Properties
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/index.md
index bfd1cbd5..230615cf 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-result/index.md
@@ -6,10 +6,11 @@ interface [OpenId4VciResult](index.md)
#### Inheritors
-| |
-|------------------------------------------|
-| [IssueEvent](../-issue-event/index.md) |
-| [OfferResult](../-offer-result/index.md) |
+| |
+|-----------------------------------------------------------|
+| [DeferredIssueResult](../-deferred-issue-result/index.md) |
+| [IssueEvent](../-issue-event/index.md) |
+| [OfferResult](../-offer-result/index.md) |
## Types
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
index 6f66c82d..c9d1529f 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
@@ -6,6 +6,7 @@
| Name | Summary |
|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [DeferredIssueResult](-deferred-issue-result/index.md) | [androidJvm]
interface [DeferredIssueResult](-deferred-issue-result/index.md) : [OpenId4VciResult](-open-id4-vci-result/index.md) |
| [IssueEvent](-issue-event/index.md) | [androidJvm]
interface [IssueEvent](-issue-event/index.md) : [OpenId4VciResult](-open-id4-vci-result/index.md)
Events related to document issuance. |
| [Offer](-offer/index.md) | [androidJvm]
interface [Offer](-offer/index.md)
An offer of credentials to be issued. |
| [OfferResult](-offer-result/index.md) | [androidJvm]
interface [OfferResult](-offer-result/index.md) : [OpenId4VciResult](-open-id4-vci-result/index.md)
The result of an offer operation. |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/index.md
index ce74deb1..e934f138 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/index.md
@@ -42,6 +42,7 @@ EudiWallet.init(context, config)
| [getDocumentById](get-document-by-id.md) | [androidJvm]
fun [getDocumentById](get-document-by-id.md)(documentId: DocumentId): Document?
Returns the document with the given [documentId](get-document-by-id.md) |
| [getDocuments](get-documents.md) | [androidJvm]
fun [getDocuments](get-documents.md)(): [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<IssuedDocument>
Returns the list of IssuedDocument |
| [init](init.md) | [androidJvm]
fun [init](init.md)(context: [Context](https://developer.android.com/reference/kotlin/android/content/Context.html), config: [EudiWalletConfig](../-eudi-wallet-config/index.md))
Initialize the sdk with the given [config](init.md) |
+| [issueDeferredDocument](issue-deferred-document.md) | [androidJvm]
fun [issueDeferredDocument](issue-deferred-document.md)(documentId: DocumentId, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onResult: [OpenId4VciManager.OnDeferredIssueResult](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md))
Issue a deferred document using the OpenId4VCI protocol |
| [issueDocumentByDocType](issue-document-by-doc-type.md) | [androidJvm]
fun [issueDocumentByDocType](issue-document-by-doc-type.md)(docType: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onEvent: [OpenId4VciManager.OnIssueEvent](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-issue-event/index.md))
Issue a document using the OpenId4VCI protocol |
| [issueDocumentByOffer](issue-document-by-offer.md) | [androidJvm]
fun [issueDocumentByOffer](issue-document-by-offer.md)(offer: [Offer](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onEvent: [OpenId4VciManager.OnIssueEvent](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-issue-event/index.md))
Issue a document using an offer and the OpenId4VCI protocol |
| [issueDocumentByOfferUri](issue-document-by-offer-uri.md) | [androidJvm]
fun [issueDocumentByOfferUri](issue-document-by-offer-uri.md)(offerUri: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), txCode: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null, executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onEvent: [OpenId4VciManager.OnIssueEvent](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-issue-event/index.md))
Issue a document using an offerUri and the OpenId4VCI protocol |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-deferred-document.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-deferred-document.md
new file mode 100644
index 00000000..b610911f
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-deferred-document.md
@@ -0,0 +1,33 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet](../index.md)/[EudiWallet](index.md)/[issueDeferredDocument](issue-deferred-document.md)
+
+# issueDeferredDocument
+
+[androidJvm]\
+fun [issueDeferredDocument](issue-deferred-document.md)(documentId: DocumentId,
+executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null,
+onResult: [OpenId4VciManager.OnDeferredIssueResult](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md))
+
+Issue a deferred document using the OpenId4VCI protocol
+
+#### Parameters
+
+androidJvm
+
+| | |
+|------------|-------------------------------------------------------------------------------------------------------------------------------|
+| documentId | the id of the deferred document |
+| executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread |
+| onResult | the callback to be called when the document is issued |
+
+#### See also
+
+| |
+|-----------------------------------------------------------------------------------------------------------------------------------------------------|
+| [OpenId4VciManager.issueDeferredDocument](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md) |
+| [OpenId4VciManager.OnDeferredIssueResult](../../eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md) | on how to handle the result |
+
+#### Throws
+
+| | |
+|------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
+| [IllegalStateException](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-state-exception/index.html) | if [EudiWallet](index.md) is not firstly initialized via the [init](init.md) method |
diff --git a/docs/wallet-core/package-list b/docs/wallet-core/package-list
index b744d6c4..08aa831d 100644
--- a/docs/wallet-core/package-list
+++ b/docs/wallet-core/package-list
@@ -7,6 +7,21 @@ $dokka.location:eu.europa.ec.eudi.wallet.document/Constants/EU_PID_NAMESPACE/#/P
$dokka.location:eu.europa.ec.eudi.wallet.document/Constants/MDL_DOCTYPE/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.document/-constants/-m-d-l_-d-o-c-t-y-p-e.md
$dokka.location:eu.europa.ec.eudi.wallet.document/Constants/MDL_NAMESPACE/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.document/-constants/-m-d-l_-n-a-m-e-s-p-a-c-e.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci////PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentFailed///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentFailed/DocumentFailed/#kotlin.String#kotlin.Throwable/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/-document-failed.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentFailed/cause/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/cause.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentFailed/documentId/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-failed/document-id.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentIssued///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentIssued/DocumentIssued/#kotlin.String#kotlin.String#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/-document-issued.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentIssued/docType/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/doc-type.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentIssued/documentId/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/document-id.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentIssued/name/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-issued/name.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentNotReady///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentNotReady/DocumentNotReady/#kotlin.String#kotlin.String#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/-document-not-ready.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentNotReady/docType/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/doc-type.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentNotReady/documentId/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/document-id.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult.DocumentNotReady/name/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/-document-not-ready/name.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/DeferredIssueResult///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-deferred-issue-result/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/IssueEvent.Companion///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-issue-event/-companion/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/IssueEvent.DocumentDeferred///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-issue-event/-document-deferred/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/IssueEvent.DocumentDeferred/DocumentDeferred/#kotlin.String#kotlin.String#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-issue-event/-document-deferred/-document-deferred.md
@@ -119,13 +134,14 @@ $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.Conf
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.Config/proofTypes/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-config/proof-types.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.Config/useDPoPIfSupported/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-config/use-d-po-p-if-supported.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.Config/useStrongBoxIfSupported/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-config/use-strong-box-if-supported.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnDeferredIssueResult///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-deferred-issue-result/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnIssueEvent///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-issue-event/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnResolvedOffer///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-resolved-offer/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnResult///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/index.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnResult/invoke/#TypeParam(bounds=[eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciResult])/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/invoke.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnResult/onResult/#TypeParam(bounds=[eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciResult])/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/-on-result/on-result.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/index.md
-$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/issueDeferredDocument/#eu.europa.ec.eudi.wallet.document.DeferredDocument#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/issueDeferredDocument/#eu.europa.ec.eudi.wallet.document.DeferredDocument#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnDeferredIssueResult/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-deferred-document.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/issueDocumentByDocType/#kotlin.String#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-doc-type.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/issueDocumentByOffer/#eu.europa.ec.eudi.wallet.issue.openid4vci.Offer#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/issueDocumentByOfferUri/#kotlin.String#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer-uri.md
@@ -274,6 +290,7 @@ $dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/getAllDocuments/#/PointingTo
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/getDocumentById/#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/get-document-by-id.md
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/getDocuments/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/get-documents.md
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/init/#android.content.Context#eu.europa.ec.eudi.wallet.EudiWalletConfig/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/init.md
+$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/issueDeferredDocument/#kotlin.String#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnDeferredIssueResult/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-deferred-document.md
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/issueDocumentByDocType/#kotlin.String#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-doc-type.md
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/issueDocumentByOffer/#eu.europa.ec.eudi.wallet.issue.openid4vci.Offer#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer.md
$dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/issueDocumentByOfferUri/#kotlin.String#kotlin.String?#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnIssueEvent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer-uri.md
diff --git a/settings.gradle b/settings.gradle
index 81bdf16b..45033f78 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
pluginManagement {
repositories {
google()
@@ -8,7 +24,6 @@ pluginManagement {
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
- mavenLocal()
google()
mavenCentral()
maven {
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 8d481129..65b911f5 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
@@ -331,6 +331,53 @@ object EudiWallet {
}
}
+ /**
+ * Issue a deferred document using the OpenId4VCI protocol
+ * @param documentId the id of the deferred document
+ * @param executor the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread
+ * @param onResult the callback to be called when the document is issued
+ * @throws IllegalStateException if [EudiWallet] is not firstly initialized via the [init] method
+ * @see [OpenId4VciManager.issueDeferredDocument]
+ * @see [OpenId4VciManager.OnDeferredIssueResult] on how to handle the result
+ */
+ fun issueDeferredDocument(
+ documentId: DocumentId,
+ executor: Executor? = null,
+ onResult: OpenId4VciManager.OnDeferredIssueResult,
+ ) {
+ requireInit {
+ config.openId4VciConfig?.let { config ->
+ openId4VciManager = OpenId4VciManager(context) {
+ documentManager(this@EudiWallet.documentManager)
+ config(config)
+ logger = this@EudiWallet.logger
+ }.also {
+ when (val document = documentManager.getDocumentById(documentId)) {
+ is DeferredDocument -> it.issueDeferredDocument(document, executor, onResult)
+ else -> (executor ?: context.mainExecutor()).execute {
+ onResult(
+ DeferredIssueResult.DocumentFailed(
+ documentId,
+ IllegalStateException("Document is not deferred")
+ )
+ )
+ }
+ }
+
+ }
+ } ?: run {
+ (executor ?: context.mainExecutor()).execute {
+ onResult(
+ DeferredIssueResult.DocumentFailed(
+ documentId,
+ IllegalStateException("OpenId4Vci config is not set in configuration")
+ )
+ )
+ }
+ }
+ }
+ }
+
/**
* Resolves a document offer using OpenId4VCI protocol
* @param offerUri the offer uri
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt
index 5bf9057e..6ce4a308 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt
@@ -20,6 +20,7 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import eu.europa.ec.eudi.openid4vci.DefaultHttpClientFactory
+import eu.europa.ec.eudi.openid4vci.DeferredIssuer
import eu.europa.ec.eudi.wallet.document.*
import eu.europa.ec.eudi.wallet.internal.mainExecutor
import eu.europa.ec.eudi.wallet.issue.openid4vci.IssueEvent.Companion.failure
@@ -136,12 +137,26 @@ internal class DefaultOpenId4VciManager(
override fun issueDeferredDocument(
deferredDocument: DeferredDocument,
executor: Executor?,
- onIssueEvent: OpenId4VciManager.OnIssueEvent,
+ onIssueEvent: OpenId4VciManager.OnDeferredIssueResult,
) {
- val deferredState = deferredDocument.relatedData.let { DeferredState.decode(it) }
- // check tokens for expiration
- // if not expires proceed with deferred issuer call
- TODO("Not yet implemented")
+ launch(onIssueEvent.wrap(executor)) { coroutineScope, callback ->
+ try {
+ val deferredContext = deferredDocument.relatedData.toDeferredIssuanceContext()
+ val (ctx, outcome) = DeferredIssuer.queryForDeferredCredential(deferredContext, ktorHttpClientFactory)
+ .getOrThrow()
+ ProcessDeferredOutcome(
+ documentManager = documentManager,
+ callback = callback,
+ deferredIssuanceContext = ctx,
+ logger = logger
+ ).process(deferredDocument, outcome)
+
+ } catch (e: Throwable) {
+ callback(DeferredIssueResult.DocumentFailed(deferredDocument.id, e))
+ coroutineScope.cancel("issueDeferredDocument failed", e)
+ }
+ }
+
}
override fun resolveDocumentOffer(
@@ -222,8 +237,7 @@ internal class DefaultOpenId4VciManager(
) {
offer as DefaultOffer
val issuer = issuerCreator.createIssuer(offer)
- var authorizedRequest = issuerAuthorization.authorize(issuer, txCode)
-
+ var authorizedRequest = issuerAuthorization.use { it.authorize(issuer, txCode) }
listener(IssueEvent.Started(offer.offeredDocuments.size))
val issuedDocumentIds = mutableListOf()
val requestMap = offer.offeredDocuments.associateBy { offeredDocument ->
@@ -235,8 +249,13 @@ internal class DefaultOpenId4VciManager(
val response = request.request(requestMap).also {
authorizedRequest = request.authorizedRequest
}
- val deferredState = DeferredState(config.clientId, issuer, authorizedRequest)
- ProcessResponse(documentManager, listener, issuedDocumentIds, deferredState).use { it.process(response) }
+ ProcessResponse(
+ documentManager = documentManager,
+ deferredContextCreator = DeferredContextCreator(issuer, authorizedRequest),
+ listener = listener,
+ issuedDocumentIds = issuedDocumentIds,
+ logger = logger
+ ).use { it.process(response) }
listener(IssueEvent.Finished(issuedDocumentIds))
}
}
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredContextCreator.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredContextCreator.kt
new file mode 100644
index 00000000..07b5c3c5
--- /dev/null
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredContextCreator.kt
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+@file:JvmMultifileClass
+
+package eu.europa.ec.eudi.wallet.issue.openid4vci
+
+import com.nimbusds.jose.EncryptionMethod
+import com.nimbusds.jose.JWEAlgorithm
+import com.nimbusds.jose.jwk.JWK
+import eu.europa.ec.eudi.openid4vci.*
+import kotlinx.serialization.Required
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.*
+import java.net.URL
+import java.time.Clock
+import java.time.Duration
+import java.time.Instant
+
+private val json = Json {
+ ignoreUnknownKeys = true
+ encodeDefaults = false
+}
+
+internal data class DeferredContextCreator(
+ val issuer: Issuer,
+ val authorizedRequest: AuthorizedRequest,
+) {
+ fun create(credential: IssuedCredential.Deferred): DeferredIssuanceContext {
+ return with(issuer) {
+ authorizedRequest.deferredContext(credential)
+ }
+ }
+}
+
+internal fun DeferredIssuanceContext.toByteArray(): ByteArray =
+ json.encodeToString(DeferredIssuanceStoredContextTO.from(this, null)).toByteArray()
+
+internal fun ByteArray.toDeferredIssuanceContext(): DeferredIssuanceContext {
+ return json.decodeFromString(DeferredIssuanceStoredContextTO.serializer(), String(this))
+ .toDeferredIssuanceStoredContext(Clock.systemUTC(), null)
+}
+//
+// Serialization
+//
+
+@Serializable
+private data class RefreshTokenTO(
+ @Required @SerialName("refresh_token") val refreshToken: String,
+ @SerialName("expires_in") val expiresIn: Long? = null,
+) {
+
+ fun toRefreshToken(): RefreshToken {
+ val exp = expiresIn?.let { Duration.ofMillis(it) }
+ return RefreshToken(refreshToken, exp)
+ }
+
+ companion object {
+
+ fun from(refreshToken: RefreshToken): RefreshTokenTO =
+ RefreshTokenTO(refreshToken.refreshToken, refreshToken.expiresIn?.toMillis())
+ }
+}
+
+@Serializable
+private enum class AccessTokenTypeTO {
+ DPoP, Bearer
+}
+
+@Serializable
+private data class AccessTokenTO(
+ @Required @SerialName("type") val type: AccessTokenTypeTO,
+ @Required @SerialName("access_token") val accessToken: String,
+ @SerialName("expires_in") val expiresIn: Long? = null,
+) {
+
+ fun toAccessToken(): AccessToken {
+ val exp = expiresIn?.let { Duration.ofMillis(it) }
+ return when (type) {
+ AccessTokenTypeTO.DPoP -> AccessToken.DPoP(accessToken, exp)
+ AccessTokenTypeTO.Bearer -> AccessToken.Bearer(accessToken, exp)
+ }
+ }
+
+ companion object {
+
+ fun from(accessToken: AccessToken): AccessTokenTO {
+ return AccessTokenTO(
+ type = when (accessToken) {
+ is AccessToken.DPoP -> AccessTokenTypeTO.DPoP
+ is AccessToken.Bearer -> AccessTokenTypeTO.Bearer
+ },
+ accessToken = accessToken.accessToken,
+ expiresIn = accessToken.expiresIn?.toMillis(),
+ )
+ }
+ }
+}
+
+@Serializable
+private data class DeferredIssuanceStoredContextTO(
+ @Required @SerialName("client_id") val clientId: String,
+ @Required @SerialName("deferred_endpoint") val deferredEndpoint: String,
+ @Required @SerialName("token_endpoint") val tokenEndpoint: String,
+ @SerialName("dpop_key_id") val dPoPSignerKid: String? = null,
+ @SerialName("credential_response_encryption_spec") val responseEncryptionSpec: JsonObject? = null,
+ @SerialName("transaction_id") val transactionId: String,
+ @SerialName("access_token") val accessToken: AccessTokenTO,
+ @SerialName("refresh_token") val refreshToken: RefreshTokenTO? = null,
+ @SerialName("authorization_timestamp") val authorizationTimestamp: Long,
+) {
+
+ fun toDeferredIssuanceStoredContext(
+ clock: Clock,
+ recreatePopSigner: ((String) -> PopSigner.Jwt)?,
+ ): DeferredIssuanceContext {
+ return DeferredIssuanceContext(
+ config = DeferredIssuerConfig(
+ clock = clock,
+ clientId = clientId,
+ deferredEndpoint = URL(deferredEndpoint),
+ tokenEndpoint = URL(tokenEndpoint),
+ dPoPSigner = dPoPSignerKid?.let { requireNotNull(recreatePopSigner).invoke(it) },
+ responseEncryptionSpec = responseEncryptionSpec?.let { responseEncryption(it) },
+ ),
+ authorizedTransaction = AuthorizedTransaction(
+ authorizedRequest = AuthorizedRequest.NoProofRequired(
+ accessToken = accessToken.toAccessToken(),
+ refreshToken = refreshToken?.toRefreshToken(),
+ credentialIdentifiers = emptyMap(),
+ timestamp = Instant.ofEpochSecond(authorizationTimestamp),
+ ),
+ transactionId = TransactionId(transactionId),
+ ),
+
+ )
+ }
+
+ companion object {
+ fun from(
+ dCtx: DeferredIssuanceContext,
+ dPoPSignerKid: String?,
+ ): DeferredIssuanceStoredContextTO {
+ val authorizedTransaction = dCtx.authorizedTransaction
+ return DeferredIssuanceStoredContextTO(
+ clientId = dCtx.config.clientId,
+ deferredEndpoint = dCtx.config.deferredEndpoint.toString(),
+ tokenEndpoint = dCtx.config.tokenEndpoint.toString(),
+ dPoPSignerKid = dPoPSignerKid,
+ responseEncryptionSpec = dCtx.config.responseEncryptionSpec?.let { responseEncryptionSpecTO(it) },
+ transactionId = authorizedTransaction.transactionId.value,
+ accessToken = AccessTokenTO.from(authorizedTransaction.authorizedRequest.accessToken),
+ refreshToken = authorizedTransaction.authorizedRequest.refreshToken?.let { RefreshTokenTO.from(it) },
+ authorizationTimestamp = authorizedTransaction.authorizedRequest.timestamp.epochSecond,
+ )
+ }
+
+ private fun responseEncryptionSpecTO(spec: IssuanceResponseEncryptionSpec): JsonObject {
+ val jwkJson = Json.parseToJsonElement(spec.jwk.toJSONString())
+ return buildJsonObject {
+ put("jwk", jwkJson)
+ put("algorithm", spec.algorithm.toString())
+ put("encryption_method", spec.encryptionMethod.toString())
+ }
+ }
+
+ private fun responseEncryption(specTO: JsonObject): IssuanceResponseEncryptionSpec =
+ IssuanceResponseEncryptionSpec(
+ jwk = run {
+ val element = specTO["jwk"]
+ require(element is JsonObject)
+ JWK.parse(element.toString())
+ },
+ algorithm = run {
+ val element = specTO["algorithm"]
+ require(element is JsonPrimitive)
+ JWEAlgorithm.parse(requireNotNull(element.contentOrNull))
+ },
+ encryptionMethod = run {
+ val element = specTO["encryption_method"]
+ require(element is JsonPrimitive)
+ EncryptionMethod.parse(requireNotNull(element.contentOrNull))
+ },
+ )
+ }
+}
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredIssueResult.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredIssueResult.kt
new file mode 100644
index 00000000..63f34062
--- /dev/null
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredIssueResult.kt
@@ -0,0 +1,47 @@
+/*
+ * 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 eu.europa.ec.eudi.wallet.document.DocumentId
+
+sealed interface DeferredIssueResult : OpenId4VciResult {
+ /**
+ * Document issued successfully.
+ * @property documentId the id of the issued document
+ * @property name the name of the document
+ * @property docType the document type
+ * @see[DocumentId] for the document id
+ */
+ data class DocumentIssued(val documentId: DocumentId, val name: String, val docType: String) : DeferredIssueResult
+
+ /**
+ * Document issuance failed.
+ * @property name the name of the document
+ * @property docType the document type
+ * @property cause the error that caused the failure
+ */
+ data class DocumentFailed(val documentId: DocumentId, override val cause: Throwable) : DeferredIssueResult,
+ OpenId4VciResult.Erroneous
+
+ /**
+ * Document issuance deferred.
+ * @property documentId the id of the deferred document
+ * @property name the name of the document
+ * @property docType the document type
+ */
+ data class DocumentNotReady(val documentId: DocumentId, val name: String, val docType: String) : DeferredIssueResult
+}
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredState.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredState.kt
deleted file mode 100644
index ee6b10a6..00000000
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredState.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 eu.europa.ec.eudi.openid4vci.AuthorizedRequest
-import eu.europa.ec.eudi.openid4vci.CredentialIssuerMetadata
-import eu.europa.ec.eudi.openid4vci.IssuedCredential
-import eu.europa.ec.eudi.openid4vci.Issuer
-import eu.europa.ec.eudi.wallet.transfer.openid4vp.ClientId
-import java.io.*
-import java.net.URI
-
-internal data class DeferredState(
- val clientId: ClientId,
- val tokenEndpoint: URI,
- val credentialIssuerMetadata: CredentialIssuerMetadata,
- val authorizedRequest: AuthorizedRequest,
- val deferredCredential: IssuedCredential.Deferred? = null,
-) : Serializable {
-
- val version = VERSION
-
- constructor(clientId: ClientId, issuer: Issuer, authorizedRequest: AuthorizedRequest) : this(
- clientId = clientId,
- tokenEndpoint = issuer.credentialOffer.authorizationServerMetadata.tokenEndpointURI,
- credentialIssuerMetadata = issuer.credentialOffer.credentialIssuerMetadata,
- authorizedRequest = authorizedRequest,
- deferredCredential = null
- )
-
- fun encode(): ByteArray {
- return ByteArrayOutputStream().use { baos ->
- ObjectOutputStream(baos).use { oos ->
- oos.writeObject(this)
- oos.flush()
- baos.toByteArray()
- }
- }
- }
-
-
- companion object {
- const val VERSION = 1L
- fun decode(encoded: ByteArray): DeferredState {
- return ByteArrayInputStream(encoded).use { bais ->
- ObjectInputStream(bais).use { ois ->
- val obj = ois.readObject()
- if (obj is DeferredState) obj
- else throw IllegalArgumentException("Invalid object type")
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
index de24147c..2ed5cf9d 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
@@ -18,14 +18,14 @@
package eu.europa.ec.eudi.wallet.issue.openid4vci
import androidx.biometric.BiometricPrompt.CryptoObject
-import eu.europa.ec.eudi.openid4vci.SubmittedRequest
+import eu.europa.ec.eudi.openid4vci.SubmissionOutcome
/**
* Exception thrown when user authentication is required.
*/
internal class UserAuthRequiredException(
val cryptoObject: CryptoObject?,
- val resume: suspend (Boolean) -> SubmittedRequest
+ val resume: suspend (Boolean) -> SubmissionOutcome,
) : Throwable()
/**
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssueEvent.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssueEvent.kt
index 432197bb..af40caf9 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssueEvent.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssueEvent.kt
@@ -167,8 +167,6 @@ sealed interface IssueEvent : OpenId4VciResult {
companion object {
internal fun failure(e: Throwable) = Failure(e)
- internal fun documentIssued(unsignedDocument: UnsignedDocument) =
- DocumentIssued(unsignedDocument.id, unsignedDocument.name, unsignedDocument.docType)
internal fun documentFailed(unsignedDocument: UnsignedDocument, cause: Throwable) =
DocumentFailed(
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt
index 53eeaf54..e04d26ec 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt
@@ -54,7 +54,8 @@ internal class IssuerAuthorization(
close() // close any previous suspensions
return with(issuer) {
when {
- !txCode.isNullOrEmpty() -> authorizeWithPreAuthorizationCode(txCode)
+ isPreAuthorized() -> authorizeWithPreAuthorizationCode(txCode)
+
else -> {
val prepareAuthorizationCodeRequest = prepareAuthorizationRequest().getOrThrow()
val authResponse = openBrowserForAuthorization(prepareAuthorizationCodeRequest).getOrThrow()
@@ -123,4 +124,12 @@ internal class IssuerAuthorization(
}
data class Response(val authorizationCode: String, val serverState: String)
+
+ companion object {
+ /**
+ * Checks if the issuer's credential offer is pre-authorized.
+ * @receiver The issuer to check.
+ */
+ fun Issuer.isPreAuthorized(): Boolean = credentialOffer.grants?.preAuthorizedCode() != null
+ }
}
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt
index 3a27865b..1e50ad5f 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt
@@ -15,10 +15,8 @@
*/
package eu.europa.ec.eudi.wallet.issue.openid4vci
-import eu.europa.ec.eudi.openid4vci.CredentialConfiguration
-import eu.europa.ec.eudi.openid4vci.CredentialConfigurationIdentifier
-import eu.europa.ec.eudi.openid4vci.TxCode
-import eu.europa.ec.eudi.openid4vci.TxCodeInputMode
+import eu.europa.ec.eudi.wallet.issue.openid4vci.Offer.TxCodeSpec.InputMode.NUMERIC
+import eu.europa.ec.eudi.wallet.issue.openid4vci.Offer.TxCodeSpec.InputMode.TEXT
/**
* An offer of credentials to be issued.
@@ -55,7 +53,7 @@ interface Offer {
* @property description a description of the transaction code
*/
data class TxCodeSpec(
- val inputMode: InputMode = InputMode.NUMERIC,
+ val inputMode: InputMode = NUMERIC,
val length: Int?,
val description: String? = null,
) {
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManager.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManager.kt
index e741b79e..189c8406 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManager.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/OpenId4VciManager.kt
@@ -88,12 +88,12 @@ interface OpenId4VciManager {
* @param deferredDocument the deferred document to issue
* @param executor the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread
* @param onIssueEvent the callback to be called when the document is issued
- * @see[IssueEvent] on how to handle the result
+ * @see[OnDeferredIssueResult] on how to handle the result
*/
fun issueDeferredDocument(
deferredDocument: DeferredDocument,
executor: Executor?,
- onIssueEvent: OnIssueEvent,
+ onIssueEvent: OnDeferredIssueResult,
)
/**
@@ -150,6 +150,11 @@ interface OpenId4VciManager {
*/
fun interface OnResolvedOffer : OnResult
+ /**
+ * Callback to be called when a deferred document is issued
+ */
+ fun interface OnDeferredIssueResult : OnResult
+
/**
* Builder to create an instance of [OpenId4VciManager]
* @param context the context
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessDeferredOutcome.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessDeferredOutcome.kt
new file mode 100644
index 00000000..a92b4f0d
--- /dev/null
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessDeferredOutcome.kt
@@ -0,0 +1,105 @@
+/*
+ * 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 eu.europa.ec.eudi.openid4vci.DeferredCredentialQueryOutcome
+import eu.europa.ec.eudi.openid4vci.DeferredIssuanceContext
+import eu.europa.ec.eudi.wallet.document.DeferredDocument
+import eu.europa.ec.eudi.wallet.document.DocumentManager
+import eu.europa.ec.eudi.wallet.document.StoreDocumentResult
+import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.Companion.TAG
+import eu.europa.ec.eudi.wallet.logging.Logger
+import org.bouncycastle.util.encoders.Hex
+import java.util.*
+
+internal class ProcessDeferredOutcome(
+ val documentManager: DocumentManager,
+ val callback: OpenId4VciManager.OnResult,
+ val deferredIssuanceContext: DeferredIssuanceContext?,
+ val logger: Logger? = null,
+) {
+
+ fun process(deferredDocument: DeferredDocument, outcome: DeferredCredentialQueryOutcome) {
+ try {
+ when (outcome) {
+ is DeferredCredentialQueryOutcome.Errored -> {
+ documentManager.deleteDocumentById(deferredDocument.id)
+ callback(
+ DeferredIssueResult.DocumentFailed(
+ deferredDocument.id,
+ IllegalStateException(outcome.error)
+ )
+ )
+ }
+
+ is DeferredCredentialQueryOutcome.IssuancePending -> {
+ deferredIssuanceContext?.let { ctx ->
+ documentManager.storeDeferredDocument(deferredDocument, ctx.toByteArray())
+ .notifyListener(deferredDocument, true)
+ } ?: callback(
+ DeferredIssueResult.DocumentNotReady(
+ deferredDocument.id,
+ deferredDocument.name,
+ deferredDocument.docType
+ )
+ )
+ }
+
+ is DeferredCredentialQueryOutcome.Issued -> {
+ val cborBytes = Base64.getUrlDecoder().decode(outcome.credential.credential)
+ logger?.d(TAG, "CBOR bytes: ${Hex.toHexString(cborBytes)}")
+ documentManager.storeIssuedDocument(deferredDocument, cborBytes)
+ .notifyListener(deferredDocument)
+ }
+ }
+ } catch (e: Throwable) {
+ documentManager.deleteDocumentById(deferredDocument.id)
+ callback(DeferredIssueResult.DocumentFailed(deferredDocument.id, e))
+ }
+ }
+
+
+ private fun StoreDocumentResult.notifyListener(deferredDocument: DeferredDocument, isDeferred: Boolean = false) =
+ when (this) {
+ is StoreDocumentResult.Success -> {
+ if (isDeferred) {
+ callback(
+ DeferredIssueResult.DocumentNotReady(
+ documentId,
+ deferredDocument.name,
+ deferredDocument.docType
+ )
+ )
+ } else {
+ callback(
+ DeferredIssueResult.DocumentIssued(
+ documentId,
+ deferredDocument.name,
+ deferredDocument.docType
+ )
+ )
+ }
+ }
+
+ is StoreDocumentResult.Failure -> {
+ documentManager.deleteDocumentById(deferredDocument.id)
+ callback(
+ DeferredIssueResult.DocumentFailed(deferredDocument.id, throwable)
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessResponse.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessResponse.kt
index 5e779439..c7a0d5b9 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessResponse.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessResponse.kt
@@ -23,12 +23,12 @@ import eu.europa.ec.eudi.wallet.document.DocumentManager
import eu.europa.ec.eudi.wallet.document.StoreDocumentResult
import eu.europa.ec.eudi.wallet.document.UnsignedDocument
import eu.europa.ec.eudi.wallet.issue.openid4vci.IssueEvent.Companion.documentFailed
-import eu.europa.ec.eudi.wallet.issue.openid4vci.IssueEvent.Companion.documentIssued
import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.Companion.TAG
import eu.europa.ec.eudi.wallet.logging.Logger
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.serialization.json.Json
import org.bouncycastle.util.encoders.Hex
import java.io.Closeable
import java.util.*
@@ -36,12 +36,16 @@ import kotlin.coroutines.resume
internal class ProcessResponse(
val documentManager: DocumentManager,
+ val deferredContextCreator: DeferredContextCreator,
val listener: OpenId4VciManager.OnResult,
val issuedDocumentIds: MutableList,
- val deferredState: DeferredState,
val logger: Logger? = null,
) : Closeable {
private val continuations = mutableMapOf>()
+ private val json = Json {
+ encodeDefaults = true
+ ignoreUnknownKeys = true
+ }
suspend fun process(response: SubmitRequest.Response) {
response.forEach { (unsignedDocument, result) ->
@@ -86,11 +90,9 @@ internal class ProcessResponse(
}
is IssuedCredential.Deferred -> {
- val state = deferredState.copy(
- deferredCredential = credential
- ).encode()
- documentManager.storeDeferredDocument(unsignedDocument, state)
- .notifyListener(unsignedDocument)
+ val contextToStore = deferredContextCreator.create(credential)
+ documentManager.storeDeferredDocument(unsignedDocument, contextToStore.toByteArray())
+ .notifyListener(unsignedDocument, isDeferred = true)
}
}
@@ -122,15 +124,20 @@ internal class ProcessResponse(
)
}
- private fun StoreDocumentResult.notifyListener(unsignedDocument: UnsignedDocument) = when (this) {
- is StoreDocumentResult.Success -> {
- issuedDocumentIds.add(documentId)
- listener(documentIssued(unsignedDocument))
- }
+ private fun StoreDocumentResult.notifyListener(unsignedDocument: UnsignedDocument, isDeferred: Boolean = false) =
+ when (this) {
+ is StoreDocumentResult.Success -> {
+ issuedDocumentIds.add(documentId)
+ if (isDeferred) {
+ listener(IssueEvent.DocumentDeferred(documentId, unsignedDocument.name, unsignedDocument.docType))
+ } else {
+ listener(IssueEvent.DocumentIssued(documentId, unsignedDocument.name, unsignedDocument.docType))
+ }
+ }
- is StoreDocumentResult.Failure -> {
- documentManager.deleteDocumentById(unsignedDocument.id)
- listener(documentFailed(unsignedDocument, throwable))
+ is StoreDocumentResult.Failure -> {
+ documentManager.deleteDocumentById(unsignedDocument.id)
+ listener(documentFailed(unsignedDocument, throwable))
+ }
}
- }
}
\ No newline at end of file
diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredStateTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredStateTest.kt
deleted file mode 100644
index c485015d..00000000
--- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DeferredStateTest.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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 com.nimbusds.jose.JWSAlgorithm
-import eu.europa.ec.eudi.openid4vci.*
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import java.net.URI
-import java.time.Instant
-import java.util.*
-
-class DeferredStateTest {
-
- @Test
- fun `test encode and decode methods`() {
- val deferredCredential = IssuedCredential.Deferred(
- transactionId = TransactionId("transactionId"),
- )
- val credentialIdentifiers = mapOf(
- CredentialConfigurationIdentifier("credentialConfigurationId") to listOf(
- CredentialIdentifier("credentialId")
- )
- )
- val authorizedRequest = AuthorizedRequest.ProofRequired(
- accessToken = AccessToken(accessToken = "accessToken", expiresInSec = 3600, useDPoP = false),
- refreshToken = RefreshToken("refreshToken", expiresInSec = 3600),
- cNonce = CNonce(value = "cNonce"),
- credentialIdentifiers = credentialIdentifiers,
- timestamp = Instant.now()
- )
-
- val credentialIssuerMetadata = CredentialIssuerMetadata(
- credentialIssuerIdentifier = CredentialIssuerId("https://localhost:8080").getOrThrow(),
- authorizationServers = listOf(HttpsUrl("https://localhost:8080").getOrThrow()),
- credentialEndpoint = CredentialIssuerEndpoint("https://localhost:8080").getOrThrow(),
- batchCredentialEndpoint = CredentialIssuerEndpoint("https://localhost:8080").getOrThrow(),
- deferredCredentialEndpoint = CredentialIssuerEndpoint("https://localhost:8080").getOrThrow(),
- notificationEndpoint = CredentialIssuerEndpoint("https://localhost:8080").getOrThrow(),
- credentialResponseEncryption = CredentialResponseEncryption.NotSupported,
- credentialIdentifiersSupported = true,
- credentialConfigurationsSupported = mapOf(
- CredentialConfigurationIdentifier("credentialConfigurationId") to MsoMdocCredential(
- credentialSigningAlgorithmsSupported = listOf("alg"),
- isoCredentialSigningAlgorithmsSupported = listOf(CoseAlgorithm.ES256),
- isoCredentialCurvesSupported = listOf(CoseCurve.P_256),
- proofTypesSupported = ProofTypesSupported(
- setOf(
- ProofTypeMeta.Jwt(listOf(JWSAlgorithm.ES256)),
- ProofTypeMeta.Cwt(listOf(CoseAlgorithm.ES256), listOf(CoseCurve.P_256))
- )
- ),
- display = listOf(
- Display(
- name = "name",
- locale = Locale.US,
- logo = Display.Logo(URI("http://localhost:8080"), "image/png"),
- textColor = "#444444"
- )
- ),
- claims = mapOf(
- "namespace" to mapOf(
- "claim" to Claim(
- true, "claim", listOf(
- Claim.Display("name", Locale.US)
- )
- )
- )
- ),
- order = listOf("claim"),
- docType = "docType",
- isoPolicy = MsoMdocPolicy(true, 10),
- scope = "scope",
- cryptographicBindingMethodsSupported = listOf(CryptographicBindingMethod.JWK),
- )
- ),
- display = listOf(
- CredentialIssuerMetadata.Display(name = "name", locale = "el_GR")
- ),
- )
- val state = DeferredState(
- clientId = "clientId",
- tokenEndpoint = URI("http://localhost:8080"),
- credentialIssuerMetadata = credentialIssuerMetadata,
- authorizedRequest = authorizedRequest,
- deferredCredential = deferredCredential
- )
-
- val encoded = state.encode()
-
- val decoded = DeferredState.decode(encoded)
-
- assertEquals(state, decoded)
-
- }
-}
\ No newline at end of file
diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorizationTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorizationTest.kt
index 05bb4ad8..fe3b4116 100644
--- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorizationTest.kt
+++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorizationTest.kt
@@ -19,10 +19,7 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci
import android.content.Context
import android.content.Intent
import android.net.Uri
-import eu.europa.ec.eudi.openid4vci.AuthorizationRequestPrepared
-import eu.europa.ec.eudi.openid4vci.AuthorizedRequest
-import eu.europa.ec.eudi.openid4vci.HttpsUrl
-import eu.europa.ec.eudi.openid4vci.Issuer
+import eu.europa.ec.eudi.openid4vci.*
import eu.europa.ec.eudi.wallet.logging.Logger
import io.mockk.*
import kotlinx.coroutines.Dispatchers
@@ -43,7 +40,6 @@ class IssuerAuthorizationTest {
lateinit var logger: Logger
lateinit var issuer: Issuer
-
@BeforeAll
@JvmStatic
fun setup() {
@@ -54,9 +50,6 @@ class IssuerAuthorizationTest {
mockkConstructor(Intent::class)
every { anyConstructed().addFlags(any()) } returns mockk(relaxed = true)
- issuer = mockk(relaxed = true)
-
-
context = mockk(relaxed = true)
logger = mockk(relaxed = true)
}
@@ -72,8 +65,8 @@ class IssuerAuthorizationTest {
preparedAuthorizationRequest.authorizationCodeURL
} returns HttpsUrl("https://test.com").getOrThrow()
+ issuer = mockk(relaxed = true)
authorizedRequest = mockk(relaxed = true)
-
coEvery {
issuer.prepareAuthorizationRequest()
} returns Result.success(preparedAuthorizationRequest)
@@ -90,8 +83,12 @@ class IssuerAuthorizationTest {
}
@Test
- fun `authorize method when txCode equals to null call openBrowserForAuthorization`() {
-
+ fun `authorize method when no preAuthorizedCode in offer and txCode is null calls openBrowserForAuthorization`() {
+ every { issuer.credentialOffer } returns mockk(relaxed = true) {
+ every { grants } returns mockk(relaxed = true) {
+ every { preAuthorizedCode() } returns null
+ }
+ }
val issuerAuthorization = spyk(IssuerAuthorization(context, logger))
runTest {
launch {
@@ -109,12 +106,21 @@ class IssuerAuthorizationTest {
}
@Test
- fun `authorize method when passing txCode does not call openBrowserForAuthorization but calls authorizeWithPreAuthorizationCode`() {
-
+ fun `authorize method when preAuthorizedCode in offer and passing txCode does not call openBrowserForAuthorization but calls authorizeWithPreAuthorizationCode`() {
+ every { issuer.credentialOffer } returns mockk(relaxed = true) {
+ every { grants } returns mockk(relaxed = true) {
+ every { preAuthorizedCode() } returns mockk(relaxed = true) {
+ every { txCode } returns mockk(relaxed = true) {
+ every { length } returns 4
+ every { inputMode } returns TxCodeInputMode.NUMERIC
+ }
+ }
+ }
+ }
val issuerAuthorization = spyk(IssuerAuthorization(context, logger))
runTest {
launch {
- issuerAuthorization.authorize(issuer, "testCode")
+ issuerAuthorization.authorize(issuer, "1234")
}
launch {
delay(500.milliseconds)
@@ -126,7 +132,7 @@ class IssuerAuthorizationTest {
issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest)
}
coVerify(exactly = 1) {
- issuer.authorizeWithPreAuthorizationCode("testCode")
+ issuer.authorizeWithPreAuthorizationCode("1234")
}
}