@@ -462,7 +462,8 @@ class OpenID4VPPresentationActivity : FragmentActivity() {
462
462
463
463
val uri = Uri .parse(authRequest)
464
464
val authorizationRequest = getAuthorizationRequest(uri, httpClient)
465
- val presentationSubmission = createPresentationSubmission(authorizationRequest)
465
+ val credentialFormat = getFormat(authorizationRequest.clientMetadata, authorizationRequest.presentationDefinition)
466
+ val presentationSubmission = createPresentationSubmission(authorizationRequest, credentialFormat)
466
467
val inputDescriptors =
467
468
authorizationRequest.presentationDefinition[" input_descriptors" ]!! .jsonArray
468
469
@@ -479,10 +480,8 @@ class OpenID4VPPresentationActivity : FragmentActivity() {
479
480
//
480
481
val inputDescriptorObj = inputDescriptors[0 ].jsonObject
481
482
val docType = inputDescriptorObj[" id" ]!! .toString().run { substring(1 , this .length - 1 ) }
482
- // Get the requested format from the client metadata.
483
- val credentialFormat = getFormat(authorizationRequest.clientMetadata)
484
- val documentRequest = formatAsDocumentRequest(inputDescriptorObj)
485
483
484
+ val documentRequest = formatAsDocumentRequest(inputDescriptorObj)
486
485
val document = firstMatchingDocument(credentialFormat, docType)
487
486
? : run { throw NoMatchingDocumentException (" No matching credentials in wallet for " +
488
487
" docType $docType and credentialFormat $credentialFormat " ) }
@@ -894,42 +893,75 @@ private class TimeChecks : JWTClaimsSetVerifier<SecurityContext> {
894
893
}
895
894
}
896
895
897
- private fun getFormat (clientMetadata : JsonObject ): CredentialFormat {
898
- // Search for these strings, in order.
896
+ private fun getFormat (
897
+ clientMetadata : JsonObject ,
898
+ presentationDefinition : JsonObject
899
+ ): CredentialFormat {
900
+ // Since we only return a single format, we order acceptedFormats such that preferred formats
901
+ // are first.
899
902
val acceptedFormats = listOf (
900
903
" mso_mdoc" to CredentialFormat .MDOC_MSO ,
901
904
" jwt_vc" to CredentialFormat .SD_JWT_VC ,
902
905
" vc+sd-jwt" to CredentialFormat .SD_JWT_VC )
903
- clientMetadata[" vp_formats" ]?.let {
904
- val vpFormats = it.jsonObject.keys
905
- for ((format, credentialFormat) in acceptedFormats) {
906
- if (vpFormats.contains(format)) {
907
- return credentialFormat
906
+
907
+ // If the clientMetadata has a exactly one format, return that.
908
+ if (clientMetadata.containsKey(" vp_formats" )) {
909
+ val vpFormats = clientMetadata[" vp_formats" ]!! .jsonObject.keys
910
+ if (vpFormats.size == 1 ) {
911
+ for ((format, credentialFormat) in acceptedFormats) {
912
+ if (vpFormats.contains(format)) {
913
+ return credentialFormat
914
+ }
908
915
}
916
+ throw IllegalArgumentException (" No supported formats found in: ${vpFormats.sorted().joinToString()} " )
909
917
}
910
- throw IllegalArgumentException (" No supported formats found in: ${vpFormats.sorted().joinToString()} " )
911
918
}
912
- throw IllegalArgumentException (" No vp_formats found in client_metadata" )
919
+
920
+ // If clientMetadata has 0 or 2+ formats, use presentation_definition -> input_descriptors
921
+ // -> format.
922
+ val inputDescriptors = presentationDefinition[" input_descriptors" ]!! .jsonArray
923
+ val vpFormats = HashSet <String >()
924
+
925
+ for (inputDescriptor: JsonElement in inputDescriptors) {
926
+ val inputDescriptorObj = inputDescriptor.jsonObject
927
+ val formatName = inputDescriptorObj[" format" ]?.jsonObject?.keys?.first()
928
+ if (formatName != null ) {
929
+ vpFormats.add(formatName)
930
+ }
931
+ }
932
+
933
+ for ((format, credentialFormat) in acceptedFormats) {
934
+ if (vpFormats.contains(format)) {
935
+ return credentialFormat
936
+ }
937
+ }
938
+ throw IllegalArgumentException (" No vp_formats found in client_metadata and no supported " +
939
+ " formats found in input_descriptors: ${vpFormats.sorted().joinToString()} " )
913
940
}
914
941
915
- private val validFormats = setOf (" mso_mdoc" , " jwt_vc" , " vc+sd-jwt" )
942
+ internal fun createPresentationSubmission (
943
+ authRequest : AuthorizationRequest ,
944
+ credentialFormat : CredentialFormat
945
+ ): PresentationSubmission {
946
+ val vpFormats = when (credentialFormat) {
947
+ CredentialFormat .MDOC_MSO -> setOf (" jwt_vc" , " vc+sd-jwt" )
948
+ CredentialFormat .SD_JWT_VC -> setOf (" mso_mdoc" )
949
+ }
916
950
917
- internal fun createPresentationSubmission (authRequest : AuthorizationRequest ): PresentationSubmission {
918
951
val descriptorMaps = ArrayList <DescriptorMap >()
919
952
val inputDescriptors = authRequest.presentationDefinition[" input_descriptors" ]!! .jsonArray
920
953
921
954
for (inputDescriptor: JsonElement in inputDescriptors) {
922
955
val inputDescriptorObj = inputDescriptor.jsonObject
923
956
val docType = inputDescriptorObj[" id" ]!! .toString().run { substring(1 , this .length - 1 ) }
924
- val formatName = inputDescriptorObj[" format" ]?.jsonObject?.keys?.first() ? : " mso_mdoc"
925
- if (! validFormats.contains(formatName)) {
926
- throw IllegalArgumentException (" Unexpected format ($formatName ) in input_descriptors." )
957
+ val formatName = inputDescriptorObj[" format" ]?.jsonObject?.keys?.first()
958
+ if (formatName != null && vpFormats.contains(formatName)) {
959
+ descriptorMaps.add(DescriptorMap (
960
+ id = docType,
961
+ format = formatName,
962
+ path = " $"
963
+ ))
927
964
}
928
- descriptorMaps.add(DescriptorMap (
929
- id = docType,
930
- format = formatName,
931
- path = " $"
932
- ))
933
965
}
934
966
935
967
return PresentationSubmission (
0 commit comments