From ebd822a19d1fb6f62352f7eada48bb5c34eb4008 Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Fri, 14 Jun 2024 07:43:02 +0000 Subject: [PATCH 1/3] authorization_servers draft 13 #2714 --- .../get_authorization_uri_for_issuer.dart | 6 +- .../lib/src/models/openid_configuration.dart | 4 + packages/oidc4vc/lib/src/oidc4vc.dart | 90 ++++++++++---- packages/oidc4vc/test/src/oidc4vc_test.dart | 113 +++++++++++++++++- 4 files changed, 189 insertions(+), 24 deletions(-) diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 8bcc1a66b..ad56a236c 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -98,19 +98,19 @@ 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', }; + /// error we shuld get it from final response = await client.post( '$authorizationEndpoint/par', headers: headers, diff --git a/packages/oidc4vc/lib/src/models/openid_configuration.dart b/packages/oidc4vc/lib/src/models/openid_configuration.dart index 11425f93e..6cb570fcb 100644 --- a/packages/oidc4vc/lib/src/models/openid_configuration.dart +++ b/packages/oidc4vc/lib/src/models/openid_configuration.dart @@ -9,6 +9,7 @@ class OpenIdConfiguration extends Equatable { const OpenIdConfiguration({ required this.requirePushedAuthorizationRequests, this.authorizationServer, + this.authorizationServers, this.credentialsSupported, this.credentialConfigurationsSupported, this.credentialEndpoint, @@ -32,6 +33,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') @@ -71,6 +74,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..db203d910 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,77 @@ 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 { + /// 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 List; + if (data.isNotEmpty && + listOpenIDConfiguration.contains(data.first)) { + authorizationEndpoint = '${data.first}/authorize'; + } + if (authorizationEndpoint == null) { + final jsonPathCredentialOffer = JsonPath( + // ignore: lines_longer_than_80_chars + r'$..authorization_code.authorization_server', + ); + final data = jsonPathCredentialOffer + .read(credentialOfferJson) + .first + .value as List; + if (data.isNotEmpty && + listOpenIDConfiguration.contains(data.first)) { + authorizationEndpoint = '${data.first}/authorize'; + } + } + } + } } - return authorizationEndpoint; + // If authorizationEndpoint is null, we consider the issuer + // as the authorizationEndpoint + + return authorizationEndpoint ??= '$issuer/authorize'; } String readIssuerDid( @@ -1655,7 +1705,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/test/src/oidc4vc_test.dart b/packages/oidc4vc/test/src/oidc4vc_test.dart index 82d9dac6b..a87776a2f 100644 --- a/packages/oidc4vc/test/src/oidc4vc_test.dart +++ b/packages/oidc4vc/test/src/oidc4vc_test.dart @@ -213,6 +213,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 +254,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 +273,7 @@ void main() { secureAuthorizedFlow: false, issuer: issuer, dio: client, + credentialOfferJson: credentialOfferJson, secureStorage: mockSecureStorage, ); @@ -296,6 +309,7 @@ void main() { scope: false, secureAuthorizedFlow: false, vcFormatType: VCFormatType.jwtVc, + credentialOfferJson: credentialOfferJson, dio: client, ), throwsA( @@ -346,6 +360,103 @@ void main() { ); }); + group('draft 13: getAuthorizationUriForIssuer', () { + const selectedCredentials = ['EmailPass']; + const clientId = + 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjZka1U2Wk1GSzc5V3dpY3dKNXJieEUxM3pTdWtCWTJPb0VpVlVFanFNRWMiLCJ5IjoiUm5Iem55VmxyUFNNVDdpckRzMTVEOXd4Z01vamlTREFRcGZGaHFUa0xSWSJ9'; + const redirectUri = 'https://app.altme.io/app/download/oidc4vc'; + + const issuer = 'https://talao.co/issuer/mfyttabosy'; + + const issuerState = 'test7'; + const nonce = '8b60e2fb-87f3-4401-8107-0f0128ea01ab'; + + const pkcePair = PkcePair( + 'Pzy4U_sJ0J7VdIAR6JCwL5hbecv30egmJVP81VDFAnk', + '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', + ); + + const state = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiI0S29yQ3dtWXlPLV90NGlfaHZhN0YzYUhHcFRfMldxcURoNmVyaW1lcE9BIiwiY3JlZGVudGlhbHMiOlsiRW1haWxQYXNzIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL21meXR0YWJvc3kiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6ImRpZDpqd2s6ZXlKamNuWWlPaUpRTFRJMU5pSXNJbXQwZVNJNklrVkRJaXdpZUNJNklqWmthMVUyV2sxR1N6YzVWM2RwWTNkS05YSmllRVV4TTNwVGRXdENXVEpQYjBWcFZsVkZhbkZOUldNaUxDSjVJam9pVW01SWVtNTVWbXh5VUZOTlZEZHBja1J6TVRWRU9YZDRaMDF2YW1sVFJFRlJjR1pHYUhGVWEweFNXU0o5IiwiaWF0IjoxNzE0NTQ5OTUxfQ.JJtv8H52NTvPzR3IPET1sXGALdt0yXaQBQbGvDLKNlM'; + + const authorizationEndPoint = + 'https://app.altme.io/app/download/authorize'; + + 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 { + const expectedAuthorizationEndpoint = + 'https://talao.co/issuer/mfyttabosy/authorize'; + + const expectedAuthorizationRequestParemeters = { + 'response_type': 'code', + 'redirect_uri': 'https://app.altme.io/app/download/oidc4vc', + 'state': + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiI0S29yQ3dtWXlPLV90NGlfaHZhN0YzYUhHcFRfMldxcURoNmVyaW1lcE9BIiwiY3JlZGVudGlhbHMiOlsiRW1haWxQYXNzIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL21meXR0YWJvc3kiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6ImRpZDpqd2s6ZXlKamNuWWlPaUpRTFRJMU5pSXNJbXQwZVNJNklrVkRJaXdpZUNJNklqWmthMVUyV2sxR1N6YzVWM2RwWTNkS05YSmllRVV4TTNwVGRXdENXVEpQYjBWcFZsVkZhbkZOUldNaUxDSjVJam9pVW01SWVtNTVWbXh5VUZOTlZEZHBja1J6TVRWRU9YZDRaMDF2YW1sVFJFRlJjR1pHYUhGVWEweFNXU0o5IiwiaWF0IjoxNzE0NTQ5OTUxfQ.JJtv8H52NTvPzR3IPET1sXGALdt0yXaQBQbGvDLKNlM', + 'nonce': '8b60e2fb-87f3-4401-8107-0f0128ea01ab', + 'code_challenge': '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', + 'code_challenge_method': 'S256', + 'issuer_state': 'test7', + 'client_metadata': + '{\"authorization_endpoint\":\"https://app.altme.io/app/download/authorize\",\"scopes_supported\":[\"openid\"],\"response_types_supported\":[\"vp_token\",\"id_token\"],\"client_id_schemes_supported\":[\"redirect_uri\",\"did\"],\"grant_types_supported\":[\"authorization_code\",\"pre-authorized_code\"],\"subject_types_supported\":[\"public\"],\"id_token_signing_alg_values_supported\":[\"ES256\",\"ES256K\"],\"request_object_signing_alg_values_supported\":[\"ES256\",\"ES256K\"],\"request_parameter_supported\":true,\"request_uri_parameter_supported\":true,\"request_authentication_methods_supported\":{\"authorization_endpoint\":[\"request_object\"]},\"vp_formats_supported\":{\"jwt_vp\":{\"alg_values_supported\":[\"ES256\",\"ES256K\"]},\"jwt_vc\":{\"alg_values_supported\":[\"ES256\",\"ES256K\"]}},\"subject_syntax_types_supported\":[\"urn:ietf:params:oauth:jwk-thumbprint\",\"did:key\",\"did:pkh\",\"did:key\",\"did:polygonid\"],\"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\"],\"token_endpoint_auth_method\":\"client_id\"}', + 'client_id': + 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjZka1U2Wk1GSzc5V3dpY3dKNXJieEUxM3pTdWtCWTJPb0VpVlVFanFNRWMiLCJ5IjoiUm5Iem55VmxyUFNNVDdpckRzMTVEOXd4Z01vamlTREFRcGZGaHFUa0xSWSJ9', + 'scope': 'openid', + 'authorization_details': + '[{\"type\":\"openid_credential\",\"credential_configuration_id\":\"EmailPass\"}]', + }; + + dioAdapter.onGet( + 'https://talao.co/issuer/mfyttabosy/.well-known/openid-credential-issuer', + (request) => request.reply(200, jsonDecode(openIdConfiguration)), + ); + 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: null, + secureAuthorizedFlow: false, + issuer: issuer, + dio: client, + credentialOfferJson: credentialOfferJson, + secureStorage: mockSecureStorage, + ); + + expect(authorizationEndpoint, expectedAuthorizationEndpoint); + expect( + authorizationRequestParemeters, + expectedAuthorizationRequestParemeters, + ); + }, + ); + }); + group('OIC4VC request credential', () { const issuer = 'https://talao.co/issuer/zxhaokccsi'; From 8e55c5065e3e6de7c694349aab6dbae3434c8b29 Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Tue, 18 Jun 2024 08:19:24 +0000 Subject: [PATCH 2/3] [red] draft 13 attribute authorization_servers #2714 --- .../get_authorization_uri_for_issuer.dart | 4 +- packages/credential_manifest/pubspec.yaml | 2 +- .../lib/src/models/openid_configuration.dart | 3 + packages/oidc4vc/lib/src/oidc4vc.dart | 37 +- packages/oidc4vc/pubspec.yaml | 2 +- packages/oidc4vc/test/src/oidc4vc_test.dart | 681 +++++++++++++++++- pubspec.lock | 44 +- pubspec.yaml | 2 +- 8 files changed, 703 insertions(+), 72 deletions(-) diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index ad56a236c..9dd413143 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -109,10 +109,12 @@ Future getAuthorizationUriForIssuer({ 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 6cb570fcb..d537e90a4 100644 --- a/packages/oidc4vc/lib/src/models/openid_configuration.dart +++ b/packages/oidc4vc/lib/src/models/openid_configuration.dart @@ -13,6 +13,7 @@ class OpenIdConfiguration extends Equatable { this.credentialsSupported, this.credentialConfigurationsSupported, this.credentialEndpoint, + this.pushedAuthorizationRequestEndpoint, this.credentialIssuer, this.subjectSyntaxTypesSupported, this.tokenEndpoint, @@ -47,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') diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index db203d910..1e1c21361 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -899,21 +899,21 @@ class OIDC4VC { authorizationEndpoint = '${listOpenIDConfiguration.first}/authorize'; } else { - /// 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 List; - if (data.isNotEmpty && - listOpenIDConfiguration.contains(data.first)) { - authorizationEndpoint = '${data.first}/authorize'; - } - if (authorizationEndpoint == null) { + try { + /// Extract the authorization endpoint from from + /// authorization_server in credentialOfferJson + final jsonPathCredentialOffer = JsonPath( + // ignore: lines_longer_than_80_chars + r'$..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( // ignore: lines_longer_than_80_chars r'$..authorization_code.authorization_server', @@ -921,10 +921,9 @@ class OIDC4VC { final data = jsonPathCredentialOffer .read(credentialOfferJson) .first - .value as List; - if (data.isNotEmpty && - listOpenIDConfiguration.contains(data.first)) { - authorizationEndpoint = '${data.first}/authorize'; + .value! as String; + if (data.isNotEmpty && listOpenIDConfiguration.contains(data)) { + authorizationEndpoint = '$data/authorize'; } } } 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/src/oidc4vc_test.dart b/packages/oidc4vc/test/src/oidc4vc_test.dart index a87776a2f..a0a12c912 100644 --- a/packages/oidc4vc/test/src/oidc4vc_test.dart +++ b/packages/oidc4vc/test/src/oidc4vc_test.dart @@ -361,15 +361,14 @@ void main() { }); group('draft 13: getAuthorizationUriForIssuer', () { - const selectedCredentials = ['EmailPass']; - const clientId = - 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjZka1U2Wk1GSzc5V3dpY3dKNXJieEUxM3pTdWtCWTJPb0VpVlVFanFNRWMiLCJ5IjoiUm5Iem55VmxyUFNNVDdpckRzMTVEOXd4Z01vamlTREFRcGZGaHFUa0xSWSJ9'; - const redirectUri = 'https://app.altme.io/app/download/oidc4vc'; + const selectedCredentials = ['Pid']; + const clientId = '8b6pHEkmIcSvpmh3LPEM7djHQvLeFYxFkaTxb1DbfZQ'; + const redirectUri = 'https://app.altme.io/app/download/callback'; - const issuer = 'https://talao.co/issuer/mfyttabosy'; + const issuer = 'https://talao.co/issuer/grlvzckofy'; - const issuerState = 'test7'; - const nonce = '8b60e2fb-87f3-4401-8107-0f0128ea01ab'; + const issuerState = 'test10'; + const nonce = 'de208cc1-1c17-4123-b52e-67321ef55aa1'; const pkcePair = PkcePair( 'Pzy4U_sJ0J7VdIAR6JCwL5hbecv30egmJVP81VDFAnk', @@ -377,53 +376,593 @@ void main() { ); const state = - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiI0S29yQ3dtWXlPLV90NGlfaHZhN0YzYUhHcFRfMldxcURoNmVyaW1lcE9BIiwiY3JlZGVudGlhbHMiOlsiRW1haWxQYXNzIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL21meXR0YWJvc3kiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6ImRpZDpqd2s6ZXlKamNuWWlPaUpRTFRJMU5pSXNJbXQwZVNJNklrVkRJaXdpZUNJNklqWmthMVUyV2sxR1N6YzVWM2RwWTNkS05YSmllRVV4TTNwVGRXdENXVEpQYjBWcFZsVkZhbkZOUldNaUxDSjVJam9pVW01SWVtNTVWbXh5VUZOTlZEZHBja1J6TVRWRU9YZDRaMDF2YW1sVFJFRlJjR1pHYUhGVWEweFNXU0o5IiwiaWF0IjoxNzE0NTQ5OTUxfQ.JJtv8H52NTvPzR3IPET1sXGALdt0yXaQBQbGvDLKNlM'; + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiJrZFFvY1hkSzg5eEFDMTd6eFFaVjg3Q3h5eU84X25OY1oxbDF4UUpnTEI0IiwiY3JlZGVudGlhbHMiOlsiUGlkIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL2dybHZ6Y2tvZnkiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6IjhiNnBIRWttSWNTdnBtaDNMUEVNN2RqSFF2TGVGWXhGa2FUeGIxRGJmWlEiLCJjbGllbnRfYXNzZXJ0aW9uIjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4amEyVjVMVElpTENKMGVYQWlPaUozWVd4c1pYUXRZWFIwWlhOMFlYUnBiMjRyYW5kMEluMC5leUpoZFhSb2IzSnBlbUYwYVc5dVgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OWhjSEF1WVd4MGJXVXVhVzh2WVhCd0wyUnZkMjVzYjJGa0wyRjFkR2h2Y21sNlpTSXNJbU5zYVdWdWRGOXBaRjl6WTJobGJXVnpYM04xY0hCdmNuUmxaQ0k2V3lKa2FXUWlMQ0p5WldScGNtVmpkRjkxY21raUxDSjROVEE1WDNOaGJsOWtibk1pTENKMlpYSnBabWxsY2w5aGRIUmxjM1JoZEdsdmJpSmRMQ0pqYm1ZaU9uc2lhbmRySWpwN0ltTnlkaUk2SWxBdE1qVTJJaXdpYTJsa0lqb2lPR0kyY0VoRmEyMUpZMU4yY0cxb00weFFSVTAzWkdwSVVYWk1aVVpaZUVacllWUjRZakZFWW1aYVVTSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrVlFiMTk0VmtoRmFpMVFZekIxZUdKdFkzaE5hakpNTmpaUWIwZG9MWFZ2V1VkQmVtZEhTMDEyVDFFaUxDSjVJam9pUm5kR1NERjJTMVpIWDJjM1FrZGlUME5JWTNkWmNuRktkRkpJTm5WRFRGVTVhVWxpVUdGNFMxZFdRU0o5ZlN3aVpYaHdJam94TnpRNU9URXlOall3TENKbmNtRnVkRjkwZVhCbGMxOXpkWEJ3YjNKMFpXUWlPbHNpWVhWMGFHOXlhWHBoZEdsdmJsOWpiMlJsSWl3aWNISmxMV0YxZEdodmNtbDZaV1JmWTI5a1pTSmRMQ0pwWVhRaU9qRTNNVGd6TnpZMk5qQXNJbWx6Y3lJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4aUxDSnFkR2tpT2lJNFl6WmtaakZsTmkweVlUVmtMVEV4WldZdFlqUXdZeTB3WVRFMk1qZzVOVGcxTmpBaUxDSnJaWGxmZEhsd1pTSTZJbk52Wm5SM1lYSmxJaXdpYm05dVkyVWlPaUk0WXpSa05EZzJZUzB5WVRWa0xURXhaV1l0WWpRd1l5MHdZVEUyTWpnNU5UZzFOakFpTENKd2NtVnpaVzUwWVhScGIyNWZaR1ZtYVc1cGRHbHZibDkxY21sZmMzVndjRzl5ZEdWa0lqcDBjblZsTENKeVpYRjFaWE4wWDI5aWFtVmpkRjl6YVdkdWFXNW5YMkZzWjE5MllXeDFaWE5mYzNWd2NHOXlkR1ZrSWpwYklrVlRNalUySWl3aVJWTXlOVFpMSWwwc0luSmxjM0J2Ym5ObFgzUjVjR1Z6WDNOMWNIQnZjblJsWkNJNld5SjJjRjkwYjJ0bGJpSXNJbWxrWDNSdmEyVnVJbDBzSW5OMFlYUjFjeUk2ZXlKemRHRjBkWE5mYkdsemRDSTZleUpwWkhnaU9qYzFOek13TENKMWNta2lPaUpvZEhSd2N6b3ZMM1JoYkdGdkxtTnZMM05oYm1SaWIzZ3ZhWE56ZFdWeUwzTjBZWFIxYzJ4cGMzUXZNU0o5ZlN3aWMzVmlJam9pT0dJMmNFaEZhMjFKWTFOMmNHMW9NMHhRUlUwM1pHcElVWFpNWlVaWmVFWnJZVlI0WWpGRVltWmFVU0lzSW5WelpYSmZZWFYwYUdWdWRHbGpZWFJwYjI0aU9pSnplWE4wWlcxZlltbHZiV1YwY25raUxDSjJjRjltYjNKdFlYUnpYM04xY0hCdmNuUmxaQ0k2ZXlKcWQzUmZkbU5mYW5OdmJpSTZleUpoYkdkZmRtRnNkV1Z6WDNOMWNIQnZjblJsWkNJNld5SkZVekkxTmlJc0lrVlRNalUyU3lJc0lrVmtSRk5CSWwxOUxDSnFkM1JmZG5CZmFuTnZiaUk2ZXlKaGJHZGZkbUZzZFdWelgzTjFjSEJ2Y25SbFpDSTZXeUpGVXpJMU5pSXNJa1ZUTWpVMlN5SXNJa1ZrUkZOQklsMTlMQ0oyWXl0elpDMXFkM1FpT25zaVlXeG5YM1poYkhWbGMxOXpkWEJ3YjNKMFpXUWlPbHNpUlZNeU5UWWlMQ0pGVXpJMU5rc2lMQ0pGWkVSVFFTSmRmWDBzSW5kaGJHeGxkRjl1WVcxbElqb2lkR0ZzWVc5ZmQyRnNiR1YwSW4wLkdjNkJUdzFwcHF2U3VLdHhiZi1saHhoamIxSGFhQnZuV0hrMUowWk1OYWg2RDBVY3IxV3pvZlhZUGJKa2tzejNBd0xya0F4NUh5QmR0NE5QMGFuSVVBfmV5SmhiR2NpT2lKRlV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSTRZalp3U0VWcmJVbGpVM1p3YldnelRGQkZUVGRrYWtoUmRreGxSbGw0Um10aFZIaGlNVVJpWmxwUklpd2lZWFZrSWpvaWFIUjBjSE02THk5MFlXeGhieTVqYnk5cGMzTjFaWEl2WjNKc2RucGphMjltZVNJc0ltNWlaaUk2TVRjeE9EWXlPVGM0TXl3aVpYaHdJam94TnpFNE5qSTVPRFF6ZlEuRC1pX3V6S3BlWE1XMXY0N0thVWxaYl9qazNMTFN1eEQ4bVRYVnMyektka00zR3V1dEtxc2NGSEkzbjZRYUYyc2EzY29RaWhnZ1I5bGJxUFpwZGN1SXciLCJpYXQiOjE3MTg2Mjk3OTJ9.lJ3ez1qV4_gUVcpMZg-agMCgwoaaLkC8yxj5R6F-ICU'; const authorizationEndPoint = 'https://app.altme.io/app/download/authorize'; - - 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', + const openIdCredentialIssuerConfiguration = { + '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 openIdConfiguration = { + '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'], + }; + test( - 'given Url of openid request we return Uri for authentication endpoint', + 'authentication code flow we return Uri for authentication endpoint', () async { + const credentialOfferJson = { + '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 expectedAuthorizationEndpoint = - 'https://talao.co/issuer/mfyttabosy/authorize'; + 'https://talao.co/issuer/grlvzckofy/authorize'; const expectedAuthorizationRequestParemeters = { 'response_type': 'code', - 'redirect_uri': 'https://app.altme.io/app/download/oidc4vc', + 'redirect_uri': 'https://app.altme.io/app/download/callback', 'state': - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiI0S29yQ3dtWXlPLV90NGlfaHZhN0YzYUhHcFRfMldxcURoNmVyaW1lcE9BIiwiY3JlZGVudGlhbHMiOlsiRW1haWxQYXNzIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL21meXR0YWJvc3kiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6ImRpZDpqd2s6ZXlKamNuWWlPaUpRTFRJMU5pSXNJbXQwZVNJNklrVkRJaXdpZUNJNklqWmthMVUyV2sxR1N6YzVWM2RwWTNkS05YSmllRVV4TTNwVGRXdENXVEpQYjBWcFZsVkZhbkZOUldNaUxDSjVJam9pVW01SWVtNTVWbXh5VUZOTlZEZHBja1J6TVRWRU9YZDRaMDF2YW1sVFJFRlJjR1pHYUhGVWEweFNXU0o5IiwiaWF0IjoxNzE0NTQ5OTUxfQ.JJtv8H52NTvPzR3IPET1sXGALdt0yXaQBQbGvDLKNlM', - 'nonce': '8b60e2fb-87f3-4401-8107-0f0128ea01ab', + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2RlVmVyaWZpZXIiOiJrZFFvY1hkSzg5eEFDMTd6eFFaVjg3Q3h5eU84X25OY1oxbDF4UUpnTEI0IiwiY3JlZGVudGlhbHMiOlsiUGlkIl0sImlzc3VlciI6Imh0dHBzOi8vdGFsYW8uY28vaXNzdWVyL2dybHZ6Y2tvZnkiLCJpc0VCU0lWMyI6ZmFsc2UsImNsaWVudF9pZCI6IjhiNnBIRWttSWNTdnBtaDNMUEVNN2RqSFF2TGVGWXhGa2FUeGIxRGJmWlEiLCJjbGllbnRfYXNzZXJ0aW9uIjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbXRwWkNJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4amEyVjVMVElpTENKMGVYQWlPaUozWVd4c1pYUXRZWFIwWlhOMFlYUnBiMjRyYW5kMEluMC5leUpoZFhSb2IzSnBlbUYwYVc5dVgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OWhjSEF1WVd4MGJXVXVhVzh2WVhCd0wyUnZkMjVzYjJGa0wyRjFkR2h2Y21sNlpTSXNJbU5zYVdWdWRGOXBaRjl6WTJobGJXVnpYM04xY0hCdmNuUmxaQ0k2V3lKa2FXUWlMQ0p5WldScGNtVmpkRjkxY21raUxDSjROVEE1WDNOaGJsOWtibk1pTENKMlpYSnBabWxsY2w5aGRIUmxjM1JoZEdsdmJpSmRMQ0pqYm1ZaU9uc2lhbmRySWpwN0ltTnlkaUk2SWxBdE1qVTJJaXdpYTJsa0lqb2lPR0kyY0VoRmEyMUpZMU4yY0cxb00weFFSVTAzWkdwSVVYWk1aVVpaZUVacllWUjRZakZFWW1aYVVTSXNJbXQwZVNJNklrVkRJaXdpZUNJNklrVlFiMTk0VmtoRmFpMVFZekIxZUdKdFkzaE5hakpNTmpaUWIwZG9MWFZ2V1VkQmVtZEhTMDEyVDFFaUxDSjVJam9pUm5kR1NERjJTMVpIWDJjM1FrZGlUME5JWTNkWmNuRktkRkpJTm5WRFRGVTVhVWxpVUdGNFMxZFdRU0o5ZlN3aVpYaHdJam94TnpRNU9URXlOall3TENKbmNtRnVkRjkwZVhCbGMxOXpkWEJ3YjNKMFpXUWlPbHNpWVhWMGFHOXlhWHBoZEdsdmJsOWpiMlJsSWl3aWNISmxMV0YxZEdodmNtbDZaV1JmWTI5a1pTSmRMQ0pwWVhRaU9qRTNNVGd6TnpZMk5qQXNJbWx6Y3lJNkltUnBaRHAzWldJNmRHRnNZVzh1WTI4aUxDSnFkR2tpT2lJNFl6WmtaakZsTmkweVlUVmtMVEV4WldZdFlqUXdZeTB3WVRFMk1qZzVOVGcxTmpBaUxDSnJaWGxmZEhsd1pTSTZJbk52Wm5SM1lYSmxJaXdpYm05dVkyVWlPaUk0WXpSa05EZzJZUzB5WVRWa0xURXhaV1l0WWpRd1l5MHdZVEUyTWpnNU5UZzFOakFpTENKd2NtVnpaVzUwWVhScGIyNWZaR1ZtYVc1cGRHbHZibDkxY21sZmMzVndjRzl5ZEdWa0lqcDBjblZsTENKeVpYRjFaWE4wWDI5aWFtVmpkRjl6YVdkdWFXNW5YMkZzWjE5MllXeDFaWE5mYzNWd2NHOXlkR1ZrSWpwYklrVlRNalUySWl3aVJWTXlOVFpMSWwwc0luSmxjM0J2Ym5ObFgzUjVjR1Z6WDNOMWNIQnZjblJsWkNJNld5SjJjRjkwYjJ0bGJpSXNJbWxrWDNSdmEyVnVJbDBzSW5OMFlYUjFjeUk2ZXlKemRHRjBkWE5mYkdsemRDSTZleUpwWkhnaU9qYzFOek13TENKMWNta2lPaUpvZEhSd2N6b3ZMM1JoYkdGdkxtTnZMM05oYm1SaWIzZ3ZhWE56ZFdWeUwzTjBZWFIxYzJ4cGMzUXZNU0o5ZlN3aWMzVmlJam9pT0dJMmNFaEZhMjFKWTFOMmNHMW9NMHhRUlUwM1pHcElVWFpNWlVaWmVFWnJZVlI0WWpGRVltWmFVU0lzSW5WelpYSmZZWFYwYUdWdWRHbGpZWFJwYjI0aU9pSnplWE4wWlcxZlltbHZiV1YwY25raUxDSjJjRjltYjNKdFlYUnpYM04xY0hCdmNuUmxaQ0k2ZXlKcWQzUmZkbU5mYW5OdmJpSTZleUpoYkdkZmRtRnNkV1Z6WDNOMWNIQnZjblJsWkNJNld5SkZVekkxTmlJc0lrVlRNalUyU3lJc0lrVmtSRk5CSWwxOUxDSnFkM1JmZG5CZmFuTnZiaUk2ZXlKaGJHZGZkbUZzZFdWelgzTjFjSEJ2Y25SbFpDSTZXeUpGVXpJMU5pSXNJa1ZUTWpVMlN5SXNJa1ZrUkZOQklsMTlMQ0oyWXl0elpDMXFkM1FpT25zaVlXeG5YM1poYkhWbGMxOXpkWEJ3YjNKMFpXUWlPbHNpUlZNeU5UWWlMQ0pGVXpJMU5rc2lMQ0pGWkVSVFFTSmRmWDBzSW5kaGJHeGxkRjl1WVcxbElqb2lkR0ZzWVc5ZmQyRnNiR1YwSW4wLkdjNkJUdzFwcHF2U3VLdHhiZi1saHhoamIxSGFhQnZuV0hrMUowWk1OYWg2RDBVY3IxV3pvZlhZUGJKa2tzejNBd0xya0F4NUh5QmR0NE5QMGFuSVVBfmV5SmhiR2NpT2lKRlV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpwYzNNaU9pSTRZalp3U0VWcmJVbGpVM1p3YldnelRGQkZUVGRrYWtoUmRreGxSbGw0Um10aFZIaGlNVVJpWmxwUklpd2lZWFZrSWpvaWFIUjBjSE02THk5MFlXeGhieTVqYnk5cGMzTjFaWEl2WjNKc2RucGphMjltZVNJc0ltNWlaaUk2TVRjeE9EWXlPVGM0TXl3aVpYaHdJam94TnpFNE5qSTVPRFF6ZlEuRC1pX3V6S3BlWE1XMXY0N0thVWxaYl9qazNMTFN1eEQ4bVRYVnMyektka00zR3V1dEtxc2NGSEkzbjZRYUYyc2EzY29RaWhnZ1I5bGJxUFpwZGN1SXciLCJpYXQiOjE3MTg2Mjk3OTJ9.lJ3ez1qV4_gUVcpMZg-agMCgwoaaLkC8yxj5R6F-ICU', + 'nonce': 'de208cc1-1c17-4123-b52e-67321ef55aa1', 'code_challenge': '4KorCwmYyO-_t4i_hva7F3aHGpT_2WqqDh6erimepOA', 'code_challenge_method': 'S256', - 'issuer_state': 'test7', + 'issuer_state': 'test10', 'client_metadata': - '{\"authorization_endpoint\":\"https://app.altme.io/app/download/authorize\",\"scopes_supported\":[\"openid\"],\"response_types_supported\":[\"vp_token\",\"id_token\"],\"client_id_schemes_supported\":[\"redirect_uri\",\"did\"],\"grant_types_supported\":[\"authorization_code\",\"pre-authorized_code\"],\"subject_types_supported\":[\"public\"],\"id_token_signing_alg_values_supported\":[\"ES256\",\"ES256K\"],\"request_object_signing_alg_values_supported\":[\"ES256\",\"ES256K\"],\"request_parameter_supported\":true,\"request_uri_parameter_supported\":true,\"request_authentication_methods_supported\":{\"authorization_endpoint\":[\"request_object\"]},\"vp_formats_supported\":{\"jwt_vp\":{\"alg_values_supported\":[\"ES256\",\"ES256K\"]},\"jwt_vc\":{\"alg_values_supported\":[\"ES256\",\"ES256K\"]}},\"subject_syntax_types_supported\":[\"urn:ietf:params:oauth:jwk-thumbprint\",\"did:key\",\"did:pkh\",\"did:key\",\"did:polygonid\"],\"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\"],\"token_endpoint_auth_method\":\"client_id\"}', - 'client_id': - 'did:jwk:eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjZka1U2Wk1GSzc5V3dpY3dKNXJieEUxM3pTdWtCWTJPb0VpVlVFanFNRWMiLCJ5IjoiUm5Iem55VmxyUFNNVDdpckRzMTVEOXd4Z01vamlTREFRcGZGaHFUa0xSWSJ9', + '%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\":\"EmailPass\"}]', + '[{"type":"openid_credential","credential_configuration_id":"Pid"}]', }; dioAdapter.onGet( - 'https://talao.co/issuer/mfyttabosy/.well-known/openid-credential-issuer', - (request) => request.reply(200, jsonDecode(openIdConfiguration)), + 'https://talao.co/issuer/grlvzckofy/.well-known/openid-credential-issuer', + (request) => + request.reply(200, openIdCredentialIssuerConfiguration), ); final (authorizationEndpoint, authorizationRequestParemeters, _) = await oidc4vc.getAuthorizationData( @@ -440,15 +979,87 @@ void main() { clientAuthentication: ClientAuthentication.clientId, oidc4vciDraftType: OIDC4VCIDraftType.draft13, vcFormatType: VCFormatType.jwtVcJson, - clientAssertion: null, - secureAuthorizedFlow: false, + clientAssertion: + 'eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDp3ZWI6dGFsYW8uY28ja2V5LTIiLCJ0eXAiOiJ3YWxsZXQtYXR0ZXN0YXRpb24rand0In0.eyJhdXRob3JpemF0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly9hcHAuYWx0bWUuaW8vYXBwL2Rvd25sb2FkL2F1dGhvcml6ZSIsImNsaWVudF9pZF9zY2hlbWVzX3N1cHBvcnRlZCI6WyJkaWQiLCJyZWRpcmVjdF91cmkiLCJ4NTA5X3Nhbl9kbnMiLCJ2ZXJpZmllcl9hdHRlc3RhdGlvbiJdLCJjbmYiOnsiandrIjp7ImNydiI6IlAtMjU2Iiwia2lkIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsImt0eSI6IkVDIiwieCI6IkVQb194VkhFai1QYzB1eGJtY3hNajJMNjZQb0doLXVvWUdBemdHS012T1EiLCJ5IjoiRndGSDF2S1ZHX2c3QkdiT0NIY3dZcnFKdFJINnVDTFU5aUliUGF4S1dWQSJ9fSwiZXhwIjoxNzQ5OTEyNjYwLCJncmFudF90eXBlc19zdXBwb3J0ZWQiOlsiYXV0aG9yaXphdGlvbl9jb2RlIiwicHJlLWF1dGhvcml6ZWRfY29kZSJdLCJpYXQiOjE3MTgzNzY2NjAsImlzcyI6ImRpZDp3ZWI6dGFsYW8uY28iLCJqdGkiOiI4YzZkZjFlNi0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJrZXlfdHlwZSI6InNvZnR3YXJlIiwibm9uY2UiOiI4YzRkNDg2YS0yYTVkLTExZWYtYjQwYy0wYTE2Mjg5NTg1NjAiLCJwcmVzZW50YXRpb25fZGVmaW5pdGlvbl91cmlfc3VwcG9ydGVkIjp0cnVlLCJyZXF1ZXN0X29iamVjdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVTMjU2IiwiRVMyNTZLIl0sInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJ2cF90b2tlbiIsImlkX3Rva2VuIl0sInN0YXR1cyI6eyJzdGF0dXNfbGlzdCI6eyJpZHgiOjc1NzMwLCJ1cmkiOiJodHRwczovL3RhbGFvLmNvL3NhbmRib3gvaXNzdWVyL3N0YXR1c2xpc3QvMSJ9fSwic3ViIjoiOGI2cEhFa21JY1N2cG1oM0xQRU03ZGpIUXZMZUZZeEZrYVR4YjFEYmZaUSIsInVzZXJfYXV0aGVudGljYXRpb24iOiJzeXN0ZW1fYmlvbWV0cnkiLCJ2cF9mb3JtYXRzX3N1cHBvcnRlZCI6eyJqd3RfdmNfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJqd3RfdnBfanNvbiI6eyJhbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFUzI1NiIsIkVTMjU2SyIsIkVkRFNBIl19LCJ2YytzZC1qd3QiOnsiYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiLCJFUzI1NksiLCJFZERTQSJdfX0sIndhbGxldF9uYW1lIjoidGFsYW9fd2FsbGV0In0.Gc6BTw1ppqvSuKtxbf-lhxhjb1HaaBvnWHk1J0ZMNah6D0Ucr1WzofXYPbJkksz3AwLrkAx5HyBdt4NP0anIUA~eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4YjZwSEVrbUljU3ZwbWgzTFBFTTdkakhRdkxlRll4RmthVHhiMURiZlpRIiwiYXVkIjoiaHR0cHM6Ly90YWxhby5jby9pc3N1ZXIvZ3Jsdnpja29meSIsIm5iZiI6MTcxODYzMDkwNCwiZXhwIjoxNzE4NjMwOTY0fQ.versm2Ejz9W5uVbejGiOl1ytAoAHSeo5zZLer-hhiWBm8y1QgCmFB5xay4xWi3Nlx2KC2f1wsZ6tMVsrfZD2rg', + secureAuthorizedFlow: true, issuer: issuer, dio: client, credentialOfferJson: credentialOfferJson, secureStorage: mockSecureStorage, ); - expect(authorizationEndpoint, expectedAuthorizationEndpoint); + expect(authorizationEndpoint, expectedAuthorizationEndpoint); + expect( + authorizationRequestParemeters, + expectedAuthorizationRequestParemeters, + ); + }, + ); + + test( + 'pre-authorized code flow we return Uri for authentication endpoint', + () async { + const credentialOfferJson = { + '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', + }, + }, + }; + + 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, openIdCredentialIssuerConfiguration), + ); + 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: credentialOfferJson, + secureStorage: mockSecureStorage, + ); + + expect(authorizationEndpoint, expectedAuthorizationEndpoint); expect( authorizationRequestParemeters, expectedAuthorizationRequestParemeters, diff --git a/pubspec.lock b/pubspec.lock index a79f4c7e3..a3abf64fa 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: @@ -1557,10 +1573,10 @@ packages: dependency: "direct dev" description: name: mocktail - sha256: c4b5007d91ca4f67256e720cb1b6d704e79a510183a12fa551021f652577dce6 + sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" model_viewer_plus: dependency: "direct main" description: @@ -1748,10 +1764,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5" + sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54 url: "https://pub.dev" source: hosted - version: "12.0.6" + version: "12.0.7" permission_handler_apple: 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 1a30f23be..a3da5ee20 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: From 627f7ef875963b9454119b65fb9fb0f67b45726f Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 18 Jun 2024 15:21:32 +0545 Subject: [PATCH 3/3] fix: Solve issue for JsonPath with pre-authorized value --- packages/oidc4vc/lib/src/oidc4vc.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index 1e1c21361..3ee2b6f90 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -904,7 +904,7 @@ class OIDC4VC { /// authorization_server in credentialOfferJson final jsonPathCredentialOffer = JsonPath( // ignore: lines_longer_than_80_chars - r'$..authorized_code.authorization_server', + r'$..["urn:ietf:params:oauth:grant-type:pre-authorized_code"].authorization_server', ); final data = jsonPathCredentialOffer .read(credentialOfferJson) @@ -915,7 +915,6 @@ class OIDC4VC { } } catch (e) { final jsonPathCredentialOffer = JsonPath( - // ignore: lines_longer_than_80_chars r'$..authorization_code.authorization_server', ); final data = jsonPathCredentialOffer