diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt index de24147c..2ed5cf9d 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt @@ -18,14 +18,14 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci import androidx.biometric.BiometricPrompt.CryptoObject -import eu.europa.ec.eudi.openid4vci.SubmittedRequest +import eu.europa.ec.eudi.openid4vci.SubmissionOutcome /** * Exception thrown when user authentication is required. */ internal class UserAuthRequiredException( val cryptoObject: CryptoObject?, - val resume: suspend (Boolean) -> SubmittedRequest + val resume: suspend (Boolean) -> SubmissionOutcome, ) : Throwable() /** diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/IssuerAuthorization.kt index 53eeaf54..825ffa7f 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 @@ -20,10 +20,7 @@ import android.content.Context import android.content.Intent import android.content.Intent.ACTION_VIEW import android.net.Uri -import eu.europa.ec.eudi.openid4vci.AuthorizationCode -import eu.europa.ec.eudi.openid4vci.AuthorizationRequestPrepared -import eu.europa.ec.eudi.openid4vci.AuthorizedRequest -import eu.europa.ec.eudi.openid4vci.Issuer +import eu.europa.ec.eudi.openid4vci.* import eu.europa.ec.eudi.wallet.issue.openid4vci.OpenId4VciManager.Companion.TAG import eu.europa.ec.eudi.wallet.logging.Logger import kotlinx.coroutines.CancellableContinuation @@ -49,12 +46,17 @@ internal class IssuerAuthorization( * otherwise the browser will be opened for user authorization * @param issuer The issuer to authorize. * @param txCode The pre-authorization code. + * @throws IllegalArgumentException if the txCode is invalid. */ suspend fun authorize(issuer: Issuer, txCode: String?): AuthorizedRequest { close() // close any previous suspensions return with(issuer) { when { - !txCode.isNullOrEmpty() -> authorizeWithPreAuthorizationCode(txCode) + isPreAuthorized() -> { + marshalTxCode(txCode) + authorizeWithPreAuthorizationCode(txCode) + } + else -> { val prepareAuthorizationCodeRequest = prepareAuthorizationRequest().getOrThrow() val authResponse = openBrowserForAuthorization(prepareAuthorizationCodeRequest).getOrThrow() @@ -122,5 +124,30 @@ internal class IssuerAuthorization( } } + /** + * Checks if the issuer's credential offer is pre-authorized. + */ + fun Issuer.isPreAuthorized(): Boolean = credentialOffer.grants?.preAuthorizedCode() != null + + /** + * Ensures the txCode is valid for the given issuer. + * @param txCode The pre-authorization code. + * @throws IllegalArgumentException if the txCode is invalid. + * @receiver The issuer to authorize. + */ + fun Issuer.marshalTxCode(txCode: String?) { + when (val txCodeSpec = credentialOffer.grants?.preAuthorizedCode()?.txCode) { + // no txCode in credential offer grants, so no txCode is expected for pre-authorization + null -> if (txCode != null) throw IllegalArgumentException("txCode is not required") + // txCode is present in credential offer grants, so it is required for pre-authorization + else -> when { + txCode == null -> throw IllegalArgumentException("txCode is required") + txCode.length != txCodeSpec.length -> throw IllegalArgumentException("txCode length is invalid") + txCodeSpec.inputMode == TxCodeInputMode.NUMERIC && !txCode.all { it.isDigit() } -> + throw IllegalArgumentException("txCode is not numeric") + } + } + } + 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 3a27865b..1e50ad5f 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Offer.kt @@ -15,10 +15,8 @@ */ package eu.europa.ec.eudi.wallet.issue.openid4vci -import eu.europa.ec.eudi.openid4vci.CredentialConfiguration -import eu.europa.ec.eudi.openid4vci.CredentialConfigurationIdentifier -import eu.europa.ec.eudi.openid4vci.TxCode -import eu.europa.ec.eudi.openid4vci.TxCodeInputMode +import eu.europa.ec.eudi.wallet.issue.openid4vci.Offer.TxCodeSpec.InputMode.NUMERIC +import eu.europa.ec.eudi.wallet.issue.openid4vci.Offer.TxCodeSpec.InputMode.TEXT /** * An offer of credentials to be issued. @@ -55,7 +53,7 @@ interface Offer { * @property description a description of the transaction code */ data class TxCodeSpec( - val inputMode: InputMode = InputMode.NUMERIC, + val inputMode: InputMode = NUMERIC, val length: Int?, val description: String? = null, ) {