diff --git a/lib/connection_bridge/beacon/cubit/beacon_cubit.dart b/lib/connection_bridge/beacon/cubit/beacon_cubit.dart index 2137bcd53..cc5e8c5da 100644 --- a/lib/connection_bridge/beacon/cubit/beacon_cubit.dart +++ b/lib/connection_bridge/beacon/cubit/beacon_cubit.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:altme/app/app.dart'; @@ -31,11 +32,14 @@ class BeaconCubit extends Cubit { } } + Timer? debounce; + void listenToBeacon() { try { log.i('listening to beacon'); + beacon.getBeaconResponse().listen( - (data) { + (data) async { final Map requestJson = jsonDecode(data) as Map; final BeaconRequest beaconRequest = @@ -43,45 +47,57 @@ class BeaconCubit extends Cubit { log.i('beacon response - $requestJson'); log.i('beaconRequest.type - ${beaconRequest.type}'); - switch (beaconRequest.type) { - case RequestType.permission: - emit( - state.copyWith( - status: BeaconStatus.permission, - beaconRequest: beaconRequest, - ), - ); - - case RequestType.signPayload: - emit( - state.copyWith( - status: BeaconStatus.signPayload, - beaconRequest: beaconRequest, - ), - ); - - case RequestType.operation: - emit( - state.copyWith( - status: BeaconStatus.operation, - beaconRequest: beaconRequest, - ), - ); - - case RequestType.broadcast: - emit( - state.copyWith( - status: BeaconStatus.broadcast, - beaconRequest: beaconRequest, - ), - ); - - // ignore: no_default_cases - default: + + /// cancel previous timer if exists + if (debounce?.isActive ?? false) { + log.w('cancelled bombarded request'); + debounce?.cancel(); } + + debounce = Timer(const Duration(seconds: 1), () { + switch (beaconRequest.type) { + case RequestType.permission: + emit( + state.copyWith( + status: BeaconStatus.permission, + beaconRequest: beaconRequest, + ), + ); + + case RequestType.signPayload: + emit( + state.copyWith( + status: BeaconStatus.signPayload, + beaconRequest: beaconRequest, + ), + ); + + case RequestType.operation: + emit( + state.copyWith( + status: BeaconStatus.operation, + beaconRequest: beaconRequest, + ), + ); + + case RequestType.broadcast: + emit( + state.copyWith( + status: BeaconStatus.broadcast, + beaconRequest: beaconRequest, + ), + ); + + // ignore: no_default_cases + default: + break; + } + debounce?.cancel(); + }); }, ); } catch (e) { + debounce?.cancel(); log.e('beacon listening error - $e'); } } diff --git a/lib/dashboard/home/tab_bar/credentials/models/credential_model/credential_model.dart b/lib/dashboard/home/tab_bar/credentials/models/credential_model/credential_model.dart index a539c4c7e..48bb41e05 100644 --- a/lib/dashboard/home/tab_bar/credentials/models/credential_model/credential_model.dart +++ b/lib/dashboard/home/tab_bar/credentials/models/credential_model/credential_model.dart @@ -244,11 +244,7 @@ class CredentialModel extends Equatable { credentialPreview.credentialSubjectModel.credentialSubjectType == CredentialSubjectType.walletCredential; - String get getFormat => format != null - ? format! - : jwt != null - ? 'jwt_vc_json-ld' - : 'ldp_vc'; + String get getFormat => format != null ? format! : 'ldp_vc'; @override List get props => [ diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/filter_credential_list_by_format.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/filter_credential_list_by_format.dart index 16eb3abaa..ae526544c 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/filter_credential_list_by_format.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/filter_credential_list_by_format.dart @@ -31,22 +31,22 @@ List filterCredenialListByFormat({ (CredentialModel credentialModel) { /// remove ldpVc if (presentLdpVc) { - return credentialModel.format != VCFormatType.ldpVc.vcValue; + return credentialModel.getFormat != VCFormatType.ldpVc.vcValue; } /// remove jwtVc if (presentJwtVc) { - return credentialModel.format != VCFormatType.jwtVc.vcValue; + return credentialModel.getFormat != VCFormatType.jwtVc.vcValue; } /// remove JwtVcJson if (presentJwtVcJson) { - return credentialModel.format != VCFormatType.jwtVcJson.vcValue; + return credentialModel.getFormat != VCFormatType.jwtVcJson.vcValue; } /// remove vcSdJwt if (presentVcSdJwt) { - return credentialModel.format != VCFormatType.vcSdJWT.vcValue; + return credentialModel.getFormat != VCFormatType.vcSdJWT.vcValue; } return false; diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 8bcc1a66b..9dd413143 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -98,21 +98,23 @@ Future getAuthorizationUriForIssuer({ vcFormatType: vcFormatType, clientAssertion: clientAssertion, secureAuthorizedFlow: secureAuthorizedFlow, + credentialOfferJson: credentialOfferJson, dio: client.dio, ); final requirePushedAuthorizationRequests = openIdConfiguration.requirePushedAuthorizationRequests; - if ((requirePushedAuthorizationRequests != null && - requirePushedAuthorizationRequests) || - (requirePushedAuthorizationRequests == null && secureAuthorizedFlow)) { + if (requirePushedAuthorizationRequests || secureAuthorizedFlow) { final headers = { 'Content-Type': 'application/x-www-form-urlencoded', }; + final parUrl = openIdConfiguration.pushedAuthorizationRequestEndpoint ?? + '$authorizationEndpoint/par'; + /// error we shuld get it from final response = await client.post( - '$authorizationEndpoint/par', + parUrl, headers: headers, data: authorizationRequestParemeters, ); diff --git a/packages/credential_manifest/pubspec.yaml b/packages/credential_manifest/pubspec.yaml index ad19ec1d1..bfc6d7a2d 100644 --- a/packages/credential_manifest/pubspec.yaml +++ b/packages/credential_manifest/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter json_annotation: ^4.8.1 - json_path: ^0.4.4 #latest version creates test issue + json_path: ^0.7.2 #latest version creates test issue dev_dependencies: build_runner: ^2.4.4 diff --git a/packages/oidc4vc/lib/src/models/openid_configuration.dart b/packages/oidc4vc/lib/src/models/openid_configuration.dart index 11425f93e..d537e90a4 100644 --- a/packages/oidc4vc/lib/src/models/openid_configuration.dart +++ b/packages/oidc4vc/lib/src/models/openid_configuration.dart @@ -9,9 +9,11 @@ class OpenIdConfiguration extends Equatable { const OpenIdConfiguration({ required this.requirePushedAuthorizationRequests, this.authorizationServer, + this.authorizationServers, this.credentialsSupported, this.credentialConfigurationsSupported, this.credentialEndpoint, + this.pushedAuthorizationRequestEndpoint, this.credentialIssuer, this.subjectSyntaxTypesSupported, this.tokenEndpoint, @@ -32,6 +34,8 @@ class OpenIdConfiguration extends Equatable { @JsonKey(name: 'authorization_server') final String? authorizationServer; + @JsonKey(name: 'authorization_servers') + final List? authorizationServers; @JsonKey(name: 'credential_endpoint') final String? credentialEndpoint; @JsonKey(name: 'credential_issuer') @@ -44,6 +48,8 @@ class OpenIdConfiguration extends Equatable { final String? batchEndpoint; @JsonKey(name: 'authorization_endpoint') final String? authorizationEndpoint; + @JsonKey(name: 'pushed_authorization_request_endpoint') + final String? pushedAuthorizationRequestEndpoint; @JsonKey(name: 'subject_trust_frameworks_supported') final List? subjectTrustFrameworksSupported; @JsonKey(name: 'credentials_supported') @@ -71,6 +77,7 @@ class OpenIdConfiguration extends Equatable { @override List get props => [ authorizationServer, + authorizationServers, credentialEndpoint, credentialIssuer, subjectSyntaxTypesSupported, diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index b242912ab..3ee2b6f90 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -149,6 +149,7 @@ class OIDC4VC { required String? clientAssertion, required bool secureAuthorizedFlow, required Dio dio, + required dynamic credentialOfferJson, SecureStorageProvider? secureStorage, }) async { try { @@ -159,11 +160,12 @@ class OIDC4VC { secureStorage: secureStorage, ); - final authorizationEndpoint = await readAuthorizationEndPoint( + final credentialAuthorizationEndpoint = await readAuthorizationEndPoint( openIdConfiguration: openIdConfiguration, issuer: issuer, oidc4vciDraftType: oidc4vciDraftType, dio: dio, + credentialOfferJson: credentialOfferJson, secureStorage: secureStorage, ); @@ -188,7 +190,7 @@ class OIDC4VC { ); return ( - authorizationEndpoint, + credentialAuthorizationEndpoint, authorizationRequestParemeters, openIdConfiguration, ); @@ -861,29 +863,75 @@ class OIDC4VC { required String issuer, required OIDC4VCIDraftType oidc4vciDraftType, required Dio dio, + required dynamic credentialOfferJson, SecureStorageProvider? secureStorage, }) async { - var authorizationEndpoint = '$issuer/authorize'; + String? authorizationEndpoint; - if (openIdConfiguration.authorizationEndpoint != null) { - authorizationEndpoint = openIdConfiguration.authorizationEndpoint!; - } else { - final authorizationServer = - openIdConfiguration.authorizationServer ?? issuer; + switch (oidc4vciDraftType) { + case OIDC4VCIDraftType.draft11: + if (openIdConfiguration.authorizationEndpoint != null) { + authorizationEndpoint = openIdConfiguration.authorizationEndpoint; + } else { + final authorizationServer = + openIdConfiguration.authorizationServer ?? issuer; - final authorizationServerConfiguration = await getOpenIdConfig( - baseUrl: authorizationServer, - isAuthorizationServer: true, - dio: dio, - secureStorage: secureStorage, - ); + final authorizationServerConfiguration = await getOpenIdConfig( + baseUrl: authorizationServer, + isAuthorizationServer: true, + dio: dio, + secureStorage: secureStorage, + ); - if (authorizationServerConfiguration.authorizationEndpoint != null) { - authorizationEndpoint = - authorizationServerConfiguration.authorizationEndpoint!; - } + if (authorizationServerConfiguration.authorizationEndpoint != null) { + authorizationEndpoint = + authorizationServerConfiguration.authorizationEndpoint; + } + } + case OIDC4VCIDraftType.draft13: + + /// Extract the authorization endpoint from from first element of + /// authorization_servers in opentIdConfiguration.authorizationServers + final listOpenIDConfiguration = + openIdConfiguration.authorizationServers ?? []; + if (listOpenIDConfiguration.isNotEmpty) { + if (listOpenIDConfiguration.length == 1) { + authorizationEndpoint = + '${listOpenIDConfiguration.first}/authorize'; + } else { + try { + /// Extract the authorization endpoint from from + /// authorization_server in credentialOfferJson + final jsonPathCredentialOffer = JsonPath( + // ignore: lines_longer_than_80_chars + r'$..["urn:ietf:params:oauth:grant-type:pre-authorized_code"].authorization_server', + ); + final data = jsonPathCredentialOffer + .read(credentialOfferJson) + .first + .value! as String; + if (listOpenIDConfiguration.contains(data)) { + authorizationEndpoint = '$data/authorize'; + } + } catch (e) { + final jsonPathCredentialOffer = JsonPath( + r'$..authorization_code.authorization_server', + ); + final data = jsonPathCredentialOffer + .read(credentialOfferJson) + .first + .value! as String; + if (data.isNotEmpty && listOpenIDConfiguration.contains(data)) { + authorizationEndpoint = '$data/authorize'; + } + } + } + } } - return authorizationEndpoint; + // If authorizationEndpoint is null, we consider the issuer + // as the authorizationEndpoint + + return authorizationEndpoint ??= '$issuer/authorize'; } String readIssuerDid( @@ -1655,7 +1703,7 @@ class OIDC4VC { ////openid-issuer-configuration or some are in the /openid-configuration ///(token endpoint etc,) and other are in the /openid-credential-issuer ///(credential supported) for OIDC4VP and SIOPV2, the serve is a client, - ///the wallet is the suthorization server the verifier metadata are in + ///the wallet is the authorization server the verifier metadata are in ////openid-configuration final url = '$baseUrl/.well-known/openid-configuration'; diff --git a/packages/oidc4vc/pubspec.yaml b/packages/oidc4vc/pubspec.yaml index a59f682f8..dd6b880de 100644 --- a/packages/oidc4vc/pubspec.yaml +++ b/packages/oidc4vc/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: http_mock_adapter: ^0.6.0 jose_plus: ^0.4.5 json_annotation: ^4.8.1 - json_path: ^0.4.4 #latest version creates test issue + json_path: ^0.7.2 #latest version creates test issue secp256k1: ^0.3.0 secure_storage: path: ../secure_storage diff --git a/packages/oidc4vc/test/configuration/configuration.dart b/packages/oidc4vc/test/configuration/configuration.dart new file mode 100644 index 000000000..00c2b6b1b --- /dev/null +++ b/packages/oidc4vc/test/configuration/configuration.dart @@ -0,0 +1 @@ +export 'issuance/issuance.dart'; diff --git a/packages/oidc4vc/test/configuration/issuance/issuance.dart b/packages/oidc4vc/test/configuration/issuance/issuance.dart new file mode 100644 index 000000000..4d9eeba98 --- /dev/null +++ b/packages/oidc4vc/test/configuration/issuance/issuance.dart @@ -0,0 +1 @@ +export 'test10.dart'; diff --git a/packages/oidc4vc/test/configuration/issuance/test10.dart b/packages/oidc4vc/test/configuration/issuance/test10.dart new file mode 100644 index 000000000..e7ef88a3d --- /dev/null +++ b/packages/oidc4vc/test/configuration/issuance/test10.dart @@ -0,0 +1,566 @@ +const openIdCredentialIssuerConfigurationTest10 = { + 'credential_issuer': 'https://talao.co/issuer/grlvzckofy', + 'credential_endpoint': 'https://talao.co/issuer/grlvzckofy/credential', + 'deferred_credential_endpoint': 'https://talao.co/issuer/grlvzckofy/deferred', + 'authorization_servers': [ + 'https://talao.co/issuer/grlvzckofy', + 'https://fake.com/as', + ], + 'credential_configurations_supported': { + 'EudiPid': { + 'format': 'vc+sd-jwt', + 'scope': 'EudiPid_scope', + 'order': [ + 'given_name', + 'family_name', + 'birth_date', + 'birth_place', + 'nationalities', + 'address', + 'age_equal_or_over', + 'age_birth_year', + 'issuing_country', + 'issuing_authority', + 'dateIssued', + ], + 'claims': { + 'given_name': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'First Name', 'locale': 'en-US'}, + {'name': 'Pr\u00e9nom', 'locale': 'fr-FR'}, + ], + }, + 'family_name': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Family Name', 'locale': 'en-US'}, + {'name': 'Nom', 'locale': 'fr-FR'}, + ], + }, + 'birth_date': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Birth date', 'locale': 'en-US'}, + {'name': 'Date de naissance', 'locale': 'fr-FR'}, + ], + }, + 'birth_place': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Birth place', 'locale': 'en-US'}, + {'name': 'Lieu de naissance', 'locale': 'fr-FR'}, + ], + }, + 'nationalities': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Nationalities', 'locale': 'en-US'}, + {'name': 'Nationalit\u00e9s', 'locale': 'fr-FR'}, + ], + }, + 'age_equal_or_over': { + 'mandatory': true, + 'value_type': 'bool', + 'display': [ + {'name': 'Age', 'locale': 'en-US'}, + {'name': 'Age', 'locale': 'fr-FR'}, + ], + '12': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 12', 'locale': 'en-US'}, + {'name': 'Plus de 12 ans', 'locale': 'fr-FR'}, + ], + }, + '14': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 14', 'locale': 'en-US'}, + {'name': 'Plus de 14 ans', 'locale': 'fr-FR'}, + ], + }, + '16': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 16', 'locale': 'en-US'}, + {'name': 'Plus de 16 ans', 'locale': 'fr-FR'}, + ], + }, + '18': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 18', 'locale': 'en-US'}, + {'name': 'Plus de 18 ans', 'locale': 'fr-FR'}, + ], + }, + '21': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 21', 'locale': 'en-US'}, + {'name': 'Plus de 21 ans', 'locale': 'fr-FR'}, + ], + }, + '65': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Senior', 'locale': 'en-US'}, + {'name': 'Senior', 'locale': 'fr-FR'}, + ], + }, + }, + 'address': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Address', 'locale': 'en-US'}, + {'name': 'Adresse', 'locale': 'fr-FR'}, + ], + 'street_address': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Street address', 'locale': 'en-US'}, + {'name': 'Rue', 'locale': 'fr-FR'}, + ], + }, + 'locality': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Locality', 'locale': 'en-US'}, + {'name': 'Ville', 'locale': 'fr-FR'}, + ], + }, + 'region': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Region', 'locale': 'en-US'}, + {'name': 'R\u00e9gion', 'locale': 'fr-FR'}, + ], + }, + 'country': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Country', 'locale': 'en-US'}, + {'name': 'Pays', 'locale': 'fr-FR'}, + ], + }, + }, + 'picture': { + 'mandatory': true, + 'value_type': 'image/jpeg', + 'display': [ + {'name': 'Picture', 'locale': 'en-US'}, + {'name': 'Portrait', 'locale': 'fr-FR'}, + ], + }, + 'age_birth_year': { + 'mandatory': true, + 'value_type': 'integer', + 'display': [ + {'name': 'Age birth year', 'locale': 'en-US'}, + {'name': 'Ann\u00e9e de naissance', 'locale': 'fr-FR'}, + ], + }, + 'dateIssued': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuance date', 'locale': 'en-US'}, + {'name': 'D\u00e9livr\u00e9 le', 'locale': 'fr-FR'}, + ], + }, + 'expiry_date': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Expiry date', 'locale': 'en-US'}, + {'name': "Date d'expiration", 'locale': 'fr-FR'}, + ], + }, + 'issuing_country': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuing country', 'locale': 'en-US'}, + {'name': "Pays d'emission", 'locale': 'fr-FR'}, + ], + }, + 'issuing_authority': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuing autority', 'locale': 'en-US'}, + {'name': "Authorit\u00e9 d'emission", 'locale': 'fr-FR'}, + ], + }, + }, + 'cryptographic_binding_methods_supported': ['DID', 'jwk'], + 'credential_signing_alg_values_supported': [ + 'ES256K', + 'ES256', + 'ES384', + 'RS256', + ], + 'vct': 'EUDI_PID_rule_book_1_0_0', + 'display': [ + { + 'name': 'EUDI PID', + 'locale': 'en-US', + 'background_color': '#14107c', + 'text_color': '#FFFFFF', + } + ], + }, + 'Pid': { + 'format': 'vc+sd-jwt', + 'scope': 'Pid_scope', + 'order': [ + 'given_name', + 'family_name', + 'birthdate', + 'address', + 'gender', + 'place_of_birth', + 'nationalities', + 'age_equal_or_over', + 'issuing_country', + 'issuing_authority', + ], + 'claims': { + 'given_name': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'First Name', 'locale': 'en-US'}, + {'name': 'Pr\u00e9nom', 'locale': 'fr-FR'}, + ], + }, + 'family_name': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Family Name', 'locale': 'en-US'}, + {'name': 'Nom', 'locale': 'fr-FR'}, + ], + }, + 'birthdate': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Birth date', 'locale': 'en-US'}, + {'name': 'Date de naissance', 'locale': 'fr-FR'}, + ], + }, + 'place_of_birth': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Birth place', 'locale': 'en-US'}, + {'name': 'Lieu de naissance', 'locale': 'fr-FR'}, + ], + 'locality': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Locality', 'locale': 'en-US'}, + {'name': 'Ville', 'locale': 'fr-FR'}, + ], + }, + 'region': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Region', 'locale': 'en-US'}, + {'name': 'R\u00e9gion', 'locale': 'fr-FR'}, + ], + }, + 'country': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Country', 'locale': 'en-US'}, + {'name': 'Pays', 'locale': 'fr-FR'}, + ], + }, + }, + 'nationalities': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Nationalities', 'locale': 'en-US'}, + {'name': 'Nationalit\u00e9s', 'locale': 'fr-FR'}, + ], + }, + 'gender': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Gender', 'locale': 'en-US'}, + {'name': 'Sexe', 'locale': 'fr-FR'}, + ], + }, + 'address': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Address', 'locale': 'en-US'}, + {'name': 'Adresse', 'locale': 'fr-FR'}, + ], + 'formatted': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Formatted', 'locale': 'en-US'}, + {'name': 'Complete', 'locale': 'fr-FR'}, + ], + }, + 'street_address': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Street address', 'locale': 'en-US'}, + {'name': 'Rue', 'locale': 'fr-FR'}, + ], + }, + 'locality': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Locality', 'locale': 'en-US'}, + {'name': 'Ville', 'locale': 'fr-FR'}, + ], + }, + 'region': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Region', 'locale': 'en-US'}, + {'name': 'R\u00e9gion', 'locale': 'fr-FR'}, + ], + }, + 'country': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Country', 'locale': 'en-US'}, + {'name': 'Pays', 'locale': 'fr-FR'}, + ], + }, + }, + 'age_equal_or_over': { + 'mandatory': true, + 'value_type': 'bool', + 'display': [ + {'name': 'Age', 'locale': 'en-US'}, + {'name': 'Age', 'locale': 'fr-FR'}, + ], + '12': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 12', 'locale': 'en-US'}, + {'name': 'Plus de 12 ans', 'locale': 'fr-FR'}, + ], + }, + '14': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 14', 'locale': 'en-US'}, + {'name': 'Plus de 14 ans', 'locale': 'fr-FR'}, + ], + }, + '16': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 16', 'locale': 'en-US'}, + {'name': 'Plus de 16 ans', 'locale': 'fr-FR'}, + ], + }, + '18': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 18', 'locale': 'en-US'}, + {'name': 'Plus de 18 ans', 'locale': 'fr-FR'}, + ], + }, + '21': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Over 21', 'locale': 'en-US'}, + {'name': 'Plus de 21 ans', 'locale': 'fr-FR'}, + ], + }, + '65': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Senior', 'locale': 'en-US'}, + {'name': 'Senior', 'locale': 'fr-FR'}, + ], + }, + }, + 'picture': { + 'mandatory': true, + 'value_type': 'image/jpeg', + 'display': [ + {'name': 'Picture', 'locale': 'en-US'}, + {'name': 'Portrait', 'locale': 'fr-FR'}, + ], + }, + 'dateIssued': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuance date', 'locale': 'en-US'}, + {'name': 'D\u00e9livr\u00e9 le', 'locale': 'fr-FR'}, + ], + }, + 'expiry_date': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Expiry date', 'locale': 'en-US'}, + {'name': "Date d'expiration", 'locale': 'fr-FR'}, + ], + }, + 'issuing_country': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuing country', 'locale': 'en-US'}, + {'name': "Pays d'emission", 'locale': 'fr-FR'}, + ], + }, + 'issuing_authority': { + 'mandatory': true, + 'value_type': 'string', + 'display': [ + {'name': 'Issuing autority', 'locale': 'en-US'}, + {'name': "Authorit\u00e9 d'emission", 'locale': 'fr-FR'}, + ], + }, + }, + 'cryptographic_binding_methods_supported': ['DID', 'jwk'], + 'credential_signing_alg_values_supported': [ + 'ES256K', + 'ES256', + 'ES384', + 'RS256', + ], + 'vct': 'urn:eu.europa.ec.eudi:pid:1', + 'display': [ + { + 'name': 'PID', + 'locale': 'en-US', + 'background_color': '#14107c', + 'text_color': '#FFFFFF', + }, + { + 'name': 'PID', + 'locale': 'fr-FR', + 'background_color': '#14107c', + 'text_color': '#FFFFFF', + } + ], + }, + }, +}; + +const openIdConfigurationTest10 = { + 'authorization_endpoint': 'https://talao.co/issuer/grlvzckofy/authorize', + 'token_endpoint': 'https://talao.co/issuer/grlvzckofy/token', + 'jwks_uri': 'https://talao.co/issuer/grlvzckofy/jwks', + 'pushed_authorization_request_endpoint': + 'https://talao.co/issuer/grlvzckofy/authorize/par', + 'require_pushed_authorization_requests': true, + 'scopes_supported': ['openid'], + 'response_types_supported': ['vp_token', 'id_token'], + 'response_modes_supported': ['query'], + 'grant_types_supported': [ + 'authorization_code', + 'urn:ietf:params:oauth:grant-type:pre-authorized_code', + ], + 'subject_types_supported': ['public', 'pairwise'], + 'id_token_signing_alg_values_supported': [ + 'ES256', + 'ES256K', + 'EdDSA', + 'RS256', + ], + 'request_object_signing_alg_values_supported': [ + 'ES256', + 'ES256K', + 'EdDSA', + 'RS256', + ], + 'request_parameter_supported': true, + 'request_uri_parameter_supported': true, + 'token_endpoint_auth_methods_supported': [ + 'client_secret_basic', + 'client_secret_post', + 'client_secret_jwt', + 'none', + ], + 'request_authentication_methods_supported': { + 'authorization_endpoint': ['request_object'], + }, + 'subject_syntax_types_supported': [ + 'urn:ietf:params:oauth:jwk-thumbprint', + 'did:key', + 'did:ebsi', + 'did:tz', + 'did:pkh', + 'did:hedera', + 'did:key', + 'did:ethr', + 'did:web', + 'did:jwk', + ], + 'subject_syntax_types_discriminations': [ + 'did:key:jwk_jcs-pub', + 'did:ebsi:v1', + ], + 'subject_trust_frameworks_supported': ['ebsi'], + 'id_token_types_supported': ['subject_signed_id_token'], +}; + +const credentialOfferJsonAuthorizedTest10 = { + 'credential_issuer': 'https://talao.co/issuer/grlvzckofy', + 'credential_configuration_ids': ['Pid'], + 'grants': { + 'authorization_code': { + 'issuer_state': 'test10', + 'authorization_server': 'https://talao.co/issuer/grlvzckofy', + }, + }, +}; + +const credentialOfferJsonPreAuthorizedTest10 = { + 'credential_issuer': 'https://talao.co/issuer/grlvzckofy', + 'credential_configuration_ids': ['Pid'], + 'grants': { + 'urn:ietf:params:oauth:grant-type:pre-authorized_code': { + 'issuer_state': 'test10', + 'authorization_server': 'https://talao.co/issuer/grlvzckofy', + }, + }, +}; diff --git a/packages/oidc4vc/test/src/oidc4vc_test.dart b/packages/oidc4vc/test/src/oidc4vc_test.dart index 82d9dac6b..c79a0db85 100644 --- a/packages/oidc4vc/test/src/oidc4vc_test.dart +++ b/packages/oidc4vc/test/src/oidc4vc_test.dart @@ -18,6 +18,8 @@ import 'package:mocktail/mocktail.dart'; import 'package:oidc4vc/oidc4vc.dart'; import 'package:secure_storage/secure_storage.dart'; +import '../configuration/configuration.dart'; + class MockPkcePair extends Mock implements PkcePair {} class MockSecureStorage extends Mock implements SecureStorageProvider {} @@ -213,6 +215,19 @@ void main() { const openIdConfiguration = '{"authorization_server":null,"credential_endpoint":"https://talao.co/issuer/mfyttabosy/credential","credential_issuer":"https://talao.co/issuer/mfyttabosy","subject_syntax_types_supported":["urn:ietf:params:oauth:jwk-thumbprint","did:key","did:ebsi","did:tz","did:pkh","did:hedera","did:key","did:ethr","did:web","did:jwk"],"token_endpoint":"https://talao.co/issuer/mfyttabosy/token","batch_endpoint":null,"authorization_endpoint":"https://talao.co/issuer/mfyttabosy/authorize","subject_trust_frameworks_supported":["ebsi"],"credentials_supported":null,"credential_configurations_supported":{"DBCGuest":{"credential_definition":{"type":["VerifiableCredential","DBCGuest"]},"display":[{"background_color":"#3B6F6D","background_image":{"alt_text":"Connected open cubes in blue with one orange cube as a background of the card","url":"https://i.ibb.co/CHqjxrJ/dbc-card-hig-res.png"},"description":"The DBC Guest credential is a DIIP example.","logo":{"alt_text":"An orange block shape, with the text Dutch Blockchain Coalition next to it, portraying the logo of the Dutch Blockchain Coalition.","url":"https://dutchblockchaincoalition.org/assets/images/icons/Logo-DBC.png"},"name":"DBC Guest (DIIP)","text_color":"#FFFFFF"},{"background_color":"#3B6F6D","background_image":{"alt_text":"Connected open cubes in blue with one orange cube as a background of the card","url":"https://i.ibb.co/CHqjxrJ/dbc-card-hig-res.png"},"description":"The DBC guest credential is a DIIP example.","locale":"en-US","logo":{"alt_text":"An orange block shape, with the text Dutch Blockchain Coalition next to it, portraying the logo of the Dutch Blockchain Coalition.","url":"https://dutchblockchaincoalition.org/assets/images/icons/Logo-DBC.png"},"name":"DBC Guest (DIIP)","text_color":"#FFFFFF"},{"background_color":"#3B6F6D","background_image":{"alt_text":"Connected open cubes in blue with one orange cube as a background of the card","url":"https://i.ibb.co/CHqjxrJ/dbc-card-hig-res.png"},"description":"De DBC gast credential is een DIIP voorbeeld.","locale":"nl-NL","logo":{"alt_text":"Aaneengesloten open blokken in de kleur blauw, met een blok in de kleur oranje, die tesamen de achtergrond van de kaart vormen.","url":"https://dutchblockchaincoalition.org/assets/images/icons/Logo-DBC.png"},"name":"DBC gast (DIIP)","text_color":"#FFFFFF"}],"format":"jwt_vc_json","scope":"DBCGuest_scope"},"EmailPass":{"credential_definition":{"type":["VerifiableCredential","EmailPass"]},"credential_signing_alg_values_supported":["ES256K","ES256","ES384","RS256"],"cryptographic_binding_methods_supported":["DID","jwk"],"display":[{"locale":"en-GB","name":"Proof of Email"}],"format":"jwt_vc_json","scope":"EmailPass_scope"},"EmployeeCredential":{"credential_definition":{"type":["VerifiableCredential","EmployeeCredential"]},"credential_signing_alg_values_supported":["ES256K","ES256","ES384","RS256"],"cryptographic_binding_methods_supported":["DID","jwk"],"display":[{"background_color":"#12107c","locale":"en-US","logo":{"alt_text":"a square logo of a university","url":"https://exampleuniversity.com/public/logo.png"},"name":"Employee Credential","text_color":"#FFFFFF"}],"format":"jwt_vc_json","scope":"EmployeeCredential_scope"},"Over18":{"credential_definition":{"type":["VerifiableCredential","Over18"]},"credential_signing_alg_values_supported":["ES256K","ES256","ES384","RS256"],"cryptographic_binding_methods_supported":["DID","jwk"],"display":[{"locale":"en-GB","name":"Over 18yo proof"},{"locale":"fr-GB","name":"Preuve de majorité"}],"format":"jwt_vc_json","scope":"Over18_scope"},"PhoneProof":{"credential_definition":{"type":["VerifiableCredential","PhoneProof"]},"credential_signing_alg_values_supported":["ES256K","ES256","ES384","RS256"],"cryptographic_binding_methods_supported":["DID","jwk"],"display":[{"locale":"en-GB","name":"Proof of phone number"}],"format":"jwt_vc_json","scope":"PhoneProof_scope"},"VerifiableId":{"credential_definition":{"credentialSubject":{"dateIssued":{"display":[{"locale":"en-US","name":"Issuance date"},{"locale":"fr-FR","name":"Délivré le"}],"mandatory":true},"dateOfBirth":{"display":[{"locale":"en-US","name":"Date of birth"},{"locale":"fr-FR","name":"Né(e) le"}],"mandatory":true},"email":{"display":[{"locale":"en-US","name":"Email"},{"locale":"fr-FR","name":"Email"}],"mandatory":true},"familyName":{"display":[{"locale":"en-US","name":"Family name"},{"locale":"fr-FR","name":"Nom"}],"mandatory":true},"firstName":{"display":[{"locale":"en-US","name":"First name"},{"locale":"fr-FR","name":"Prénom(s)"}],"mandatory":true},"gender":{"display":[{"locale":"en-US","name":"Gender"},{"locale":"fr-FR","name":"Sexe"}],"mandatory":true},"issuing_country":{"display":[{"locale":"en-US","name":"Issuing country"},{"locale":"fr-FR","name":"Délivré par"}],"mandatory":true},"phone_number":{"display":[{"locale":"en-US","name":"Phone number"},{"locale":"fr-FR","name":"Téléphone"}],"mandatory":true}},"order":["firstName","familyName","dateOfBirth","gender","dateIssued","issuing_country","email","phone_number"],"type":["VerifiableCredential","VerifiableId"]},"credential_signing_alg_values_supported":["ES256K","ES256","ES384","RS256"],"cryptographic_binding_methods_supported":["DID","jwk"],"display":[{"background_color":"#12107c","locale":"en-US","name":"Verifiable Id","text_color":"#FFFFFF"}],"format":"jwt_vc_json","scope":"VerifiableId_scope"}},"deferred_credential_endpoint":"https://talao.co/issuer/mfyttabosy/deferred","service_documentation":null,"credential_manifest":null,"credential_manifests":null,"issuer":null,"jwks_uri":"https://talao.co/issuer/mfyttabosy/jwks","grant_types_supported":["authorization_code","urn:ietf:params:oauth:grant-type:pre-authorized_code"]}'; + const credentialOfferJson = { + 'credential_offer': { + 'credential_issuer': 'https://talao.co/issuer/pcbrwbvrsi', + 'credential_configuration_ids': ['Pid'], + 'grants': { + 'authorization_code': { + 'issuer_state': 'test11', + 'authorization_server': 'https://talao.co/issuer/pcbrwbvrsi', + }, + }, + }, + }; + test( 'given Url of openid request we return Uri for authentication endpoint', () async { @@ -241,7 +256,6 @@ void main() { 'https://talao.co/issuer/mfyttabosy/.well-known/openid-credential-issuer', (request) => request.reply(200, jsonDecode(openIdConfiguration)), ); - final (authorizationEndpoint, authorizationRequestParemeters, _) = await oidc4vc.getAuthorizationData( selectedCredentials: selectedCredentials, @@ -261,6 +275,7 @@ void main() { secureAuthorizedFlow: false, issuer: issuer, dio: client, + credentialOfferJson: credentialOfferJson, secureStorage: mockSecureStorage, ); @@ -296,6 +311,7 @@ void main() { scope: false, secureAuthorizedFlow: false, vcFormatType: VCFormatType.jwtVc, + credentialOfferJson: credentialOfferJson, dio: client, ), throwsA( @@ -346,6 +362,150 @@ void main() { ); }); + group('Draft 13: getAuthorizationUriForIssuer', () { + const selectedCredentials = ['Pid']; + const clientId = '8b6pHEkmIcSvpmh3LPEM7djHQvLeFYxFkaTxb1DbfZQ'; + const redirectUri = 'https://app.altme.io/app/download/callback'; + + const issuer = 'https://talao.co/issuer/grlvzckofy'; + + const issuerState = 'test10'; + const nonce = 'de208cc1-1c17-4123-b52e-67321ef55aa1'; + + const pkcePair = PkcePair( + 'Pzy4U_sJ0J7VdIAR6JCwL5hbecv30egmJVP81VDFAnk', + '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', + ); + + const state = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiJrZFFvY1hkSzg5eEFDMTd6eFFaVjg3Q3h5eU84X25OY1oxbDF4UUpnTEI0IiwiY3JlZGVudGlhbHMiOlsiUGlkIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL2dybHZ6Y2tvZnkiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6IjhiNnBIRWttSWNTdnBtaDNMUEVNN2RqSFF2TGVGWXhGa2FUeGIxRGJmWlEiLCJjbGllbnRfYXNzZXJ0aW9uIjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4amEyVjVMVElpTENKMGVYQWlPaUozWVd4c1pYUXRZWFIwWlhOMFlYUnBiMjRyYW5kMEluMC5leUpoZFhSb2IzSnBlbUYwYVc5dVgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OWhjSEF1WVd4MGJXVXVhVzh2WVhCd0wyUnZkMjVzYjJGa0wyRjFkR2h2Y21sNlpTSXNJbU5zYVdWdWRGOXBaRjl6WTJobGJXVnpYM04xY0hCdmNuUmxaQ0k2V3lKa2FXUWlMQ0p5WldScGNtVmpkRjkxY21raUxDSjROVEE1WDNOaGJsOWtibk1pTENKMlpYSnBabWxsY2w5aGRIUmxjM1JoZEdsdmJpSmRMQ0pqYm1ZaU9uc2lhbmRySWpwN0ltTnlkaUk2SWxBdE1qVTJJaXdpYTJsa0lqb2lPR0kyY0VoRmEyMUpZMU4yY0cxb00weFFSVTAzWkdwSVVYWk1aVVpaZUVacllWUjRZakZFWW1aYVVTSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrVlFiMTk0VmtoRmFpMVFZekIxZUdKdFkzaE5hakpNTmpaUWIwZG9MWFZ2V1VkQmVtZEhTMDEyVDFFaUxDSjVJam9pUm5kR1NERjJTMVpIWDJjM1FrZGlUME5JWTNkWmNuRktkRkpJTm5WRFRGVTVhVWxpVUdGNFMxZFdRU0o5ZlN3aVpYaHdJam94TnpRNU9URXlOall3TENKbmNtRnVkRjkwZVhCbGMxOXpkWEJ3YjNKMFpXUWlPbHNpWVhWMGFHOXlhWHBoZEdsdmJsOWpiMlJsSWl3aWNISmxMV0YxZEdodmNtbDZaV1JmWTI5a1pTSmRMQ0pwWVhRaU9qRTNNVGd6TnpZMk5qQXNJbWx6Y3lJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4aUxDSnFkR2tpT2lJNFl6WmtaakZsTmkweVlUVmtMVEV4WldZdFlqUXdZeTB3WVRFMk1qZzVOVGcxTmpBaUxDSnJaWGxmZEhsd1pTSTZJbk52Wm5SM1lYSmxJaXdpYm05dVkyVWlPaUk0WXpSa05EZzJZUzB5WVRWa0xURXhaV1l0WWpRd1l5MHdZVEUyTWpnNU5UZzFOakFpTENKd2NtVnpaVzUwWVhScGIyNWZaR1ZtYVc1cGRHbHZibDkxY21sZmMzVndjRzl5ZEdWa0lqcDBjblZsTENKeVpYRjFaWE4wWDI5aWFtVmpkRjl6YVdkdWFXNW5YMkZzWjE5MllXeDFaWE5mYzNWd2NHOXlkR1ZrSWpwYklrVlRNalUySWl3aVJWTXlOVFpMSWwwc0luSmxjM0J2Ym5ObFgzUjVjR1Z6WDNOMWNIQnZjblJsWkNJNld5SjJjRjkwYjJ0bGJpSXNJbWxrWDNSdmEyVnVJbDBzSW5OMFlYUjFjeUk2ZXlKemRHRjBkWE5mYkdsemRDSTZleUpwWkhnaU9qYzFOek13TENKMWNta2lPaUpvZEhSd2N6b3ZMM1JoYkdGdkxtTnZMM05oYm1SaWIzZ3ZhWE56ZFdWeUwzTjBZWFIxYzJ4cGMzUXZNU0o5ZlN3aWMzVmlJam9pT0dJMmNFaEZhMjFKWTFOMmNHMW9NMHhRUlUwM1pHcElVWFpNWlVaWmVFWnJZVlI0WWpGRVltWmFVU0lzSW5WelpYSmZZWFYwYUdWdWRHbGpZWFJwYjI0aU9pSnplWE4wWlcxZlltbHZiV1YwY25raUxDSjJjRjltYjNKdFlYUnpYM04xY0hCdmNuUmxaQ0k2ZXlKcWQzUmZkbU5mYW5OdmJpSTZleUpoYkdkZmRtRnNkV1Z6WDNOMWNIQnZjblJsWkNJNld5SkZVekkxTmlJc0lrVlRNalUyU3lJc0lrVmtSRk5CSWwxOUxDSnFkM1JmZG5CZmFuTnZiaUk2ZXlKaGJHZGZkbUZzZFdWelgzTjFjSEJ2Y25SbFpDSTZXeUpGVXpJMU5pSXNJa1ZUTWpVMlN5SXNJa1ZrUkZOQklsMTlMQ0oyWXl0elpDMXFkM1FpT25zaVlXeG5YM1poYkhWbGMxOXpkWEJ3YjNKMFpXUWlPbHNpUlZNeU5UWWlMQ0pGVXpJMU5rc2lMQ0pGWkVSVFFTSmRmWDBzSW5kaGJHeGxkRjl1WVcxbElqb2lkR0ZzWVc5ZmQyRnNiR1YwSW4wLkdjNkJUdzFwcHF2U3VLdHhiZi1saHhoamIxSGFhQnZuV0hrMUowWk1OYWg2RDBVY3IxV3pvZlhZUGJKa2tzejNBd0xya0F4NUh5QmR0NE5QMGFuSVVBfmV5SmhiR2NpT2lKRlV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSTRZalp3U0VWcmJVbGpVM1p3YldnelRGQkZUVGRrYWtoUmRreGxSbGw0Um10aFZIaGlNVVJpWmxwUklpd2lZWFZrSWpvaWFIUjBjSE02THk5MFlXeGhieTVqYnk5cGMzTjFaWEl2WjNKc2RucGphMjltZVNJc0ltNWlaaUk2TVRjeE9EWXlPVGM0TXl3aVpYaHdJam94TnpFNE5qSTVPRFF6ZlEuRC1pX3V6S3BlWE1XMXY0N0thVWxaYl9qazNMTFN1eEQ4bVRYVnMyektka00zR3V1dEtxc2NGSEkzbjZRYUYyc2EzY29RaWhnZ1I5bGJxUFpwZGN1SXciLCJpYXQiOjE3MTg2Mjk3OTJ9.lJ3ez1qV4_gUVcpMZg-agMCgwoaaLkC8yxj5R6F-ICU'; + + const authorizationEndPoint = + 'https://app.altme.io/app/download/authorize'; + + group('test 10: LSP Potential Interop Event', () { + test( + 'authentication code flow we return Uri for authentication endpoint', + () async { + const expectedAuthorizationEndpoint = + 'https://talao.co/issuer/grlvzckofy/authorize'; + + const expectedAuthorizationRequestParemeters = { + 'response_type': 'code', + 'redirect_uri': 'https://app.altme.io/app/download/callback', + 'state': + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiJrZFFvY1hkSzg5eEFDMTd6eFFaVjg3Q3h5eU84X25OY1oxbDF4UUpnTEI0IiwiY3JlZGVudGlhbHMiOlsiUGlkIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL2dybHZ6Y2tvZnkiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6IjhiNnBIRWttSWNTdnBtaDNMUEVNN2RqSFF2TGVGWXhGa2FUeGIxRGJmWlEiLCJjbGllbnRfYXNzZXJ0aW9uIjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4amEyVjVMVElpTENKMGVYQWlPaUozWVd4c1pYUXRZWFIwWlhOMFlYUnBiMjRyYW5kMEluMC5leUpoZFhSb2IzSnBlbUYwYVc5dVgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OWhjSEF1WVd4MGJXVXVhVzh2WVhCd0wyUnZkMjVzYjJGa0wyRjFkR2h2Y21sNlpTSXNJbU5zYVdWdWRGOXBaRjl6WTJobGJXVnpYM04xY0hCdmNuUmxaQ0k2V3lKa2FXUWlMQ0p5WldScGNtVmpkRjkxY21raUxDSjROVEE1WDNOaGJsOWtibk1pTENKMlpYSnBabWxsY2w5aGRIUmxjM1JoZEdsdmJpSmRMQ0pqYm1ZaU9uc2lhbmRySWpwN0ltTnlkaUk2SWxBdE1qVTJJaXdpYTJsa0lqb2lPR0kyY0VoRmEyMUpZMU4yY0cxb00weFFSVTAzWkdwSVVYWk1aVVpaZUVacllWUjRZakZFWW1aYVVTSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrVlFiMTk0VmtoRmFpMVFZekIxZUdKdFkzaE5hakpNTmpaUWIwZG9MWFZ2V1VkQmVtZEhTMDEyVDFFaUxDSjVJam9pUm5kR1NERjJTMVpIWDJjM1FrZGlUME5JWTNkWmNuRktkRkpJTm5WRFRGVTVhVWxpVUdGNFMxZFdRU0o5ZlN3aVpYaHdJam94TnpRNU9URXlOall3TENKbmNtRnVkRjkwZVhCbGMxOXpkWEJ3YjNKMFpXUWlPbHNpWVhWMGFHOXlhWHBoZEdsdmJsOWpiMlJsSWl3aWNISmxMV0YxZEdodmNtbDZaV1JmWTI5a1pTSmRMQ0pwWVhRaU9qRTNNVGd6TnpZMk5qQXNJbWx6Y3lJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4aUxDSnFkR2tpT2lJNFl6WmtaakZsTmkweVlUVmtMVEV4WldZdFlqUXdZeTB3WVRFMk1qZzVOVGcxTmpBaUxDSnJaWGxmZEhsd1pTSTZJbk52Wm5SM1lYSmxJaXdpYm05dVkyVWlPaUk0WXpSa05EZzJZUzB5WVRWa0xURXhaV1l0WWpRd1l5MHdZVEUyTWpnNU5UZzFOakFpTENKd2NtVnpaVzUwWVhScGIyNWZaR1ZtYVc1cGRHbHZibDkxY21sZmMzVndjRzl5ZEdWa0lqcDBjblZsTENKeVpYRjFaWE4wWDI5aWFtVmpkRjl6YVdkdWFXNW5YMkZzWjE5MllXeDFaWE5mYzNWd2NHOXlkR1ZrSWpwYklrVlRNalUySWl3aVJWTXlOVFpMSWwwc0luSmxjM0J2Ym5ObFgzUjVjR1Z6WDNOMWNIQnZjblJsWkNJNld5SjJjRjkwYjJ0bGJpSXNJbWxrWDNSdmEyVnVJbDBzSW5OMFlYUjFjeUk2ZXlKemRHRjBkWE5mYkdsemRDSTZleUpwWkhnaU9qYzFOek13TENKMWNta2lPaUpvZEhSd2N6b3ZMM1JoYkdGdkxtTnZMM05oYm1SaWIzZ3ZhWE56ZFdWeUwzTjBZWFIxYzJ4cGMzUXZNU0o5ZlN3aWMzVmlJam9pT0dJMmNFaEZhMjFKWTFOMmNHMW9NMHhRUlUwM1pHcElVWFpNWlVaWmVFWnJZVlI0WWpGRVltWmFVU0lzSW5WelpYSmZZWFYwYUdWdWRHbGpZWFJwYjI0aU9pSnplWE4wWlcxZlltbHZiV1YwY25raUxDSjJjRjltYjNKdFlYUnpYM04xY0hCdmNuUmxaQ0k2ZXlKcWQzUmZkbU5mYW5OdmJpSTZleUpoYkdkZmRtRnNkV1Z6WDNOMWNIQnZjblJsWkNJNld5SkZVekkxTmlJc0lrVlRNalUyU3lJc0lrVmtSRk5CSWwxOUxDSnFkM1JmZG5CZmFuTnZiaUk2ZXlKaGJHZGZkbUZzZFdWelgzTjFjSEJ2Y25SbFpDSTZXeUpGVXpJMU5pSXNJa1ZUTWpVMlN5SXNJa1ZrUkZOQklsMTlMQ0oyWXl0elpDMXFkM1FpT25zaVlXeG5YM1poYkhWbGMxOXpkWEJ3YjNKMFpXUWlPbHNpUlZNeU5UWWlMQ0pGVXpJMU5rc2lMQ0pGWkVSVFFTSmRmWDBzSW5kaGJHeGxkRjl1WVcxbElqb2lkR0ZzWVc5ZmQyRnNiR1YwSW4wLkdjNkJUdzFwcHF2U3VLdHhiZi1saHhoamIxSGFhQnZuV0hrMUowWk1OYWg2RDBVY3IxV3pvZlhZUGJKa2tzejNBd0xya0F4NUh5QmR0NE5QMGFuSVVBfmV5SmhiR2NpT2lKRlV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSTRZalp3U0VWcmJVbGpVM1p3YldnelRGQkZUVGRrYWtoUmRreGxSbGw0Um10aFZIaGlNVVJpWmxwUklpd2lZWFZrSWpvaWFIUjBjSE02THk5MFlXeGhieTVqYnk5cGMzTjFaWEl2WjNKc2RucGphMjltZVNJc0ltNWlaaUk2TVRjeE9EWXlPVGM0TXl3aVpYaHdJam94TnpFNE5qSTVPRFF6ZlEuRC1pX3V6S3BlWE1XMXY0N0thVWxaYl9qazNMTFN1eEQ4bVRYVnMyektka00zR3V1dEtxc2NGSEkzbjZRYUYyc2EzY29RaWhnZ1I5bGJxUFpwZGN1SXciLCJpYXQiOjE3MTg2Mjk3OTJ9.lJ3ez1qV4_gUVcpMZg-agMCgwoaaLkC8yxj5R6F-ICU', + 'nonce': 'de208cc1-1c17-4123-b52e-67321ef55aa1', + 'code_challenge': '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', + 'code_challenge_method': 'S256', + 'issuer_state': 'test10', + 'client_metadata': + '%7B%22authorization_endpoint%22%3A%22https%3A%2F%2Fapp.altme.io%2Fapp%2Fdownload%2Fauthorize%22%2C%22scopes_supported%22%3A%5B%22openid%22%5D%2C%22response_types_supported%22%3A%5B%22vp_token%22%2C%22id_token%22%5D%2C%22client_id_schemes_supported%22%3A%5B%22redirect_uri%22%2C%22did%22%5D%2C%22grant_types_supported%22%3A%5B%22authorization_code%22%2C%22pre-authorized_code%22%5D%2C%22subject_types_supported%22%3A%5B%22public%22%5D%2C%22id_token_signing_alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%2C%22request_object_signing_alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%2C%22request_parameter_supported%22%3Atrue%2C%22request_uri_parameter_supported%22%3Atrue%2C%22request_authentication_methods_supported%22%3A%7B%22authorization_endpoint%22%3A%5B%22request_object%22%5D%7D%2C%22vp_formats_supported%22%3A%7B%22jwt_vp%22%3A%7B%22alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%7D%2C%22jwt_vc%22%3A%7B%22alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%7D%7D%2C%22subject_syntax_types_supported%22%3A%5B%22urn%3Aietf%3Aparams%3Aoauth%3Ajwk-thumbprint%22%2C%22did%3Akey%22%2C%22did%3Apkh%22%2C%22did%3Akey%22%2C%22did%3Apolygonid%22%5D%2C%22subject_syntax_types_discriminations%22%3A%5B%22did%3Akey%3Ajwk_jcs-pub%22%2C%22did%3Aebsi%3Av1%22%5D%2C%22subject_trust_frameworks_supported%22%3A%5B%22ebsi%22%5D%2C%22id_token_types_supported%22%3A%5B%22subject_signed_id_token%22%5D%2C%22token_endpoint_auth_method%22%3A%22client_id%22%7D', + 'client_id': '8b6pHEkmIcSvpmh3LPEM7djHQvLeFYxFkaTxb1DbfZQ', + 'scope': 'openid', + 'authorization_details': + '[{"type":"openid_credential","credential_configuration_id":"Pid"}]', + }; + + dioAdapter.onGet( + 'https://talao.co/issuer/grlvzckofy/.well-known/openid-credential-issuer', + (request) => + request.reply(200, openIdCredentialIssuerConfigurationTest10), + ); + final (authorizationEndpoint, authorizationRequestParemeters, _) = + await oidc4vc.getAuthorizationData( + selectedCredentials: selectedCredentials, + clientId: clientId, + clientSecret: null, + redirectUri: redirectUri, + issuerState: issuerState, + nonce: nonce, + pkcePair: pkcePair, + state: state, + authorizationEndPoint: authorizationEndPoint, + scope: false, + clientAuthentication: ClientAuthentication.clientId, + oidc4vciDraftType: OIDC4VCIDraftType.draft13, + vcFormatType: VCFormatType.jwtVcJson, + clientAssertion: + 'eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDp3ZWI6dGFsYW8uY28ja2V5LTIiLCJ0eXAiOiJ3YWxsZXQtYXR0ZXN0YXRpb24rand0In0.eyJhdXRob3JpemF0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly9hcHAuYWx0bWUuaW8vYXBwL2Rvd25sb2FkL2F1dGhvcml6ZSIsImNsaWVudF9pZF9zY2hlbWVzX3N1cHBvcnRlZCI6WyJkaWQiLCJyZWRpcmVjdF91cmkiLCJ4NTA5X3Nhbl9kbnMiLCJ2ZXJpZmllcl9hdHRlc3RhdGlvbiJdLCJjbmYiOnsiandrIjp7ImNydiI6IlAtMjU2Iiwia2lkIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsImt0eSI6IkVDIiwieCI6IkVQb194VkhFai1QYzB1eGJtY3hNajJMNjZQb0doLXVvWUdBemdHS012T1EiLCJ5IjoiRndGSDF2S1ZHX2c3QkdiT0NIY3dZcnFKdFJINnVDTFU5aUliUGF4S1dWQSJ9fSwiZXhwIjoxNzQ5OTEyNjYwLCJncmFudF90eXBlc19zdXBwb3J0ZWQiOlsiYXV0aG9yaXphdGlvbl9jb2RlIiwicHJlLWF1dGhvcml6ZWRfY29kZSJdLCJpYXQiOjE3MTgzNzY2NjAsImlzcyI6ImRpZDp3ZWI6dGFsYW8uY28iLCJqdGkiOiI4YzZkZjFlNi0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJrZXlfdHlwZSI6InNvZnR3YXJlIiwibm9uY2UiOiI4YzRkNDg2YS0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJwcmVzZW50YXRpb25fZGVmaW5pdGlvbl91cmlfc3VwcG9ydGVkIjp0cnVlLCJyZXF1ZXN0X29iamVjdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVTMjU2IiwiRVMyNTZLIl0sInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJ2cF90b2tlbiIsImlkX3Rva2VuIl0sInN0YXR1cyI6eyJzdGF0dXNfbGlzdCI6eyJpZHgiOjc1NzMwLCJ1cmkiOiJodHRwczovL3RhbGFvLmNvL3NhbmRib3gvaXNzdWVyL3N0YXR1c2xpc3QvMSJ9fSwic3ViIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsInVzZXJfYXV0aGVudGljYXRpb24iOiJzeXN0ZW1fYmlvbWV0cnkiLCJ2cF9mb3JtYXRzX3N1cHBvcnRlZCI6eyJqd3RfdmNfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJqd3RfdnBfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJ2YytzZC1qd3QiOnsiYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiLCJFUzI1NksiLCJFZERTQSJdfX0sIndhbGxldF9uYW1lIjoidGFsYW9fd2FsbGV0In0.Gc6BTw1ppqvSuKtxbf-lhxhjb1HaaBvnWHk1J0ZMNah6D0Ucr1WzofXYPbJkksz3AwLrkAx5HyBdt4NP0anIUA~eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4YjZwSEVrbUljU3ZwbWgzTFBFTTdkakhRdkxlRll4RmthVHhiMURiZlpRIiwiYXVkIjoiaHR0cHM6Ly90YWxhby5jby9pc3N1ZXIvZ3Jsdnpja29meSIsIm5iZiI6MTcxODYzMDkwNCwiZXhwIjoxNzE4NjMwOTY0fQ.versm2Ejz9W5uVbejGiOl1ytAoAHSeo5zZLer-hhiWBm8y1QgCmFB5xay4xWi3Nlx2KC2f1wsZ6tMVsrfZD2rg', + secureAuthorizedFlow: true, + issuer: issuer, + dio: client, + credentialOfferJson: credentialOfferJsonAuthorizedTest10, + secureStorage: mockSecureStorage, + ); + + expect(authorizationEndpoint, expectedAuthorizationEndpoint); + expect( + authorizationRequestParemeters, + expectedAuthorizationRequestParemeters, + ); + }, + ); + + test( + 'pre-authorized code flow we return Uri for authentication endpoint', + () async { + const expectedAuthorizationEndpoint = + 'https://talao.co/issuer/grlvzckofy/authorize'; + + const expectedAuthorizationRequestParemeters = { + 'response_type': 'code', + 'redirect_uri': 'https://app.altme.io/app/download/callback', + 'state': + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiJrZFFvY1hkSzg5eEFDMTd6eFFaVjg3Q3h5eU84X25OY1oxbDF4UUpnTEI0IiwiY3JlZGVudGlhbHMiOlsiUGlkIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL2dybHZ6Y2tvZnkiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6IjhiNnBIRWttSWNTdnBtaDNMUEVNN2RqSFF2TGVGWXhGa2FUeGIxRGJmWlEiLCJjbGllbnRfYXNzZXJ0aW9uIjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4amEyVjVMVElpTENKMGVYQWlPaUozWVd4c1pYUXRZWFIwWlhOMFlYUnBiMjRyYW5kMEluMC5leUpoZFhSb2IzSnBlbUYwYVc5dVgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OWhjSEF1WVd4MGJXVXVhVzh2WVhCd0wyUnZkMjVzYjJGa0wyRjFkR2h2Y21sNlpTSXNJbU5zYVdWdWRGOXBaRjl6WTJobGJXVnpYM04xY0hCdmNuUmxaQ0k2V3lKa2FXUWlMQ0p5WldScGNtVmpkRjkxY21raUxDSjROVEE1WDNOaGJsOWtibk1pTENKMlpYSnBabWxsY2w5aGRIUmxjM1JoZEdsdmJpSmRMQ0pqYm1ZaU9uc2lhbmRySWpwN0ltTnlkaUk2SWxBdE1qVTJJaXdpYTJsa0lqb2lPR0kyY0VoRmEyMUpZMU4yY0cxb00weFFSVTAzWkdwSVVYWk1aVVpaZUVacllWUjRZakZFWW1aYVVTSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrVlFiMTk0VmtoRmFpMVFZekIxZUdKdFkzaE5hakpNTmpaUWIwZG9MWFZ2V1VkQmVtZEhTMDEyVDFFaUxDSjVJam9pUm5kR1NERjJTMVpIWDJjM1FrZGlUME5JWTNkWmNuRktkRkpJTm5WRFRGVTVhVWxpVUdGNFMxZFdRU0o5ZlN3aVpYaHdJam94TnpRNU9URXlOall3TENKbmNtRnVkRjkwZVhCbGMxOXpkWEJ3YjNKMFpXUWlPbHNpWVhWMGFHOXlhWHBoZEdsdmJsOWpiMlJsSWl3aWNISmxMV0YxZEdodmNtbDZaV1JmWTI5a1pTSmRMQ0pwWVhRaU9qRTNNVGd6TnpZMk5qQXNJbWx6Y3lJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4aUxDSnFkR2tpT2lJNFl6WmtaakZsTmkweVlUVmtMVEV4WldZdFlqUXdZeTB3WVRFMk1qZzVOVGcxTmpBaUxDSnJaWGxmZEhsd1pTSTZJbk52Wm5SM1lYSmxJaXdpYm05dVkyVWlPaUk0WXpSa05EZzJZUzB5WVRWa0xURXhaV1l0WWpRd1l5MHdZVEUyTWpnNU5UZzFOakFpTENKd2NtVnpaVzUwWVhScGIyNWZaR1ZtYVc1cGRHbHZibDkxY21sZmMzVndjRzl5ZEdWa0lqcDBjblZsTENKeVpYRjFaWE4wWDI5aWFtVmpkRjl6YVdkdWFXNW5YMkZzWjE5MllXeDFaWE5mYzNWd2NHOXlkR1ZrSWpwYklrVlRNalUySWl3aVJWTXlOVFpMSWwwc0luSmxjM0J2Ym5ObFgzUjVjR1Z6WDNOMWNIQnZjblJsWkNJNld5SjJjRjkwYjJ0bGJpSXNJbWxrWDNSdmEyVnVJbDBzSW5OMFlYUjFjeUk2ZXlKemRHRjBkWE5mYkdsemRDSTZleUpwWkhnaU9qYzFOek13TENKMWNta2lPaUpvZEhSd2N6b3ZMM1JoYkdGdkxtTnZMM05oYm1SaWIzZ3ZhWE56ZFdWeUwzTjBZWFIxYzJ4cGMzUXZNU0o5ZlN3aWMzVmlJam9pT0dJMmNFaEZhMjFKWTFOMmNHMW9NMHhRUlUwM1pHcElVWFpNWlVaWmVFWnJZVlI0WWpGRVltWmFVU0lzSW5WelpYSmZZWFYwYUdWdWRHbGpZWFJwYjI0aU9pSnplWE4wWlcxZlltbHZiV1YwY25raUxDSjJjRjltYjNKdFlYUnpYM04xY0hCdmNuUmxaQ0k2ZXlKcWQzUmZkbU5mYW5OdmJpSTZleUpoYkdkZmRtRnNkV1Z6WDNOMWNIQnZjblJsWkNJNld5SkZVekkxTmlJc0lrVlRNalUyU3lJc0lrVmtSRk5CSWwxOUxDSnFkM1JmZG5CZmFuTnZiaUk2ZXlKaGJHZGZkbUZzZFdWelgzTjFjSEJ2Y25SbFpDSTZXeUpGVXpJMU5pSXNJa1ZUTWpVMlN5SXNJa1ZrUkZOQklsMTlMQ0oyWXl0elpDMXFkM1FpT25zaVlXeG5YM1poYkhWbGMxOXpkWEJ3YjNKMFpXUWlPbHNpUlZNeU5UWWlMQ0pGVXpJMU5rc2lMQ0pGWkVSVFFTSmRmWDBzSW5kaGJHeGxkRjl1WVcxbElqb2lkR0ZzWVc5ZmQyRnNiR1YwSW4wLkdjNkJUdzFwcHF2U3VLdHhiZi1saHhoamIxSGFhQnZuV0hrMUowWk1OYWg2RDBVY3IxV3pvZlhZUGJKa2tzejNBd0xya0F4NUh5QmR0NE5QMGFuSVVBfmV5SmhiR2NpT2lKRlV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSTRZalp3U0VWcmJVbGpVM1p3YldnelRGQkZUVGRrYWtoUmRreGxSbGw0Um10aFZIaGlNVVJpWmxwUklpd2lZWFZrSWpvaWFIUjBjSE02THk5MFlXeGhieTVqYnk5cGMzTjFaWEl2WjNKc2RucGphMjltZVNJc0ltNWlaaUk2TVRjeE9EWXlPVGM0TXl3aVpYaHdJam94TnpFNE5qSTVPRFF6ZlEuRC1pX3V6S3BlWE1XMXY0N0thVWxaYl9qazNMTFN1eEQ4bVRYVnMyektka00zR3V1dEtxc2NGSEkzbjZRYUYyc2EzY29RaWhnZ1I5bGJxUFpwZGN1SXciLCJpYXQiOjE3MTg2Mjk3OTJ9.lJ3ez1qV4_gUVcpMZg-agMCgwoaaLkC8yxj5R6F-ICU', + 'nonce': 'de208cc1-1c17-4123-b52e-67321ef55aa1', + 'code_challenge': '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', + 'code_challenge_method': 'S256', + 'issuer_state': 'test10', + 'client_metadata': + '%7B%22authorization_endpoint%22%3A%22https%3A%2F%2Fapp.altme.io%2Fapp%2Fdownload%2Fauthorize%22%2C%22scopes_supported%22%3A%5B%22openid%22%5D%2C%22response_types_supported%22%3A%5B%22vp_token%22%2C%22id_token%22%5D%2C%22client_id_schemes_supported%22%3A%5B%22redirect_uri%22%2C%22did%22%5D%2C%22grant_types_supported%22%3A%5B%22authorization_code%22%2C%22pre-authorized_code%22%5D%2C%22subject_types_supported%22%3A%5B%22public%22%5D%2C%22id_token_signing_alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%2C%22request_object_signing_alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%2C%22request_parameter_supported%22%3Atrue%2C%22request_uri_parameter_supported%22%3Atrue%2C%22request_authentication_methods_supported%22%3A%7B%22authorization_endpoint%22%3A%5B%22request_object%22%5D%7D%2C%22vp_formats_supported%22%3A%7B%22jwt_vp%22%3A%7B%22alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%7D%2C%22jwt_vc%22%3A%7B%22alg_values_supported%22%3A%5B%22ES256%22%2C%22ES256K%22%5D%7D%7D%2C%22subject_syntax_types_supported%22%3A%5B%22urn%3Aietf%3Aparams%3Aoauth%3Ajwk-thumbprint%22%2C%22did%3Akey%22%2C%22did%3Apkh%22%2C%22did%3Akey%22%2C%22did%3Apolygonid%22%5D%2C%22subject_syntax_types_discriminations%22%3A%5B%22did%3Akey%3Ajwk_jcs-pub%22%2C%22did%3Aebsi%3Av1%22%5D%2C%22subject_trust_frameworks_supported%22%3A%5B%22ebsi%22%5D%2C%22id_token_types_supported%22%3A%5B%22subject_signed_id_token%22%5D%2C%22token_endpoint_auth_method%22%3A%22client_id%22%7D', + 'client_id': '8b6pHEkmIcSvpmh3LPEM7djHQvLeFYxFkaTxb1DbfZQ', + 'scope': 'openid', + 'authorization_details': + '[{"type":"openid_credential","credential_configuration_id":"Pid"}]', + }; + + dioAdapter.onGet( + 'https://talao.co/issuer/grlvzckofy/.well-known/openid-credential-issuer', + (request) => + request.reply(200, openIdCredentialIssuerConfigurationTest10), + ); + final (authorizationEndpoint, authorizationRequestParemeters, _) = + await oidc4vc.getAuthorizationData( + selectedCredentials: selectedCredentials, + clientId: clientId, + clientSecret: null, + redirectUri: redirectUri, + issuerState: issuerState, + nonce: nonce, + pkcePair: pkcePair, + state: state, + authorizationEndPoint: authorizationEndPoint, + scope: false, + clientAuthentication: ClientAuthentication.clientId, + oidc4vciDraftType: OIDC4VCIDraftType.draft13, + vcFormatType: VCFormatType.jwtVcJson, + clientAssertion: + 'eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDp3ZWI6dGFsYW8uY28ja2V5LTIiLCJ0eXAiOiJ3YWxsZXQtYXR0ZXN0YXRpb24rand0In0.eyJhdXRob3JpemF0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly9hcHAuYWx0bWUuaW8vYXBwL2Rvd25sb2FkL2F1dGhvcml6ZSIsImNsaWVudF9pZF9zY2hlbWVzX3N1cHBvcnRlZCI6WyJkaWQiLCJyZWRpcmVjdF91cmkiLCJ4NTA5X3Nhbl9kbnMiLCJ2ZXJpZmllcl9hdHRlc3RhdGlvbiJdLCJjbmYiOnsiandrIjp7ImNydiI6IlAtMjU2Iiwia2lkIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsImt0eSI6IkVDIiwieCI6IkVQb194VkhFai1QYzB1eGJtY3hNajJMNjZQb0doLXVvWUdBemdHS012T1EiLCJ5IjoiRndGSDF2S1ZHX2c3QkdiT0NIY3dZcnFKdFJINnVDTFU5aUliUGF4S1dWQSJ9fSwiZXhwIjoxNzQ5OTEyNjYwLCJncmFudF90eXBlc19zdXBwb3J0ZWQiOlsiYXV0aG9yaXphdGlvbl9jb2RlIiwicHJlLWF1dGhvcml6ZWRfY29kZSJdLCJpYXQiOjE3MTgzNzY2NjAsImlzcyI6ImRpZDp3ZWI6dGFsYW8uY28iLCJqdGkiOiI4YzZkZjFlNi0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJrZXlfdHlwZSI6InNvZnR3YXJlIiwibm9uY2UiOiI4YzRkNDg2YS0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJwcmVzZW50YXRpb25fZGVmaW5pdGlvbl91cmlfc3VwcG9ydGVkIjp0cnVlLCJyZXF1ZXN0X29iamVjdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVTMjU2IiwiRVMyNTZLIl0sInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJ2cF90b2tlbiIsImlkX3Rva2VuIl0sInN0YXR1cyI6eyJzdGF0dXNfbGlzdCI6eyJpZHgiOjc1NzMwLCJ1cmkiOiJodHRwczovL3RhbGFvLmNvL3NhbmRib3gvaXNzdWVyL3N0YXR1c2xpc3QvMSJ9fSwic3ViIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsInVzZXJfYXV0aGVudGljYXRpb24iOiJzeXN0ZW1fYmlvbWV0cnkiLCJ2cF9mb3JtYXRzX3N1cHBvcnRlZCI6eyJqd3RfdmNfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJqd3RfdnBfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJ2YytzZC1qd3QiOnsiYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiLCJFUzI1NksiLCJFZERTQSJdfX0sIndhbGxldF9uYW1lIjoidGFsYW9fd2FsbGV0In0.Gc6BTw1ppqvSuKtxbf-lhxhjb1HaaBvnWHk1J0ZMNah6D0Ucr1WzofXYPbJkksz3AwLrkAx5HyBdt4NP0anIUA~eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4YjZwSEVrbUljU3ZwbWgzTFBFTTdkakhRdkxlRll4RmthVHhiMURiZlpRIiwiYXVkIjoiaHR0cHM6Ly90YWxhby5jby9pc3N1ZXIvZ3Jsdnpja29meSIsIm5iZiI6MTcxODYzMDkwNCwiZXhwIjoxNzE4NjMwOTY0fQ.versm2Ejz9W5uVbejGiOl1ytAoAHSeo5zZLer-hhiWBm8y1QgCmFB5xay4xWi3Nlx2KC2f1wsZ6tMVsrfZD2rg', + secureAuthorizedFlow: true, + issuer: issuer, + dio: client, + credentialOfferJson: credentialOfferJsonPreAuthorizedTest10, + secureStorage: mockSecureStorage, + ); + + expect(authorizationEndpoint, expectedAuthorizationEndpoint); + expect( + authorizationRequestParemeters, + expectedAuthorizationRequestParemeters, + ); + }, + ); + }); + }); + group('OIC4VC request credential', () { const issuer = 'https://talao.co/issuer/zxhaokccsi'; diff --git a/packages/oidc4vc/test/test.dart b/packages/oidc4vc/test/test.dart new file mode 100644 index 000000000..71655d2ec --- /dev/null +++ b/packages/oidc4vc/test/test.dart @@ -0,0 +1 @@ +export 'configuration/configuration.dart'; diff --git a/pubspec.lock b/pubspec.lock index 4c768bffe..0f51292d4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -973,10 +973,10 @@ packages: dependency: "direct main" description: name: flutter_olm - sha256: f98cafb434b3858d46446a93eb269a8e97eb38ccc5f8e0281b167d66d95c15dc + sha256: "9233fd8699e1dec0e4d5cfb9b0d0f7293db3308daf412c57093b69b461bb4a18" url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" flutter_openssl_crypto: dependency: "direct main" description: @@ -1307,6 +1307,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + iregexp: + dependency: transitive + description: + name: iregexp + sha256: "143859dcaeecf6f683102786762d70a47ef8441a0d2287a158172d32d38799cf" + url: "https://pub.dev" + source: hosted + version: "0.1.2" jose_plus: dependency: "direct main" description: @@ -1335,10 +1343,10 @@ packages: dependency: "direct main" description: name: json_path - sha256: "1f5a47f8d56f28ddfef5f5d7cd3d14f101dc9694aa2728e415d3d749f6abbddb" + sha256: dc25b4e2297a6bd39fb52b7d122a7787b7dab751fb278d315b54706b98bb76db url: "https://pub.dev" source: hosted - version: "0.4.4" + version: "0.7.2" json_rpc_2: dependency: transitive description: @@ -1505,6 +1513,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.7.4" + maybe_just_nothing: + dependency: transitive + description: + name: maybe_just_nothing + sha256: "0c06326e26d08f6ed43247404376366dc4d756cef23a4f1db765f546224c35e0" + url: "https://pub.dev" + source: hosted + version: "0.5.3" memoize: dependency: transitive description: @@ -1788,10 +1804,10 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.2" photo_view: dependency: transitive description: @@ -1996,10 +2012,10 @@ packages: dependency: transitive description: name: rfc_6901 - sha256: "8d97680dada633146cf75ab9382f2ce2b7e4bd63ceecd867416cf43b5832b988" + sha256: df1bbfa3d023009598f19636d6114c6ac1e0b7bb7bf6a260f0e6e6ce91416820 url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.2.0" rxdart: dependency: transitive description: @@ -2689,10 +2705,10 @@ packages: dependency: transitive description: name: xml - sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.5.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6782fdf53..f1288af52 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,7 +68,7 @@ dependencies: image_picker: ^1.0.7 jose_plus: ^0.4.5 json_annotation: ^4.8.1 - json_path: ^0.4.4 #latest version creates test issue + json_path: ^0.7.2 #latest version creates test issue jwt_decode: path: packages/jwt_decode key_generator: