Skip to content

Commit

Permalink
Merge branch 'main' into TALAO
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkbee1 committed Apr 18, 2024
2 parents 474d311 + 72527d5 commit bd5049c
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 43 deletions.
13 changes: 8 additions & 5 deletions lib/app/shared/helper_functions/helper_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import 'package:altme/app/app.dart';
import 'package:altme/dashboard/dashboard.dart';
import 'package:altme/oidc4vc/oidc4vc.dart';
import 'package:altme/selective_disclosure/selective_disclosure.dart';
import 'package:asn1lib/asn1lib.dart' as asn1lib;
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:convert/convert.dart';
import 'package:credential_manifest/credential_manifest.dart';

import 'package:dartez/dartez.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';

import 'package:fast_base58/fast_base58.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:intl/intl.dart';
Expand All @@ -23,8 +22,6 @@ import 'package:key_generator/key_generator.dart';
import 'package:oidc4vc/oidc4vc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:secure_storage/secure_storage.dart';
import 'package:pointycastle/pointycastle.dart' as pc;
import 'package:asn1lib/asn1lib.dart' as asn1lib;
import 'package:x509/x509.dart' as x509;

String generateDefaultAccountName(
Expand Down Expand Up @@ -1107,6 +1104,13 @@ MessageHandler getMessageHandler(dynamic e) {
'error_description': 'The credential support format has some issues.',
},
);
} else if (stringException == 'AUTHORIZATION_DETAIL_ERROR') {
return ResponseMessage(
data: {
'error': 'unsupported_format',
'error_description': 'Invalid token response format.',
},
);
} else {
return ResponseMessage(
message:
Expand Down Expand Up @@ -1661,7 +1665,6 @@ List<String> getStringCredentialsForToken({

/// jwt_vc
presentJwtVc = format?.jwtVc != null || format?.jwtVp != null;
;

/// jwt_vc_json
presentJwtVcJson = format?.jwtVcJson != null || format?.jwtVpJson != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,6 @@ class _CredentialsDetailsViewState extends State<CredentialsDetailsView> {
.customOidc4vcProfile
.credentialManifestSupport;

final isSecure = profileData.profileSetting.selfSovereignIdentityOptions
.customOidc4vcProfile.securityLevel;

final credentialSupported = widget.credentialModel.credentialSupported;

final claims = credentialSupported?['claims'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,13 @@ class CredentialManifestOfferPickView extends StatelessWidget {
.filteredCredentialList[
credentialManifestState
.selected.first],
presentationDefinition:
presentationDefinition,
),
),

/// next button because we will now choose the claims we will present
/// next button because we will now choose
/// the claims we will present
/// from the selected credential
text: l10n.next,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:altme/app/shared/shared.dart';
import 'package:altme/dashboard/home/home.dart';
import 'package:altme/selective_disclosure/selective_disclosure.dart';
import 'package:credential_manifest/credential_manifest.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:json_annotation/json_annotation.dart';
Expand All @@ -16,6 +17,41 @@ class SelectiveDisclosureCubit extends Cubit<SelectiveDisclosureState> {

final OIDC4VC oidc4vc;

void dataFromPresentation({
required CredentialModel credentialModel,
required PresentationDefinition? presentationDefinition,
}) {
String? limitDisclosure;
final json = <String, dynamic>{};

if (presentationDefinition != null) {
final selectiveDisclosure = SelectiveDisclosure(credentialModel);

final credentialData = createJsonByDecryptingSDValues(
encryptedJson: credentialModel.data,
selectiveDisclosure: selectiveDisclosure,
);

for (final inputDescriptor in presentationDefinition.inputDescriptors) {
final filterList = inputDescriptor.constraints?.fields ?? <Field>[];

limitDisclosure = inputDescriptor.constraints?.limitDisclosure;

for (final field in filterList) {
for (final path in field.path) {
final searchList = getTextsFromCredential(path, credentialData);
for (final element in searchList) {
final key = path.split('.').toList().last;
json[key] = element;
}
}
}
}

emit(state.copyWith(limitDisclosure: limitDisclosure, filters: json));
}
}

void toggle(String claimKeyId) {
final List<String> selectedClaimsKeys = List.of(state.selectedClaimsKeyIds);

Expand Down Expand Up @@ -82,4 +118,18 @@ class SelectiveDisclosureCubit extends Cubit<SelectiveDisclosureState> {
}
emit(state.copyWith(selectedSDIndexInJWT: selected));
}

void disclosureAction({
required String claimKeyId,
required CredentialModel credentialModel,
String? threeDotValue,
String? claimsKey,
}) {
toggle(claimKeyId);
saveIndexOfSDJWT(
claimsKey: claimsKey,
credentialModel: credentialModel,
threeDotValue: threeDotValue,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class SelectiveDisclosureState extends Equatable {
this.message,
this.selectedClaimsKeyIds = const [],
this.selectedSDIndexInJWT = const [],
this.limitDisclosure,
this.filters,
});

factory SelectiveDisclosureState.fromJson(Map<String, dynamic> json) =>
Expand All @@ -14,15 +16,21 @@ class SelectiveDisclosureState extends Equatable {
final StateMessage? message;
final List<String> selectedClaimsKeyIds;
final List<int> selectedSDIndexInJWT;
final String? limitDisclosure;
final Map<String, dynamic>? filters;

SelectiveDisclosureState copyWith({
List<String>? selectedClaimsKeyIds,
List<int>? selectedSDIndexInJWT,
StateMessage? message,
String? limitDisclosure,
Map<String, dynamic>? filters,
}) {
return SelectiveDisclosureState(
selectedClaimsKeyIds: selectedClaimsKeyIds ?? this.selectedClaimsKeyIds,
selectedSDIndexInJWT: selectedSDIndexInJWT ?? this.selectedSDIndexInJWT,
limitDisclosure: limitDisclosure ?? this.limitDisclosure,
filters: filters ?? this.filters,
message: message,
);
}
Expand All @@ -34,5 +42,7 @@ class SelectiveDisclosureState extends Equatable {
selectedClaimsKeyIds,
selectedSDIndexInJWT,
message,
limitDisclosure,
filters,
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:altme/l10n/l10n.dart';
import 'package:altme/scan/cubit/scan_cubit.dart';
import 'package:altme/selective_disclosure/selective_disclosure.dart';
import 'package:altme/selective_disclosure/widget/display_selective_disclosure.dart';
import 'package:credential_manifest/credential_manifest.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:oidc4vc/oidc4vc.dart';
Expand All @@ -17,25 +18,29 @@ class SelectiveDisclosurePickPage extends StatelessWidget {
required this.credential,
required this.issuer,
required this.credentialToBePresented,
required this.presentationDefinition,
});

final Uri uri;
final CredentialModel credential;
final Issuer issuer;
final CredentialModel credentialToBePresented;
final PresentationDefinition? presentationDefinition;

static Route<dynamic> route({
required Uri uri,
required CredentialModel credential,
required Issuer issuer,
required CredentialModel credentialToBePresented,
required PresentationDefinition? presentationDefinition,
}) {
return MaterialPageRoute<void>(
builder: (context) => SelectiveDisclosurePickPage(
uri: uri,
credential: credential,
issuer: issuer,
credentialToBePresented: credentialToBePresented,
presentationDefinition: presentationDefinition,
),
settings: const RouteSettings(name: '/SelectiveDisclosurePickPage'),
);
Expand All @@ -52,24 +57,45 @@ class SelectiveDisclosurePickPage extends StatelessWidget {
credential: credential,
issuer: issuer,
credentialToBePresented: credentialToBePresented,
presentationDefinition: presentationDefinition,
),
);
}
}

class SelectiveDisclosurePickView extends StatelessWidget {
class SelectiveDisclosurePickView extends StatefulWidget {
const SelectiveDisclosurePickView({
super.key,
required this.uri,
required this.credential,
required this.issuer,
required this.credentialToBePresented,
required this.presentationDefinition,
});

final Uri uri;
final CredentialModel credential;
final Issuer issuer;
final CredentialModel credentialToBePresented;
final PresentationDefinition? presentationDefinition;

@override
State<SelectiveDisclosurePickView> createState() =>
_SelectiveDisclosurePickViewState();
}

class _SelectiveDisclosurePickViewState
extends State<SelectiveDisclosurePickView> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
context.read<SelectiveDisclosureCubit>().dataFromPresentation(
credentialModel: widget.credentialToBePresented,
presentationDefinition: widget.presentationDefinition,
);
});
}

@override
Widget build(BuildContext context) {
Expand All @@ -95,7 +121,7 @@ class SelectiveDisclosurePickView extends StatelessWidget {
context.read<ProfileCubit>().state.model.profileSetting;

final credentialImage =
SelectiveDisclosure(credentialToBePresented).getPicture;
SelectiveDisclosure(widget.credentialToBePresented).getPicture;

return BasePage(
title: l10n.thisOrganisationRequestsThisInformation,
Expand All @@ -111,22 +137,22 @@ class SelectiveDisclosurePickView extends StatelessWidget {
PictureDisplay(credentialImage: credentialImage)
else
CredentialDisplay(
credentialModel: credentialToBePresented,
credentialModel: widget.credentialToBePresented,
credDisplayType: CredDisplayType.List,
profileSetting: profileSetting,
isDiscover: false,
),
const SizedBox(height: 20),
DisplaySelectiveDisclosure(
credentialModel: credentialToBePresented,
credentialModel: widget.credentialToBePresented,
claims: null,
selectedClaimsKeyIds: state.selectedClaimsKeyIds,
selectiveDisclosureState: state,
onPressed: (claimKey, claimKeyId, threeDotValue) {
context.read<SelectiveDisclosureCubit>().toggle(claimKeyId);
context.read<SelectiveDisclosureCubit>().saveIndexOfSDJWT(
context.read<SelectiveDisclosureCubit>().disclosureAction(
claimsKey: claimKey,
credentialModel: credentialToBePresented,
credentialModel: widget.credentialToBePresented,
threeDotValue: threeDotValue,
claimKeyId: claimKeyId,
);
},
showVertically: true,
Expand All @@ -142,7 +168,7 @@ class SelectiveDisclosurePickView extends StatelessWidget {
onPressed: () => present(
context: context,
selectedSDIndexInJWT: state.selectedSDIndexInJWT,
uri: uri,
uri: widget.uri,
),
text: l10n.credentialPickPresent,
),
Expand Down Expand Up @@ -184,7 +210,7 @@ class SelectiveDisclosurePickView extends StatelessWidget {
}
}

final encryptedValues = credentialToBePresented.jwt
final encryptedValues = widget.credentialToBePresented.jwt
?.split('~')
.where((element) => element.isNotEmpty)
.toList();
Expand Down Expand Up @@ -244,17 +270,17 @@ class SelectiveDisclosurePickView extends StatelessWidget {

newJwt = '$newJwt$jwtToken';

final CredentialModel newModel =
credentialToBePresented.copyWith(selectiveDisclosureJwt: newJwt);
final CredentialModel newModel = widget.credentialToBePresented
.copyWith(selectiveDisclosureJwt: newJwt);

final credToBePresented = [newModel];

await context.read<ScanCubit>().credentialOfferOrPresent(
uri: uri,
credentialModel: credential,
credentialModel: widget.credential,
keyId: SecureStorageKeys.ssiKey,
credentialsToBePresented: credToBePresented,
issuer: issuer,
issuer: widget.issuer,
qrCodeScanCubit: context.read<QRCodeScanCubit>(),
);
} else {
Expand Down
11 changes: 8 additions & 3 deletions lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1360,8 +1360,13 @@ class QRCodeScanCubit extends Cubit<QRCodeScanState> {
}
}

if (savedAccessToken == null || savedNonce == null) {
throw Exception();
if (savedAccessToken == null) {
throw ResponseMessage(
data: {
'error': 'invalid_request',
'error_description': 'Access token is not provided.',
},
);
}

/// get credentials
Expand All @@ -1379,7 +1384,7 @@ class QRCodeScanCubit extends Cubit<QRCodeScanState> {
clientId: clientId,
profileCubit: profileCubit,
accessToken: savedAccessToken!,
nonce: savedNonce!,
nonce: savedNonce,
authorizationDetails: savedAuthorizationDetails,
openIdConfiguration: openIdConfiguration,
);
Expand Down
2 changes: 1 addition & 1 deletion lib/oidc4vc/get_credential.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Future<
required DidKeyType didKeyType,
required String? clientId,
required String accessToken,
required String nonce,
required String? nonce,
required OpenIdConfiguration openIdConfiguration,
required List<dynamic>? authorizationDetails,
}) async {
Expand Down
3 changes: 3 additions & 0 deletions lib/scan/cubit/scan_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,9 @@ class ScanCubit extends Cubit<ScanState> {
body = {'response': jwtProofOfPossession};
} else {
final presentationSubmissionString = jsonEncode(presentationSubmission);

///it is required because of bad async handling with didKit presentation
await Future<void>.delayed(const Duration(seconds: 1));
final responseData = <String, dynamic>{
'vp_token': vpToken,
'presentation_submission': presentationSubmissionString,
Expand Down
4 changes: 1 addition & 3 deletions lib/selective_disclosure/selective_disclosure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ class SelectiveDisclosure {
}
}

List<ClaimsData> getClaimsData({
required String key,
}) {
List<ClaimsData> getClaimsData({required String key}) {
dynamic data;
final value = <ClaimsData>[];
final JsonPath dataPath = JsonPath(
Expand Down
Loading

0 comments on commit bd5049c

Please sign in to comment.