Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEVISACCESSAPP-5744: InitializationError handling improvement on Android platform #37

Merged
merged 6 commits into from
May 29, 2024
26 changes: 25 additions & 1 deletion lib/domain/client_provider/client_provider.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright © 2022 Nevis Security AG. All rights reserved.

import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
Expand Down Expand Up @@ -47,8 +48,31 @@ class ClientProviderImpl implements ClientProvider {
onSuccess.call();
_operationTypeRepository.reset();
}).onError((error) {
debugPrint('Client initialization failed: ${error.runtimeType}.');
debugPrint('Client initialization failed: ${error.description}.');

// The SDK removes all the data when a rooted device or tampering
// is detected
if (Platform.isAndroid && _isNonRootedDeviceTamperingError(error)) {
// On Android the application must be closed when a generic device
// protection error is received (i.e. it is a checksum, debugger,
// emulator or instrumentation guard error)
exit(-1);
}

_errorHandler.handle(error);
}).execute();
}

bool _isNonRootedDeviceTamperingError(
InitializationError initializationError,
) {
// Return true if this is a tampering error different than rooted device
// error occurred (i.e. this is a checksum, debugger, emulator or
// instrumentation guard error).
return initializationError is InitializationDeviceProtectionError &&
initializationError is! InitializationRootedError &&
initializationError is! InitializationHardwareError &&
initializationError is! InitializationNoDeviceLockError &&
initializationError is! InitializationLockScreenHasChangedError;
}
balazs-gerlei marked this conversation as resolved.
Show resolved Hide resolved
}
2 changes: 1 addition & 1 deletion lib/domain/error/error_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class ErrorHandlerImpl extends ErrorHandler {
MobileAuthenticationClientError error,
) {
if (error is InitializationError) {
return ResultParameter.failure(description: error.description);
return ResultParameter.fatal(description: error.description);
} else if (error is OperationFidoError) {
return ResultParameter.failure(description: error.errorCode.description);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/app_state/operation_result_type.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Copyright © 2022 Nevis Security AG. All rights reserved.

enum OperationResultType { success, failure }
enum OperationResultType { success, failure, fatal }
5 changes: 5 additions & 0 deletions lib/ui/screens/result/navigation/result_parameter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ class ResultParameter {
this.errorType,
this.description,
}) : type = OperationResultType.failure;

ResultParameter.fatal({
this.errorType,
this.description,
}) : type = OperationResultType.fatal;
}
21 changes: 16 additions & 5 deletions lib/ui/screens/result/result_screen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright © 2022 Nevis Security AG. All rights reserved.

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down Expand Up @@ -69,11 +71,19 @@ class ResultContent extends StatelessWidget {
Button.outlined(
text: localization.confirmButtonTitle,
onPressed: () {
final event = NavigateToHomeEvent(
resultType: state.type,
operationType: state.operationType,
);
context.read<ResultBloc>().add(event);
// On Android the application must be closed when a fatal result
// type is received. At this moment only initialization errors are
// treated as fatal results.
if (Platform.isAndroid &&
state.type == OperationResultType.fatal) {
exit(-1);
} else {
final event = NavigateToHomeEvent(
resultType: state.type,
operationType: state.operationType,
);
context.read<ResultBloc>().add(event);
}
},
),
const SizedBox(height: 16.0),
Expand All @@ -92,6 +102,7 @@ class ResultContent extends StatelessWidget {
case OperationResultType.success:
return localizations.operationSucceededResultTitle(
state.operationType.resolve(localizations));
case OperationResultType.fatal:
case OperationResultType.failure:
return localizations.operationFailedResultTitle(
state.operationType.resolve(localizations));
Expand Down
Loading