Error Handling
Overview
Methods defined in the public interface of the Nevis Mobile Authentication SDK are asynchronous and will always return their result using the Result
type. This means that if something goes wrong while processing the requested operation, Result.failure(Error)
will be returned as a result.
NEVIS Errors
The SDK always returns an error of type NevisError
, which might have an underlying
error that refers to the reason, showing what led to the problem.
The NevisError
represents the list of errors that can happen in the NEVIS domain or in the FIDO layers, hence NEVIS errors contain a type (see NevisError.ErrorType
) that indicates the type of error.
- NEVIS domain: This layer is responsible for communicating with a NEVIS Mobile Authentication backend and interacts directly with the FIDO UAF Client in order to perform FIDO operations.
- FIDO layers: i.e. authenticators, ASM or FIDO UAF Client.
In case the executed operation can be determined by the time the error occurred, then the operation
property is filled with that. (See NevisOperationType
.)
The list of possible result error types is documented on each method directly.
FIDO Errors
NOTE
FIDOError
is an underlying error of aNevisError
. In these cases theErrorType
of theNevisError
isfidoError
.
All errors that are raised in the FIDO layers are defined or mapped to FIDO errors, as defined in the specifications:
- UAF Error Code Interface
- Mapping ASM Status Codes to ErrorCode
- Mapping Authenticator Status Codes to ASM Status Codes
- Authenticator Status Codes
FIDO errors contain a code (see FIDOError.Code
) that indicates the type of error as described in the UAF Error Code Interface.
Because authenticator errors are mapped to ASM errors, which are themselves mapped to FIDO Client errors, any error raised in those layers that is not part of the FIDO specifications will be mapped to a FIDO Client error (see FIDOError
). Beside FIDOError.Code
the FIDOError
struct may contain the followings:
- Such errors are represented by the
FIDOError.Code.unknown
code and may contain an optionalunderlying
error that provides more information about the exact issue. - In case the authenticator can be determined by the time the error occurred then its
aaid
is propagated.
SDK Initialization Errors
NOTE
SdkInitializationError
is an underlying error of aNevisError
. In these cases theErrorType
of theNevisError
isfailedSdkInitialization
.
Errors that can be thrown when the SDK is being initialized:
noDevicePasscodeError
: This error is thrown if there is no device passcode configured.deviceProtectionError
: This error is thrown in case the SDK detects device protection violation. (Such violation can be for example if the device is rooted, or if debugger is attached to the application process).
Recoverable Errors
Errors are considered to be recoverable if a user intervention allows an ongoing erroneous operation to be completed successfully.
These types of errors occur because of miss-typed credentials or a failed biometric authentication which don’t require the whole operation to be restarted. For errors such as this, the SDK allows for user intervention (for example re-typing the credentials) whilst still taking into consideration brute force attack prevention.
In case a recoverable error occurs, the SDK calls again the UserInteractionDelegate.verifyUser
delegate method extended with the reason of last failed attempts. This reason is stored in the UserVerification.Context.lastRecoverableError
attribute as RecoverableError
.
public enum RecoverableError {
case badPinCredentials
}
///The context provided to the user interaction delegate for a user verification.
public struct Context {
...
/// When a recoverable error occurred during the last verification of credentials, this method returns the reason of the last error.
public let lastRecoverableError: RecoverableError?
...
}
⚠️️️ This behavior is valid for all non-system authenticators (currently for only PIN authenticator).
Examples
This section provides some example code snippets to handle errors originating from the Nevis Mobile Authentication SDK.
Given an In-band Registration operation, see code snippet below.
let userInteractionDelegate: UserInteractionDelegate = ...
session.register(username: username, dispatchTargetConfiguration: dispatchTargetConfiguration, authorizationProvider: authorizationProvider, userInteractionDelegate: userInteractionDelegate) { [unowned self] result in
DispatchQueue.main.async {
switch result {
case .success:
// Handle success case
case let .failure(error):
// Handle failure cases
self.operation(.reg, didFailWith: error)
}
}
}
This can produce a variety of errors in case of failure. For a possible error handling, see code snippet below.
func operation(_ operation: NevisMobileAuthentication.Operation?, didFailWith error: Error) {
if let nevisError = error as? NevisError {
// Get the current operation that failed.
// The SDK sends back the operation in `NevisError.operation`. Should that be nil, it is still possible to get a `NevisOperationType` from an `Operation`.
let nevisOperation = nevisError.operation ?? operation?.toNevisOperationType
if let fidoError = nevisError.lastUnderlyingFIDOError() {
// Handle FIDO errors
switch fidoError.code {
...
case .authenticatorAccessDenied where nevisOperation == .registration:
// Handle authenticatorAccessDenied for registration operations
...
}
}
else {
// Handle non FIDO errors
switch nevisError.type {
...
case .networking where nevisOperation == .registration:
// Handle networking errors for registration operations
...
}
}
}
else {
// Generic error handling
}
}