From 853b0cebc43e6879133cfe23550c133fff22f4da Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 3 Aug 2023 15:45:26 +0545 Subject: [PATCH] feat: Added resolver for did:web #1749 and deal with jwt and jsonLd --- .../helper_functions/helper_functions.dart | 4 -- .../cubit/credential_details_cubit.dart | 28 +++++++----- lib/scan/cubit/scan_cubit.dart | 4 +- packages/oidc4vc/lib/src/oidc4vc.dart | 45 +++++++++++++++---- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index df4537b88..95d190a13 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -101,10 +101,6 @@ String getIssuerDid({required Uri uriToCheck}) { return did; } -bool isEbsiIssuer(CredentialModel credentialModel) { - return credentialModel.issuer.startsWith('did:ebsi'); -} - bool isPolygonssuer(CredentialModel credentialModel) { return credentialModel.issuer.contains('did:polygonid'); } diff --git a/lib/dashboard/home/tab_bar/credentials/detail/cubit/credential_details_cubit.dart b/lib/dashboard/home/tab_bar/credentials/detail/cubit/credential_details_cubit.dart index 9ba831116..ca5bfd667 100644 --- a/lib/dashboard/home/tab_bar/credentials/detail/cubit/credential_details_cubit.dart +++ b/lib/dashboard/home/tab_bar/credentials/detail/cubit/credential_details_cubit.dart @@ -56,20 +56,28 @@ class CredentialDetailsCubit extends Cubit { } } - if (isEbsiIssuer(item)) { - final issuerDid = item.data['issuer']! as String; - - final encodedData = item.jwt!; - - final Map header = - decodeHeader(jwtDecode: jwtDecode, token: encodedData); - - final String issuerKid = jsonEncode(header['kid']); + if (item.jwt != null) { + /// issuer did + final issuerDid = item.issuer; + + late final String issuerKid; + late final String encodedData; + if (item.issuer.startsWith('did:web')) { + issuerKid = item.data['proof']['verificationMethod'] as String; + } else if (item.issuer.startsWith('did:ebsi')) { + encodedData = item.jwt!; + + final Map header = + decodeHeader(jwtDecode: jwtDecode, token: encodedData); + issuerKid = jsonEncode(header['kid']); + } else { + throw Exception(); + } final VerificationType isVerified = await verifyEncodedData( issuerDid, issuerKid, - item.jwt!, + encodedData, ); late CredentialStatus credentialStatus; diff --git a/lib/scan/cubit/scan_cubit.dart b/lib/scan/cubit/scan_cubit.dart index 674780932..d8f6e1706 100644 --- a/lib/scan/cubit/scan_cubit.dart +++ b/lib/scan/cubit/scan_cubit.dart @@ -219,8 +219,8 @@ class ScanCubit extends Cubit { final dynamic jsonCredential = credential is String ? jsonDecode(credential) : credential; - if (!isEbsiIssuer(credentialModel)) { - /// not verifying credential for did:ebsi issuer + if (credentialModel.jwt == null) { + /// not verifying credential for did:ebsi and did:web issuer log.i('verifying Credential'); final vcStr = jsonEncode(jsonCredential); diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index c906449c4..d3feb8e25 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -282,15 +282,44 @@ class OIDC4VC { Future>> getDidDocument(String didKey) async { try { - final didDocument = await client.get>( - 'https://api-pilot.ebsi.eu/did-registry/v3/identifiers/$didKey', - ); - return didDocument; + if (didKey.startsWith('did:ebsi')) { + final didDocument = await client.get>( + 'https://api-pilot.ebsi.eu/did-registry/v3/identifiers/$didKey', + ); + return didDocument; + } else if (didKey.startsWith('did:web')) { + final url = didWebToUrl(didKey); + final didDocument = await client.get>(url); + return didDocument; + } else { + throw Exception(); + } } catch (e) { throw Exception(e); } } + String didWebToUrl(String didKey) { + if (!didKey.startsWith('did:web:')) { + throw const FormatException('Invalid DID format'); + } + + // Extract the path after 'did:web:' + final didPath = didKey.substring('did:web:'.length); + + if (didPath.contains(':')) { + final parts = didPath.split(':'); + final domain = parts[0]; + final issuer = parts[1]; + + final url = 'https://$domain/$issuer/did.json'; + return url; + } else { + final url = 'https://$didPath/.well-known/did.json'; + return url; + } + } + String readTokenEndPoint( Response> openidConfigurationResponse, ) { @@ -318,9 +347,10 @@ class OIDC4VC { ) { final jsonPath = JsonPath(r'$..verificationMethod'); final data = (jsonPath.read(didDocumentResponse.data).first.value as List) - ..where( - (dynamic e) => e['id'].toString() == holderKid, - ).toList(); + .where( + (dynamic e) => e['id'].toString() == holderKid, + ) + .toList(); final value = data.first['publicKeyJwk']; @@ -418,7 +448,6 @@ class OIDC4VC { isVerified = await verifyJwt(jwt, publicKey); } else { - // create a JsonWebSignature from the encoded string final jws = JsonWebSignature.fromCompactSerialization(jwt); // create a JsonWebKey for verifying the signature