diff --git a/README.md b/README.md index 733c65e9..45546a9a 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,13 @@ The library provides the following functionality: - Document issuance - [x] Support for OpenId4VCI Draft 13 document issuance - [x] Authorization Code Flow - - [ ] Pre-authorization Code Flow + - [x] Pre-authorization Code Flow - [x] Support for mso_mdoc format - [ ] Support for sd-jwt-vc format - - [x] Support credential offer - - [x] Support for DPoP JWT in authorization - - [x] Support for JWT and CWT proof types + - [x] Support credential offer + - [x] Support for DPoP JWT in authorization + - [x] Support for JWT and CWT proof types + - [ ] Support for deferred issuing - Proximity document presentation - [x] Support for ISO-18013-5 device retrieval - [x] QR device engagement @@ -454,6 +455,7 @@ EudiWallet.resolveDocumentOffer(offerUri) { result -> // display the offer's data to the user val issuerName = offer.issuerName val offeredDocuments: List = offer.offeredDocuments + val txCodeSpec: Offer.TxCodeSpec? = offer.txCodeSpec // information about pre-authorized flow // ... } is OfferResult.Failure -> { @@ -546,11 +548,23 @@ val onIssueEvent = OnIssueEvent { event -> } } -EudiWallet.issueDocumentByDocType("eu.europa.ec.eudiw.pid.1", onIssueEvent) +EudiWallet.issueDocumentByDocType( + docType = "eu.europa.ec.eudiw.pid.1", + txCode = "", // if transaction code is provided + onEvent = onIssueEvent +) // or -EudiWallet.issueDocumentByOfferUri("https://issuer.com/?credential_offer=...", onIssueEvent) +EudiWallet.issueDocumentByOfferUri( + offerUri = "https://issuer.com/?credential_offer=...", + txCode = "", // if transaction code is provided + onEvent = onIssueEvent +) // or given a resolved offer object -EudiWallet.issueDocumentByOffer(offer, onIssueEvent) +EudiWallet.issueDocumentByOffer( + offer = offer, + txCode = "", // if transaction code is provided + onEvent = onIssueEvent +) ``` There's also available for `issueDocumentByDocType`, `issueDocumentByOfferUri` and `issueDocumentByOffer` methods to @@ -559,7 +573,10 @@ If the `executor` parameter is null, the callback will be executed on the main t ```kotlin val executor = Executors.newSingleThreadExecutor() -EudiWallet.issueDocumentByDocType("eu.europa.ec.eudiw.pid.1", executor) { event -> +EudiWallet.issueDocumentByDocType( + docType = "eu.europa.ec.eudiw.pid.1", + executor = executor +) { event -> // ... } ``` @@ -578,8 +595,8 @@ Also, the redirect uri declared in the OpenId4VCI configuration must be declared + android:name=".MainActivity" + android:exported="true"> @@ -621,6 +638,25 @@ class SomeActivity : AppCompatActivity() { } ``` +##### 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: + +- The input mode, whether it is NUMERIC or TEXT +- The expected length of the input +- The description of the input + +From the user's perspective, the application must provide a way to input the transaction code. + +When the transaction code is provided, the issuance process can be resumed by calling any of the following methods: + +- `EudiWallet.issueDocumentByDocType` +- `EudiWallet.issueDocumentByOfferUri` +- `EudiWallet.issueDocumentByOffer` + +passing the transaction code as in the `txCode` parameter. + ### Transfer documents The library supports the following 3 ways to transfer documents: diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/as-pair.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/as-pair.md index 7a9e268c..2851fe17 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/as-pair.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/as-pair.md @@ -3,7 +3,7 @@ # asPair [androidJvm]\ -fun [asPair](as-pair.md)(): [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html) +open fun [asPair](as-pair.md)(): [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html) <[String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), [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/-offer/-offered-document/doc-type.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/doc-type.md index 4f511a53..8a5c9e36 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/doc-type.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/doc-type.md @@ -3,4 +3,4 @@ # docType [androidJvm]\ -val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) +abstract 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/-offer/-offered-document/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/index.md index f1518195..bf7f6e06 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/index.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/index.md @@ -3,20 +3,19 @@ # OfferedDocument [androidJvm]\ -data class [OfferedDocument](index.md) +interface [OfferedDocument](index.md) An item to be issued. ## Functions -| Name | Summary | -|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [asPair](as-pair.md) | [androidJvm]
fun [asPair](as-pair.md)(): [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)<[String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)>
Converts this item to a pair of name and document type. | -| [toString](to-string.md) | [androidJvm]
open override fun [toString](to-string.md)(): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| Name | Summary | +|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [asPair](as-pair.md) | [androidJvm]
open fun [asPair](as-pair.md)(): [Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)<[String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)>
Converts this item to a pair of name and document type. | ## 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 of the item | -| [name](name.md) | [androidJvm]
val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the name of the item | +| Name | Summary | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [docType](doc-type.md) | [androidJvm]
abstract val [docType](doc-type.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the document type of the item | +| [name](name.md) | [androidJvm]
abstract val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the name of the item | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/name.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/name.md index a15bc8c7..77ab07a6 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/name.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/name.md @@ -3,4 +3,4 @@ # name [androidJvm]\ -val [name](name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) +abstract 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/-offer/-offered-document/to-string.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/to-string.md deleted file mode 100644 index 340daca1..00000000 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/to-string.md +++ /dev/null @@ -1,7 +0,0 @@ -//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[OfferedDocument](index.md)/[toString](to-string.md) - -# toString - -[androidJvm]\ -open override -fun [toString](to-string.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/-offer/-tx-code-spec/-input-mode/-n-u-m-e-r-i-c/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-n-u-m-e-r-i-c/index.md new file mode 100644 index 00000000..70d65dd1 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-n-u-m-e-r-i-c/index.md @@ -0,0 +1,13 @@ +//[wallet-core](../../../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../../../index.md)/[Offer](../../../index.md)/[TxCodeSpec](../../index.md)/[InputMode](../index.md)/[NUMERIC](index.md) + +# NUMERIC + +[androidJvm]\ +[NUMERIC](index.md) + +## Properties + +| Name | Summary | +|-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [name](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946) | [androidJvm]
val [name](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [ordinal](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946) | [androidJvm]
val [ordinal](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946): [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-t-e-x-t/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-t-e-x-t/index.md new file mode 100644 index 00000000..3dc2a372 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-t-e-x-t/index.md @@ -0,0 +1,13 @@ +//[wallet-core](../../../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../../../index.md)/[Offer](../../../index.md)/[TxCodeSpec](../../index.md)/[InputMode](../index.md)/[TEXT](index.md) + +# TEXT + +[androidJvm]\ +[TEXT](index.md) + +## Properties + +| Name | Summary | +|-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [name](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946) | [androidJvm]
val [name](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [ordinal](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946) | [androidJvm]
val [ordinal](../../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946): [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/index.md new file mode 100644 index 00000000..28618a53 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/index.md @@ -0,0 +1,30 @@ +//[wallet-core](../../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../../index.md)/[Offer](../../index.md)/[TxCodeSpec](../index.md)/[InputMode](index.md) + +# InputMode + +[androidJvm]\ +enum [InputMode](index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html) +<[Offer.TxCodeSpec.InputMode](index.md)> + +The input mode for the transaction code. + +## Entries + +| | | +|------------------------------------|----------------------------------------------------| +| [NUMERIC](-n-u-m-e-r-i-c/index.md) | [androidJvm]
[NUMERIC](-n-u-m-e-r-i-c/index.md) | +| [TEXT](-t-e-x-t/index.md) | [androidJvm]
[TEXT](-t-e-x-t/index.md) | + +## Functions + +| Name | Summary | +|------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [valueOf](value-of.md) | [androidJvm]
fun [valueOf](value-of.md)(value: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)): [Offer.TxCodeSpec.InputMode](index.md)
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) | +| [values](values.md) | [androidJvm]
fun [values](values.md)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[Offer.TxCodeSpec.InputMode](index.md)>
Returns an array containing the constants of this enum type, in the order they're declared. | + +## Properties + +| Name | Summary | +|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [name](../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946) | [androidJvm]
val [name](../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-372974862%2FProperties%2F1615067946): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | +| [ordinal](../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946) | [androidJvm]
val [ordinal](../../../-open-id4-vci-manager/-config/-proof-type/-c-w-t/index.md#-739389684%2FProperties%2F1615067946): [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html) | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/value-of.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/value-of.md new file mode 100644 index 00000000..0c761560 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/value-of.md @@ -0,0 +1,16 @@ +//[wallet-core](../../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../../index.md)/[Offer](../../index.md)/[TxCodeSpec](../index.md)/[InputMode](index.md)/[valueOf](value-of.md) + +# valueOf + +[androidJvm]\ +fun [valueOf](value-of.md)( +value: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)): [Offer.TxCodeSpec.InputMode](index.md) + +Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to +declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) + +#### Throws + +| | | +|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| [IllegalArgumentException](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-argument-exception/index.html) | if this enum type has no constant with the specified name | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/values.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/values.md new file mode 100644 index 00000000..e3932a49 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/values.md @@ -0,0 +1,11 @@ +//[wallet-core](../../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../../index.md)/[Offer](../../index.md)/[TxCodeSpec](../index.md)/[InputMode](index.md)/[values](values.md) + +# values + +[androidJvm]\ +fun [values](values.md)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html) +<[Offer.TxCodeSpec.InputMode](index.md)> + +Returns an array containing the constants of this enum type, in the order they're declared. + +This method may be used to iterate over the constants. 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 new file mode 100644 index 00000000..f98d9408 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md @@ -0,0 +1,8 @@ +//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[TxCodeSpec](index.md)/[TxCodeSpec](-tx-code-spec.md) + +# TxCodeSpec + +[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) diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/description.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/description.md new file mode 100644 index 00000000..f8fd47ec --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/description.md @@ -0,0 +1,7 @@ +//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[TxCodeSpec](index.md)/[description](description.md) + +# description + +[androidJvm]\ +val [description](description.md): [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 new file mode 100644 index 00000000..2c8ff9ca --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md @@ -0,0 +1,30 @@ +//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[TxCodeSpec](index.md) + +# 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 +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) | + +## Types + +| Name | Summary | +|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [InputMode](-input-mode/index.md) | [androidJvm]
enum [InputMode](-input-mode/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[Offer.TxCodeSpec.InputMode](-input-mode/index.md)>
The input mode for the transaction code. | + +## Properties + +| Name | Summary | +|-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [description](description.md) | [androidJvm]
val [description](description.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? = null
a description of the transaction code | +| [inputMode](input-mode.md) | [androidJvm]
val [inputMode](input-mode.md): [Offer.TxCodeSpec.InputMode](-input-mode/index.md)
the input mode for the transaction code | +| [length](length.md) | [androidJvm]
val [length](length.md): [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)?
the length of the transaction code | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/input-mode.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/input-mode.md new file mode 100644 index 00000000..aeac9f3f --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/input-mode.md @@ -0,0 +1,6 @@ +//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[TxCodeSpec](index.md)/[inputMode](input-mode.md) + +# inputMode + +[androidJvm]\ +val [inputMode](input-mode.md): [Offer.TxCodeSpec.InputMode](-input-mode/index.md) diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/length.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/length.md new file mode 100644 index 00000000..e5446d67 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/length.md @@ -0,0 +1,6 @@ +//[wallet-core](../../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../../index.md)/[Offer](../index.md)/[TxCodeSpec](index.md)/[length](length.md) + +# length + +[androidJvm]\ +val [length](length.md): [Int](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html)? 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 9a47285c..ef8c770f 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,9 +9,10 @@ An offer of credentials to be issued. ## Types -| Name | Summary | -|-----------------------------------------------|---------------------------------------------------------------------------------------------------| -| [OfferedDocument](-offered-document/index.md) | [androidJvm]
data class [OfferedDocument](-offered-document/index.md)
An item to be issued. | +| 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. | ## Properties @@ -19,3 +20,4 @@ An offer of credentials to be issued. |------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [issuerName](issuer-name.md) | [androidJvm]
abstract val [issuerName](issuer-name.md): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)
the name of the issuer | | [offeredDocuments](offered-documents.md) | [androidJvm]
abstract val [offeredDocuments](offered-documents.md): [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)<[Offer.OfferedDocument](-offered-document/index.md)>
the items to be issued | +| [txCodeSpec](tx-code-spec.md) | [androidJvm]
abstract val [txCodeSpec](tx-code-spec.md): [Offer.TxCodeSpec](-tx-code-spec/index.md)?
the specification for the transaction code | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/tx-code-spec.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/tx-code-spec.md new file mode 100644 index 00000000..81e10592 --- /dev/null +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/tx-code-spec.md @@ -0,0 +1,6 @@ +//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[Offer](index.md)/[txCodeSpec](tx-code-spec.md) + +# txCodeSpec + +[androidJvm]\ +abstract val [txCodeSpec](tx-code-spec.md): [Offer.TxCodeSpec](-tx-code-spec/index.md)? 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 9f856e20..4344b457 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 @@ -29,8 +29,8 @@ documents using a document type or an offer, and to resolve an offer | 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 | -| [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), 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), 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), 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 | +| [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 | | [resolveDocumentOffer](resolve-document-offer.md) | [androidJvm]
abstract fun [resolveDocumentOffer](resolve-document-offer.md)(offerUri: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), executor: [Executor](https://developer.android.com/reference/kotlin/java/util/concurrent/Executor.html)? = null, onResolvedOffer: [OpenId4VciManager.OnResolvedOffer](-on-resolved-offer/index.md))
Resolve an offer using OpenId4Vci protocol | | [resumeWithAuthorization](resume-with-authorization.md) | [androidJvm]
abstract fun [resumeWithAuthorization](resume-with-authorization.md)(intent: [Intent](https://developer.android.com/reference/kotlin/android/content/Intent.html))
abstract fun [resumeWithAuthorization](resume-with-authorization.md)(uri: [Uri](https://developer.android.com/reference/kotlin/android/net/Uri.html))
abstract fun [resumeWithAuthorization](resume-with-authorization.md)(uri: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html))
Resume the authorization flow after the user has been redirected back to the app | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-doc-type.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-doc-type.md index 52a03688..660e3283 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-doc-type.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-doc-type.md @@ -5,6 +5,7 @@ [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)) @@ -17,6 +18,7 @@ androidJvm | | | |--------------|-------------------------------------------------------------------------------------------------------------------------------| | docType | the document type to issue | +| txCode | the transaction code to use for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onIssueEvent | the callback to be called when the document is issued | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer-uri.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer-uri.md index ab1ed88a..0a31d5a0 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer-uri.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer-uri.md @@ -5,6 +5,7 @@ [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)) @@ -17,6 +18,7 @@ androidJvm | | | |--------------|-----------------------------------------------------------------------------------------------------------------------------------------| | offerUri | the offer URI | +| txCode | the transaction code to use for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onIssueEvent | the callback to be called when the document is issued. This callback may be called multiple times, each for every document in the offer | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer.md index 2aeb5784..0a58509e 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/issue-document-by-offer.md @@ -4,6 +4,7 @@ [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)) @@ -16,6 +17,7 @@ androidJvm | | | |--------------|-----------------------------------------------------------------------------------------------------------------------------------------| | offer | the offer to issue | +| txCode | the transaction code to use for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onIssueEvent | the callback to be called when the document is issued. This callback may be called multiple times, each for every document in the offer | 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 04c3bf82..ce74deb1 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,9 +42,9 @@ 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) | -| [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), 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), 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), 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 | +| [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 | | [loadSampleData](load-sample-data.md) | [androidJvm]
fun [loadSampleData](load-sample-data.md)(sampleData: [ByteArray](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-byte-array/index.html)): LoadSampleResult
Loads sample data into the wallet's document manager | | [removeAllTransferEventListeners](remove-all-transfer-event-listeners.md) | [androidJvm]
fun [removeAllTransferEventListeners](remove-all-transfer-event-listeners.md)(): [EudiWallet](index.md)
Removes all transfer event listeners. | | [removeTransferEventListener](remove-transfer-event-listener.md) | [androidJvm]
fun [removeTransferEventListener](remove-transfer-event-listener.md)(listener: TransferEvent.Listener): [EudiWallet](index.md)
Removes a transfer event listener. | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-doc-type.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-doc-type.md index c0445268..1a8ebdc2 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-doc-type.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-doc-type.md @@ -5,6 +5,7 @@ [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)) @@ -17,6 +18,7 @@ androidJvm | | | |----------|-------------------------------------------------------------------------------------------------------------------------------| | docType | the document type to issue | +| txCode | the transaction code for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onEvent | the callback to be called when the document is issued | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer-uri.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer-uri.md index f1b25f3c..4c3bd262 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer-uri.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer-uri.md @@ -5,6 +5,7 @@ [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)) @@ -17,6 +18,7 @@ androidJvm | | | |----------|-------------------------------------------------------------------------------------------------------------------------------| | offerUri | the offer uri | +| txCode | the transaction code for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onEvent | the callback to be called when the document is issued | diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer.md b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer.md index 7bdc11ff..99c2b277 100644 --- a/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer.md +++ b/docs/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/issue-document-by-offer.md @@ -5,6 +5,7 @@ [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)) @@ -17,6 +18,7 @@ androidJvm | | | |----------|-------------------------------------------------------------------------------------------------------------------------------| | offer | the offer to issue | +| txCode | the transaction code for pre-authorized issuing | | executor | the executor defines the thread on which the callback will be called. If null, the callback will be called on the main thread | | onEvent | the callback to be called when the document is issued | diff --git a/docs/wallet-core/package-list b/docs/wallet-core/package-list index 00272cd0..b744d6c4 100644 --- a/docs/wallet-core/package-list +++ b/docs/wallet-core/package-list @@ -44,10 +44,20 @@ $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.OfferedDocument/ $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.OfferedDocument/asPair/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/as-pair.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.OfferedDocument/docType/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/doc-type.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.OfferedDocument/name/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/name.md -$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.OfferedDocument/toString/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-offered-document/to-string.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec.InputMode.NUMERIC///PointingToDeclaration/{"org.jetbrains.dokka.links.EnumEntryDRIExtra":{"key":"org.jetbrains.dokka.links.EnumEntryDRIExtra"}}wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-n-u-m-e-r-i-c/index.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec.InputMode.TEXT///PointingToDeclaration/{"org.jetbrains.dokka.links.EnumEntryDRIExtra":{"key":"org.jetbrains.dokka.links.EnumEntryDRIExtra"}}wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/-t-e-x-t/index.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec.InputMode///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/index.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec.InputMode/valueOf/#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/value-of.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec.InputMode/values/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-input-mode/values.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/index.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec/TxCodeSpec/#eu.europa.ec.eudi.wallet.issue.openid4vci.Offer.TxCodeSpec.InputMode#kotlin.Int?#kotlin.String?/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/-tx-code-spec.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec/description/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/description.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec/inputMode/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/input-mode.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer.TxCodeSpec/length/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/-tx-code-spec/length.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/index.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer/issuerName/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/issuer-name.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer/offeredDocuments/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/offered-documents.md +$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/Offer/txCodeSpec/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer/tx-code-spec.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OfferResult.Failure///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer-result/-failure/index.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OfferResult.Failure/Failure/#kotlin.Throwable/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer-result/-failure/-failure.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OfferResult.Failure/cause/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-offer-result/-failure/cause.md @@ -116,9 +126,9 @@ $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager.OnRe $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/issueDocumentByDocType/#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#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#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 +$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 $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resolveDocumentOffer/#kotlin.String#java.util.concurrent.Executor?#eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.OnResolvedOffer/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resolve-document-offer.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resumeWithAuthorization/#android.content.Intent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resume-with-authorization.md $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resumeWithAuthorization/#android.net.Uri/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resume-with-authorization.md @@ -264,9 +274,9 @@ $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/issueDocumentByDocType/#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#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#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 +$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 $dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/loadSampleData/#kotlin.ByteArray/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/load-sample-data.md $dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/removeAllTransferEventListeners/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/remove-all-transfer-event-listeners.md $dokka.location:eu.europa.ec.eudi.wallet/EudiWallet/removeTransferEventListener/#eu.europa.ec.eudi.iso18013.transfer.TransferEvent.Listener/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet/-eudi-wallet/remove-transfer-event-listener.md diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ace60a96..1fd387c5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ dependency-license-report = "2.4" dependencycheck = "9.0.9" espresso-contrib = "3.5.1" espresso-core = "3.5.1" -eudi-document-manager = "0.4.0-LOCAL1-SNAPSHOT" +eudi-document-manager = "0.4.0-SNAPSHOT" eudi-iso18013-data-transfer = "0.2.0-SNAPSHOT" eudi-lib-jvm-openid4vci-kt = "0.3.2-SNAPSHOT" eudi-lib-jvm-siop-openid4vp-kt = "0.4.2" 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 7fe52653..8d481129 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 @@ -234,6 +234,7 @@ object EudiWallet { /** * Issue a document using the OpenId4VCI protocol * @param docType the document type to issue + * @param txCode the transaction code for pre-authorized issuing * @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 onEvent the callback to be called when the document is issued * @throws IllegalStateException if [EudiWallet] is not firstly initialized via the [init] method @@ -244,6 +245,7 @@ object EudiWallet { */ fun issueDocumentByDocType( docType: String, + txCode: String? = null, executor: Executor? = null, onEvent: OpenId4VciManager.OnIssueEvent, ) { @@ -253,7 +255,7 @@ object EudiWallet { documentManager(this@EudiWallet.documentManager) config(config) logger = this@EudiWallet.logger - }.also { it.issueDocumentByDocType(docType, executor, onEvent) } + }.also { it.issueDocumentByDocType(docType, txCode, executor, onEvent) } } ?: run { (executor ?: context.mainExecutor()).execute { onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration"))) @@ -265,6 +267,7 @@ object EudiWallet { /** * Issue a document using an offer and the OpenId4VCI protocol * @param offer the offer to issue + * @param txCode the transaction code for pre-authorized issuing * @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 onEvent the callback to be called when the document is issued @@ -276,6 +279,7 @@ object EudiWallet { */ fun issueDocumentByOffer( offer: Offer, + txCode: String? = null, executor: Executor? = null, onEvent: OpenId4VciManager.OnIssueEvent, ) { @@ -285,7 +289,7 @@ object EudiWallet { documentManager(this@EudiWallet.documentManager) config(config) logger = this@EudiWallet.logger - }.also { it.issueDocumentByOffer(offer, executor, onEvent) } + }.also { it.issueDocumentByOffer(offer, txCode, executor, onEvent) } } ?: run { (executor ?: context.mainExecutor()).execute { onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration"))) @@ -297,6 +301,7 @@ object EudiWallet { /** * Issue a document using an offerUri and the OpenId4VCI protocol * @param offerUri the offer uri + * @param txCode the transaction code for pre-authorized issuing * @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 onEvent the callback to be called when the document is issued * @throws IllegalStateException if [EudiWallet] is not firstly initialized via the [init] method @@ -307,6 +312,7 @@ object EudiWallet { */ fun issueDocumentByOfferUri( offerUri: String, + txCode: String? = null, executor: Executor? = null, onEvent: OpenId4VciManager.OnIssueEvent, ) { @@ -316,7 +322,7 @@ object EudiWallet { documentManager(this@EudiWallet.documentManager) config(config) logger = this@EudiWallet.logger - }.also { it.issueDocumentByOfferUri(offerUri, executor, onEvent) } + }.also { it.issueDocumentByOfferUri(offerUri, txCode, executor, onEvent) } } ?: run { (executor ?: context.mainExecutor()).execute { onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration"))) diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOffer.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOffer.kt index 15518d1c..b86e4c86 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOffer.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOffer.kt @@ -16,10 +16,7 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci -import eu.europa.ec.eudi.openid4vci.CredentialConfiguration -import eu.europa.ec.eudi.openid4vci.CredentialIssuerMetadata -import eu.europa.ec.eudi.openid4vci.CredentialOffer -import eu.europa.ec.eudi.openid4vci.MsoMdocCredential +import eu.europa.ec.eudi.openid4vci.* /** * Default implementation of [Offer]. @@ -33,7 +30,7 @@ import eu.europa.ec.eudi.openid4vci.MsoMdocCredential */ internal data class DefaultOffer( @JvmSynthetic val credentialOffer: CredentialOffer, - @JvmSynthetic val credentialConfigurationFilter: CredentialConfigurationFilter = CredentialConfigurationFilter.MsoMdocFormatFilter + @JvmSynthetic val credentialConfigurationFilter: CredentialConfigurationFilter = CredentialConfigurationFilter.MsoMdocFormatFilter, ) : Offer { private val issuerMetadata: CredentialIssuerMetadata = credentialOffer.credentialIssuerMetadata @@ -42,10 +39,35 @@ internal data class DefaultOffer( override val offeredDocuments: List = issuerMetadata.credentialConfigurationsSupported .filterKeys { it in credentialOffer.credentialConfigurationIdentifiers } .filterValues { credentialConfigurationFilter(it) } - .map { (id, conf) -> Offer.OfferedDocument(conf.name, conf.docType, id, conf) } + .map { (id, conf) -> DefaultOfferedDocument(id, conf) } + override val txCodeSpec: Offer.TxCodeSpec? + get() = credentialOffer.txCodeSpec override fun toString(): String { - return "Offer(issuerName='$issuerName', offeredDocuments=$offeredDocuments)" + return "Offer(issuerName='$issuerName', offeredDocuments=$offeredDocuments, txCodeSpec=$txCodeSpec)" + } +} + +/** + * Default implementation of [Offer.OfferedDocument]. + * @property configurationIdentifier credential configuration identifier + * @property configuration credential configuration + * @constructor Creates a new [DefaultOfferedDocument] instance. + * @param configurationIdentifier [CredentialConfigurationIdentifier] instance + * @param configuration [CredentialConfiguration] instance + */ +internal data class DefaultOfferedDocument( + @JvmSynthetic internal val configurationIdentifier: CredentialConfigurationIdentifier, + @JvmSynthetic internal val configuration: CredentialConfiguration, +) : Offer.OfferedDocument { + override val name: String = configuration.name + override val docType: String = configuration.docType + + /** + * + */ + override fun toString(): String { + return "OfferedDocument(name='$name', docType='$docType')" } } @@ -66,4 +88,18 @@ internal val CredentialConfiguration.docType: String @JvmSynthetic get() = when (this) { is MsoMdocCredential -> docType else -> "unknown" + } + +internal val CredentialOffer.txCodeSpec: Offer.TxCodeSpec? + @JvmSynthetic get() = grants?.preAuthorizedCode()?.txCode.let { + it?.let { txCode -> + Offer.TxCodeSpec( + inputMode = when (txCode.inputMode) { + TxCodeInputMode.NUMERIC -> Offer.TxCodeSpec.InputMode.NUMERIC + TxCodeInputMode.TEXT -> Offer.TxCodeSpec.InputMode.TEXT + }, + length = txCode.length, + description = txCode.description + ) + } } \ No newline at end of file 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 050fbc96..5bf9057e 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 @@ -79,18 +79,19 @@ internal class DefaultOpenId4VciManager( IssuerCreator(config, ktorHttpClientFactory) } private val issuerAuthorization: IssuerAuthorization by lazy { - IssuerAuthorization(config, context, logger) + IssuerAuthorization(context, logger) } override fun issueDocumentByDocType( docType: String, + txCode: String?, executor: Executor?, onIssueEvent: OpenId4VciManager.OnIssueEvent, ) { launch(onIssueEvent.wrap(executor)) { coroutineScope, listener -> try { val offer = offerCreator.createOffer(docType) - doIssue(offer, listener) + doIssue(offer, txCode, listener) } catch (e: Throwable) { listener(failure(e)) coroutineScope.cancel("issueDocumentByDocType failed", e) @@ -100,12 +101,13 @@ internal class DefaultOpenId4VciManager( override fun issueDocumentByOffer( offer: Offer, + txCode: String?, executor: Executor?, onIssueEvent: OpenId4VciManager.OnIssueEvent, ) { launch(onIssueEvent.wrap(executor)) { coroutineScope, listener -> try { - doIssue(offer, listener) + doIssue(offer, txCode, listener) } catch (e: Throwable) { listener(failure(e)) coroutineScope.cancel("issueDocumentByOffer failed", e) @@ -116,13 +118,14 @@ internal class DefaultOpenId4VciManager( override fun issueDocumentByOfferUri( offerUri: String, + txCode: String?, executor: Executor?, onIssueEvent: OpenId4VciManager.OnIssueEvent, ) { launch(onIssueEvent.wrap(executor)) { coroutineScope, listener -> try { val offer = offerResolver.resolve(offerUri).getOrThrow() - doIssue(offer, listener) + doIssue(offer, txCode, listener) } catch (e: Throwable) { listener(failure(e)) coroutineScope.cancel("issueDocumentByOfferUri failed", e) @@ -214,11 +217,12 @@ internal class DefaultOpenId4VciManager( */ private suspend fun doIssue( offer: Offer, + txCode: String?, listener: OpenId4VciManager.OnResult, ) { offer as DefaultOffer val issuer = issuerCreator.createIssuer(offer) - var authorizedRequest = issuerAuthorization.authorize(issuer) + var authorizedRequest = issuerAuthorization.authorize(issuer, txCode) listener(IssueEvent.Started(offer.offeredDocuments.size)) val issuedDocumentIds = mutableListOf() 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 6f13a8b6..53eeaf54 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 @@ -32,112 +32,95 @@ import java.io.Closeable import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.resume - +/** + * Authorizes an [Issuer] and provides the authorization code. + * @property continuation The continuation for the authorization. + */ internal class IssuerAuthorization( - private val config: OpenId4VciManager.Config, private val context: Context, private val logger: Logger? = null, ) : Closeable { - private var suspendedAuthorization: SuspendedAuthorization? = null + var continuation: CancellableContinuation>? = null - suspend fun authorize(issuer: Issuer): AuthorizedRequest { + /** + * Authorizes the given [Issuer] and returns the authorized request. + * If txCode is provided, it will be used to authorize the issuer, + * otherwise the browser will be opened for user authorization + * @param issuer The issuer to authorize. + * @param txCode The pre-authorization code. + */ + suspend fun authorize(issuer: Issuer, txCode: String?): AuthorizedRequest { close() // close any previous suspensions return with(issuer) { - val prepareAuthorizationCodeRequest = prepareAuthorizationRequest().getOrThrow() - val authResponse = openBrowserForAuthorization(prepareAuthorizationCodeRequest).getOrThrow() - prepareAuthorizationCodeRequest.authorizeWithAuthorizationCode( - AuthorizationCode(authResponse.authorizationCode), - authResponse.serverState - ).getOrThrow() - } - } - - fun resumeFromUri(uri: Uri) { - logger?.d(TAG, "IssuerAuthorization.resumeFromUri($uri)") - suspendedAuthorization?.use { it.resumeFromUri(uri) } - ?: logger?.e( - TAG, - "${this::class.simpleName}.resumeFromUri failed", - IllegalStateException("No suspended authorization found") - ) - - } - - override fun close() { - suspendedAuthorization?.close() - suspendedAuthorization = null - } + when { + !txCode.isNullOrEmpty() -> authorizeWithPreAuthorizationCode(txCode) + else -> { + val prepareAuthorizationCodeRequest = prepareAuthorizationRequest().getOrThrow() + val authResponse = openBrowserForAuthorization(prepareAuthorizationCodeRequest).getOrThrow() + prepareAuthorizationCodeRequest.authorizeWithAuthorizationCode( + AuthorizationCode(authResponse.authorizationCode), + authResponse.serverState + ) - /** - * Opens a browser for authorization. - * @param prepareAuthorizationCodeRequest The prepared authorization request. - * @return The authorization response wrapped in a [Result]. - */ - private suspend fun openBrowserForAuthorization(prepareAuthorizationCodeRequest: AuthorizationRequestPrepared): Result { - val authorizationCodeUri = - Uri.parse(prepareAuthorizationCodeRequest.authorizationCodeURL.value.toString()) - return suspendCancellableCoroutine { continuation -> - suspendedAuthorization = SuspendedAuthorization(continuation, logger) - continuation.invokeOnCancellation { - suspendedAuthorization = null - } - context.startActivity(Intent(ACTION_VIEW, authorizationCodeUri).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - }) + } + }.getOrThrow() } } /** - * Suspended authorization. It is used to resume the authorization process. + * Resumes the authorization from the given [Uri]. */ - class SuspendedAuthorization( - val continuation: CancellableContinuation>, - val logger: Logger? = null, - ) : Closeable { - - - /** - * Resumes the authorization process from the given uri. - * @param uri the uri - * @throws Throwable if the uri is invalid - */ - fun resumeFromUri(uri: Uri) { + fun resumeFromUri(uri: Uri) { + logger?.d(TAG, "IssuerAuthorization.resumeFromUri($uri)") + continuation?.let { cont -> try { uri.getQueryParameter("code")?.let { authorizationCode -> uri.getQueryParameter("state")?.let { serverState -> - continuation.resume(Result.success(Response(authorizationCode, serverState))) + cont.resume(Result.success(Response(authorizationCode, serverState))) } ?: "No server state found".let { msg -> val exception = IllegalStateException(msg) logger?.e(TAG, "resumeFromUri: $msg", exception) - continuation.resume(Result.failure(exception)) + cont.resume(Result.failure(exception)) } } ?: "No authorization code found".let { msg -> val exception = IllegalStateException(msg) logger?.e(TAG, "resumeFromUri: $msg", exception) - continuation.resume(Result.failure(exception)) + cont.resume(Result.failure(exception)) } } catch (e: Throwable) { logger?.e(TAG, "resumeFromUri: ${e.message}", e) - continuation.resume(Result.failure(e)) + cont.resume(Result.failure(e)) } + } ?: run { + val exception = IllegalStateException("No suspended authorization found") + logger?.e(TAG, "IssuerAuthorization.resumeFromUri failed", exception) + throw exception } - /** - * Cancels the wrapped continuation. - */ - override fun close() { - continuation.takeIf { it.isActive }?.cancel(CancellationException("Authorization was cancelled")) - } + } - /** - * Response of the authorization process. - * @property authorizationCode the authorization code - * @property serverState the server state - * @constructor Creates a new [Response] instance. - * @param authorizationCode the authorization code - * @param serverState the server state - */ - data class Response(val authorizationCode: String, val serverState: String) + override fun close() { + continuation?.cancel(CancellationException("Authorization was cancelled")) + continuation = null } + + /** + * Opens a browser for authorization. + * @param prepareAuthorizationCodeRequest The prepared authorization request. + * @return The authorization response wrapped in a [Result]. + */ + suspend fun openBrowserForAuthorization(prepareAuthorizationCodeRequest: AuthorizationRequestPrepared): Result { + val authorizationCodeUri = + Uri.parse(prepareAuthorizationCodeRequest.authorizationCodeURL.value.toString()) + return suspendCancellableCoroutine { cont -> + continuation = cont + cont.invokeOnCancellation { continuation = null } + context.startActivity(Intent(ACTION_VIEW, authorizationCodeUri).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + }) + } + } + + data class Response(val authorizationCode: String, val serverState: String) } \ 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 3d853aaa..3a27865b 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 @@ -17,35 +17,56 @@ 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 /** * An offer of credentials to be issued. * @property issuerName the name of the issuer * @property offeredDocuments the items to be issued + * @property txCodeSpec the specification for the transaction code */ interface Offer { val issuerName: String val offeredDocuments: List + val txCodeSpec: TxCodeSpec? /** * An item to be issued. * @property name the name of the item * @property docType the document type of the item */ - data class OfferedDocument internal constructor( - val name: String, - val docType: String, - @JvmSynthetic internal val configurationIdentifier: CredentialConfigurationIdentifier, - @JvmSynthetic internal val configuration: CredentialConfiguration - ) { + interface OfferedDocument { + val name: String + val docType: String + /** * Converts this item to a pair of name and document type. */ fun asPair() = Pair(name, docType) - override fun toString(): String { - return "OfferedDocument(name='$name', docType='$docType')" + } + + /** + * Specification for a transaction code. + * @property inputMode the input mode for the transaction code + * @property length the length of the transaction code + * @property description a description of the transaction code + */ + data class TxCodeSpec( + val inputMode: InputMode = InputMode.NUMERIC, + val length: Int?, + val description: String? = null, + ) { + + /** + * The input mode for the transaction code. + * @property NUMERIC the transaction code is numeric + * @property TEXT the transaction code is text + */ + enum class InputMode { + NUMERIC, TEXT } } } 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 eaaf1232..e741b79e 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 @@ -40,12 +40,14 @@ interface OpenId4VciManager { /** * Issue a document using a document type * @param docType the document type to issue + * @param txCode the transaction code to use for pre-authorized issuing * @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 */ fun issueDocumentByDocType( docType: String, + txCode: String? = null, executor: Executor? = null, onIssueEvent: OnIssueEvent, ) @@ -53,6 +55,7 @@ interface OpenId4VciManager { /** * Issue a document using an offer * @param offer the offer to issue + * @param txCode the transaction code to use for pre-authorized issuing * @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. This callback may be called multiple times, each for every document in the offer * @@ -60,6 +63,7 @@ interface OpenId4VciManager { */ fun issueDocumentByOffer( offer: Offer, + txCode: String? = null, executor: Executor? = null, onIssueEvent: OnIssueEvent, ) @@ -67,12 +71,14 @@ interface OpenId4VciManager { /** * Issue a document using an offer URI * @param offerUri the offer URI + * @param txCode the transaction code to use for pre-authorized issuing * @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. This callback may be called multiple times, each for every document in the offer * @see[IssueEvent] on how to handle the result */ fun issueDocumentByOfferUri( offerUri: String, + txCode: String? = null, executor: Executor? = null, onIssueEvent: OnIssueEvent, ) diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SubmitRequest.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SubmitRequest.kt index ee15f10d..3c002f00 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SubmitRequest.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SubmitRequest.kt @@ -45,6 +45,7 @@ internal class SubmitRequest( unsignedDocument: UnsignedDocument, offeredDocument: Offer.OfferedDocument, ): SubmissionOutcome { + offeredDocument as DefaultOfferedDocument var proofSigner: ProofSigner? = null val claimSet = null val payload = IssuanceRequestPayload.ConfigurationBased(offeredDocument.configurationIdentifier, claimSet) diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOfferTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOfferTest.kt index 66dfee53..4d5817ab 100644 --- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOfferTest.kt +++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOfferTest.kt @@ -75,13 +75,13 @@ class DefaultOfferTest { assertEquals(1, offer.offeredDocuments.size) - val expectedOfferedDocument = Offer.OfferedDocument( - "testName", - "testDocType", + val expectedOfferedDocument = DefaultOfferedDocument( mockCredentialConfigurationIdentifiers[0], mockCredentialConfigurations[0] ) assertEquals(listOf(expectedOfferedDocument), offer.offeredDocuments) + assertEquals("testName", offer.offeredDocuments[0].name) + assertEquals("testDocType", offer.offeredDocuments[0].docType) } } \ 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 new file mode 100644 index 00000000..05bb4ad8 --- /dev/null +++ b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorizationTest.kt @@ -0,0 +1,231 @@ +/* + * 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 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.wallet.logging.Logger +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.time.Duration.Companion.milliseconds + + +class IssuerAuthorizationTest { + + companion object { + lateinit var context: Context + lateinit var logger: Logger + lateinit var issuer: Issuer + + + @BeforeAll + @JvmStatic + fun setup() { + + mockkStatic(Uri::class) + every { Uri.parse(any()) } returns mockk(relaxed = true) + + mockkConstructor(Intent::class) + every { anyConstructed().addFlags(any()) } returns mockk(relaxed = true) + + issuer = mockk(relaxed = true) + + + context = mockk(relaxed = true) + logger = mockk(relaxed = true) + } + } + + lateinit var preparedAuthorizationRequest: AuthorizationRequestPrepared + lateinit var authorizedRequest: AuthorizedRequest + + @BeforeEach + fun setupTest() { + preparedAuthorizationRequest = mockk(relaxed = true) + every { + preparedAuthorizationRequest.authorizationCodeURL + } returns HttpsUrl("https://test.com").getOrThrow() + + authorizedRequest = mockk(relaxed = true) + + coEvery { + issuer.prepareAuthorizationRequest() + } returns Result.success(preparedAuthorizationRequest) + + coEvery { + with(issuer) { + preparedAuthorizationRequest.authorizeWithAuthorizationCode(any(), any()) + } + } returns Result.success(authorizedRequest) + + coEvery { + issuer.authorizeWithPreAuthorizationCode(any()) + } returns Result.success(authorizedRequest) + } + + @Test + fun `authorize method when txCode equals to null call openBrowserForAuthorization`() { + + val issuerAuthorization = spyk(IssuerAuthorization(context, logger)) + runTest { + launch { + issuerAuthorization.authorize(issuer, null) + } + launch { + delay(500.milliseconds) + issuerAuthorization.close() + } + } + coVerify(exactly = 1) { + issuer.prepareAuthorizationRequest() + issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + } + + @Test + fun `authorize method when passing txCode does not call openBrowserForAuthorization but calls authorizeWithPreAuthorizationCode`() { + + val issuerAuthorization = spyk(IssuerAuthorization(context, logger)) + runTest { + launch { + issuerAuthorization.authorize(issuer, "testCode") + } + launch { + delay(500.milliseconds) + issuerAuthorization.close() + } + } + coVerify(exactly = 0) { + issuer.prepareAuthorizationRequest() + issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + coVerify(exactly = 1) { + issuer.authorizeWithPreAuthorizationCode("testCode") + } + } + + @Test + fun `resumeFromUri resumes with success when authorization code and server state are present`() { + + val issuerAuthorization = spyk(IssuerAuthorization(context, logger)) + val uri = mockk(relaxed = true) { + every { getQueryParameter("code") } returns "testCode" + every { getQueryParameter("state") } returns "testState" + } + var result: Result? = null + runTest { + launch { + result = issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + + launch { + delay(500.milliseconds) + issuerAuthorization.use { it.resumeFromUri(uri) } + } + } + assertNotNull(result, "Result is not null") + assertTrue(result!!.isSuccess) + assertEquals("testCode", result!!.getOrNull()!!.authorizationCode) + assertEquals("testState", result!!.getOrNull()!!.serverState) + verify(exactly = 1) { + issuerAuthorization.resumeFromUri(uri) + } + } + + @Test + fun `resumeFromUri resumes with failure when authorization code is missing`() { + val issuerAuthorization: IssuerAuthorization = spyk(IssuerAuthorization(context, logger)) + val uri = mockk(relaxed = true) { + every { getQueryParameter("code") } returns null + every { getQueryParameter("state") } returns "testState" + } + var result: Result? = null + runTest { + launch { + result = issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + + launch { + delay(500.milliseconds) + issuerAuthorization.use { it.resumeFromUri(uri) } + } + } + assertNotNull(result, "Result is not null") + assertTrue(result!!.isFailure) + verify(exactly = 1) { + issuerAuthorization.resumeFromUri(uri) + } + } + + @Test + fun `resumeFromUri resumes with failure when server state is missing`() { + val issuerAuthorization: IssuerAuthorization = spyk(IssuerAuthorization(context, logger)) + val uri = mockk { + every { getQueryParameter("code") } returns "testCode" + every { getQueryParameter("state") } returns null + } + var result: Result? = null + runTest { + launch(Dispatchers.Default) { + result = issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + + + launch(Dispatchers.Default) { + delay(500.milliseconds) + issuerAuthorization.use { it.resumeFromUri(uri) } + } + } + assertNotNull(result, "Result is not null") + assertTrue(result!!.isFailure, "Result failed") + verify(exactly = 1) { + issuerAuthorization.resumeFromUri(uri) + } + } + + @Test + fun `close cancels the continuation`() { + val issuerAuthorization: IssuerAuthorization = spyk(IssuerAuthorization(context, logger)) + var result: Result? = null + runTest { + launch { + result = issuerAuthorization.openBrowserForAuthorization(preparedAuthorizationRequest) + } + + launch { + delay(500.milliseconds) + issuerAuthorization.close() + + } + } + assertNull(result, "Result is null") + verify(exactly = 1) { issuerAuthorization.close() } + assertNull(issuerAuthorization.continuation, "Continuation is removed") + } +} \ No newline at end of file diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorizationTest.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorizationTest.kt deleted file mode 100644 index 0d663011..00000000 --- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorizationTest.kt +++ /dev/null @@ -1,185 +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 android.net.Uri -import android.util.Log -import eu.europa.ec.eudi.wallet.issue.openid4vci.IssuerAuthorization.SuspendedAuthorization -import eu.europa.ec.eudi.wallet.logging.Logger -import io.mockk.* -import kotlinx.coroutines.* -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.Test -import kotlin.time.Duration.Companion.milliseconds - - -class SuspendedAuthorizationTest { - - companion object { - @BeforeAll - @JvmStatic - fun setup() { - mockkStatic(Log::class) - every { Log.e(any(), any()) } returns 0 - every { Log.e(any(), any(), any()) } returns 0 - } - - @JvmStatic - internal val dummyLogger: Logger = mockk(relaxed = true) - } - - @Test - fun `resumeFromUri resumes with success when authorization code and server state are present`() { - - var suspendedAuthorization: SuspendedAuthorization? = null - val uri = mockk(relaxed = true) { - every { getQueryParameter("code") } returns "testCode" - every { getQueryParameter("state") } returns "testState" - } - var result: Result? = null - runTest { - launch { - result = suspendCancellableCoroutine { continuation -> - suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - } - } - - launch { - delay(500.milliseconds) - suspendedAuthorization!!.use { it.resumeFromUri(uri) } - } - } - assertTrue(result!!.isSuccess, "Result succeed") - assertEquals("testCode", result!!.getOrNull()?.authorizationCode) - assertEquals("testState", result!!.getOrNull()?.serverState) - verify(exactly = 1) { - suspendedAuthorization!!.resumeFromUri(uri) - } - } - - @Test - fun `resumeFromUri resumes with failure when authorization code is missing`() { - var suspendedAuthorization: SuspendedAuthorization? = null - val uri = mockk(relaxed = true) { - every { getQueryParameter("code") } returns null - every { getQueryParameter("state") } returns "testState" - } - var result: Result? = null - runTest { - launch { - result = suspendCancellableCoroutine { continuation -> - suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - } - } - - launch { - delay(500.milliseconds) - suspendedAuthorization!!.use { - it.resumeFromUri(uri) - } - } - } - assertTrue(result!!.isFailure, "Result failed") - verify(exactly = 1) { - suspendedAuthorization!!.resumeFromUri(uri) - } - } - - @Test - fun `resumeFromUri resumes with failure when server state is missing`() { - var suspendedAuthorization: SuspendedAuthorization? = null - val uri = mockk { - every { getQueryParameter("code") } returns "testCode" - every { getQueryParameter("state") } returns null - } - var result: Result? = null - runTest { - launch(Dispatchers.Default) { - result = suspendCancellableCoroutine { continuation -> - suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - } - } - - - launch(Dispatchers.Default) { - delay(500.milliseconds) - suspendedAuthorization!!.use { it.resumeFromUri(uri) } - } - } - assertTrue(result!!.isFailure, "Result failed") - verify(exactly = 1) { - suspendedAuthorization!!.resumeFromUri(uri) - } - } - - @Test - fun `close cancels the continuation`() { - var suspendedAuthorization: SuspendedAuthorization? = null - var result: Result? = null - runTest { - launch { - result = suspendCancellableCoroutine { continuation -> - suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - } - } - - launch { - delay(500.milliseconds) - suspendedAuthorization!!.close() - - } - } - assertNull(result, "Result is null") - verify(exactly = 1) { suspendedAuthorization!!.close() } - assertTrue(suspendedAuthorization!!.continuation.isCancelled, "Continuation is cancelled") - } - - @Test - fun `verify that method resumeFromUri calls resumeFromUri`() { - val continuation = mockk>>(relaxed = true) - val suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - val uri = mockk { - every { getQueryParameter("code") } returns "testCode" - every { getQueryParameter("state") } returns "testState" - } - suspendedAuthorization.resumeFromUri(uri) - verify(exactly = 1) { - suspendedAuthorization.resumeFromUri(uri) - } - } - - @Test - fun `verify that method resumeFromUri with String calls resumeFromUri with Uri`() { - mockkStatic(Uri::class) - - val continuation = mockk>>(relaxed = true) - val suspendedAuthorization = spyk(SuspendedAuthorization(continuation, dummyLogger)) - val uriStr = "https://test.com?code=testCode&state=testState" - val uri = mockk(relaxed = true) { - every { getQueryParameter("code") } returns "testCode" - every { getQueryParameter("state") } returns "testState" - } - every { Uri.parse(uriStr) } answers { uri } - - suspendedAuthorization.resumeFromUri(uri) - verify(exactly = 1) { - suspendedAuthorization.resumeFromUri(uri) - } - } -} \ No newline at end of file