Error Handling
There is a manifold of error scenarios which can occur during the initialisation or usage of the Nevis Mobile Authentication SDK. This chapter serves to provide an overview of the most prominent or usual error scenarios as well as our recommendation on how to handle them. As every app has different requirements, the specifics are up to the customer app developers as well as the business requirements of the app itself.
The chapter will not list all errors, just the most prominent ones. Refer to the API documentation for the complete set.
SDK initialization errors
Errors during SDK initialization are grouped as InitializationError
java, swift, objc, flutter, react native.
These errors either require user interaction to resolve or cannot be resolved at all, rendering the app non-functional on the specific device. Additionally, due to platform differences not all errors are applicable to both platforms.
Error | Require user interaction | Resolvable | Android | iOS |
---|---|---|---|---|
RootedError | (✅) | ❌ | ✅ | ❌ |
DeviceProtectionError | ❌ | ❌ | ✅ | ✅ |
HardwareError | ❌ | ❌ | ✅ | ❌ |
LockScreenHasChangedError (*) | ✅ | ✅ | ✅ | ❌ |
NoDeviceLockError | ✅ | ✅ | ✅ | ✅ |
In essence, only the NoDeviceLockError
can be easily resolved by user interaction. We recommend showing the user an informational message about the necessity of creating and using a device passcode to protect the phone for security reasons.
All other errors either indicate a severe security issue (like using a rooted device) or a device not fulfilling the minimum security requirements (which is only applicable for Android devices.)
The hardening related errors DeviceProtectionError
and RootedError
can also occur during operation execution as the SDKs guard network will check the mobile devices integrity during operation execution.
Removing the device lock after registration will automatically render all registered credentials invalid for OS-managed authenticators (Android biometric, Device passcode, Android fingerprint, TouchID and FaceID) as well as the iOS Application PIN and iOS Application Password . This action will require re-registration, invalidated credentials cannot be "re-enabled".
The Android Application PIN or Android Application Password authenticators are not affected.
Recoverable errors
RecoverableError
java, swift, objc, flutter, react native indicates that the issue can be solved during the operation via user interaction. They are mainly related to the Application PIN or Application Password authenticators except for the FingerprintUerVerificationError
java which is Android specific. A recoverable error will not lead to the operation directly failing as it's not considered an operation result.
Operation errors
Operation errors occur during operation execution which leads to the onError()
callback being executed.
Most errors are grouped into OperationError
java, swift, objc, flutter, react native or OutOfBandOperationError
java, swift, objc, flutter, react native depending on the nature of the operation itself.
Depending on the underlying cause, various forms are possible:
- User interaction related errors such the user cancelling the operation or waiting for too long.
- Backend related errors such as the backend rejecting the selected user or authenticator.
- Networking related errors.
For errors who don't have a specific error type, you'll need to handle the error code.
Authentication errors
A special type of operation error is the AuthenticationError
java, swift, objc, flutter, react native as it contains the SessionProvider
accessible via sessionProvider()
Handling error codes
It's very important to be aware of the FIDO errors and handle them in an appropriate manner as FIDO-specific errors are not handled by a specific error subtype of OperationError
. The FIDO UAF error codes are also sent to the backend as part of the operation response where they are reported as client errors.
We want to point out some of the errors explicitly as they will require specific handling by the mobile application.
There is currently a slight difference in how FIDO errors are handled between the platforms.
Android
All
OperationError
objects contain aFidoErrorCode
java, swift, objc, flutter, react native accessible viaerrorCode()
describing the nature of the error. In case the error is a named error and not FIDO related, theFidoErrorCode
value isUNKNOWN
.iOS, Flutter and ReactNative
FIDO related operation errors are indicated by the
FidoErrorCode
swift, objc, flutter, react native property in the FIDO specific subtype of theOperationError
swift, objc, flutter, react native. All other, non-FIDO related errors don't have theFidoErrorCode
property.The cross-platform plugins will not propagate the
FidoErrorCode
to the Dart or TypeScript side, when the error is a specific, "named"OperationError
(for exampleOperationError.NetworkError
).The difference to Android is that an error is either a "named" error or a
FidoError
having aFidoErrorCode
whilst Android will always return aFidoErrorCode
with every error.
We intend to improve and align and simplify the error handling in this area with future SDK versions to ease app integration.
USER_LOCKOUT
This is the most prominent error, likely to occur with some frequency during the normal usage of the app and SDK.
The two scenarios leading to this error are:
Too many failed fingerprint or face verification attempts leads to the mobile OS locking the biometric authenticator.
Although this lockout cannot be resolved programmatically, it's not permanent. To unlock the biometric authenticators, the user must provide the device passcode by for example locking or unlocking the phone. Additional information can be found in the locked biometric authenticators chapter.
The user entered the PIN or password wrong too often and the brute force attack prevention locks the authenticator.
This is a permanent lockout, the Application PIN or Application Password authenticator affected must be deleted (either via deregistration or LocalData operation) and a new registration performed.
USER_CANCELED
The user canceling an operation leads to this FIDO UAF error being generated. However, this is to be considered a normal scenario where the user decides to deliberately decline an operation.
User cancellations are done by invoking the cancel()
method in the CancelableHandler
java, swift, objc, flutter, react native of the respective verification handles of the authenticator, account or authenticator selector.
When putting the app into the background, the operation is cancelled and the mobile SDK treats this as USER_CANCELED
for biometric authenticators.
USER_NOT_RESPONSIVE
This is an inactivity timout leading to the operation failing. The inactivity timeout can be configured during SDK initialisation with the userInteractionTimeoutInSeconds()
java, swift, objc, flutter, react native method.
User interaction timeouts must be shorter than the operation timeout configured in the backend. A user interaction timeout value higher than the operation timeout value will lead to a failed operation indicated by the backend responding with UAF status code 1408 - Request timeout
even if the user responded during the interaction timeout value. In this case, the SDK will still respond with USER_NOT_RESPONSIVE
.
USER_NOT_ENROLLED
The operation failed because there is no authenticator registered to the user trying to perform the operation.
NO_SUITABLE_AUTHENTICATOR
No authenticator matching the authenticator policy specified by the backend is available to service the request, or the user declined to consent to the use of a suitable authenticator. As the backend specifies the allowed authenticators for an operation, it's necessary to be aware of the policies used. The following documentation provides additional policy-related information:
UNTRUSTED_FACET_ID
This error occurs typically when there is a misconfiguration of the server: the facets defined by the FIDO UAF server do not match the configuration of the application. The Facet ID chapter provides more information.
KEY_DISAPPEARED_PERMANENTLY
This error can occur in scenarios where the private key is no longer accessible by the authenticator, for example when a new biometric credential was defined in the OS settings, and during registration it was specified to invalidate the authenticator on new credentials. As this error is non-recoverable we recommend deleting the authenticator locally and in the backend; a new authentication registration is required.
PROTOCOL_ERROR
This error is very unlikely to occur, it indicates UAF protocol violation which points to an issue with the backend. Solving this issue will require analysing the backend to determine the root cause.
AUTHENTICATOR_ACCESS_DENIED
This is a rare error which could technically occur in scenarios where there is an issue accessing the key material and the cause is neither USER_LOCKOUT
nor USER_CANCELED
.
Consider this a "generic" low-level issue by Android and iOS related to keystore access.
We ourselves have not yet seen this error during our tests.
UNKNOWN
Indicates an error which is not FIDO UAF related, in this case you’ll get a one of the specific "named" errors returned by the SDK, such as:
Unlikely to occur FIDO UAF errors
Some of the errors are very unlikely to occur in production but exist to adhere to the specification:
INSECURE_TRANSPORT
indicating a non https connection.UNSUPPORTED_VERSION
impossible to occur with the Nevis backend.INVALID_TRANSACTION_CONTENT
impossible to occur with the Nevis backend.INSUFFICIENT_AUTHENTICATOR_RESOURCES
would indicate the inability to create and store new key material in the secure hardware. We have never experienced this error so far.
Non-errors
Lastly, there are two "non-error" types:
NO_ERROR
is set as the name indicates in case no UAF operation related error occuredWAIT_USER_ACTION
is part of the normal lifecycle and is set when an authenticator is waiting for the user to provide his/her credentials.
Multi-backend errors
Two errors of note regard the SDKs multi-backend feature and usually indicate a user interaction error where the end user "accidentally" used the wrong backend:
UserAlreadyRegisteredInAnotherServer
occurs during a registration operation when the exact same username is already registered in the client and the current operation tries to register it again but with a different backend.UserNotRegisteredInServer
can only occur with usernameless authentication where the end user selected an account which is not registered in the backend which started the operation.
Out-of-band token errors
Two errors of note are specific to out of band operations:
TokenAlreadyRedeemed
indicates a "double redemption" of an out-of-band token. A token can only be used once to prevent reply attacks.TokenExpired
A redeem token has a limited lifetime controlled via the nevisFIDO instance configuration.
Both errors require a new operation to be started by dispatching a new token form the backend-side.
Out-of-band payload errors
The Nevis SDK provides methods to decode out-of-band payloads.
As the payloads are encrypted, a DecryptionError
java, swift, objc, flutter, react native can occur in two scenarios:
- The key used to decrypt the out-of-band payload does not exist anymore.
- The user is trying to redeem a token which was generated for another mobile device.
In addition, a MalformedPayload
java, swift, objc, flutter, react native error may be thrown if the SDK was unable to parse the JSON payload.
Networking and backend related errors
NetworkError
is indicating connectivity issues. Anything leading to the backend not being reachable, or the backend returning an unexpected HTTP error, will lead to this error.ClockSkewTooBig
is a quite specific error which during "normal operations" should never occur but nevertheless can during device information change, check and synchronise device information or fetching pending operations operations. The issue causing this error is a "too large" discrepancy between the servers and mobile clients system clock and can be addressed by the user updating it.OperationNotSupportedByBackend
can occur with the Nevis Identity Suite backend in case the nevisFIDO component version is too old and not supporting the operation.
As described in the NetworkError
part, issues directly related to connectivity (e.g. no internet connection at all) are not that easily distinguishable for error occurring when the backend was reachable.
We plan to improve this in future SDK versions.