-
Notifications
You must be signed in to change notification settings - Fork 46
[iOS/Android] Duplicate passkey registration not mapped to ExcludeCredentialsCanNotBeRegisteredException #232
Description
Description
When a user attempts to register a passkey that already exists on the device (duplicate registration), both iOS and Android fail to map the native error to exclude-credentials-match, causing it to surface as a generic PlatformException instead of ExcludeCredentialsCanNotBeRegisteredException.
Current Behavior
iOS
PlatformException(unknown, The operation couldn't be completed.
(com.apple.AuthenticationServices.AuthorizationError error 1006.), , null)
Android
PlatformException(android-unhandled:
androidx.credentials.TYPE_CREATE_PUBLIC_KEY_CREDENTIAL_DOM_EXCEPTION/androidx.credentials.TYPE_INVALID_STATE_ERROR,
One of the excluded credentials exists on the local device.,
One of the excluded credentials exists on the local device., null)
In both cases, the error is not caught by PasskeyAuthenticator and falls through to the generic catch block.
Expected Behavior
The error should be mapped to exclude-credentials-match and result in ExcludeCredentialsCanNotBeRegisteredException on both platforms.
Root Cause
iOS — ErrorExtension.swift
Only WKErrorDomain with code 8 is mapped to exclude-credentials-match:
if (error.domain == "WKErrorDomain" && error.code == 8) {
code = "exclude-credentials-match"
}The native ASAuthorizationError domain with code 1006 (matchedExcludedCredential) is not handled.
Android — MessageHandler.java
The existing check matches the error message:
if (Objects.equals(e.getMessage(),
"One of the excluded credentials exists on the local device")) {
platformException = new Messages.FlutterError("exclude-credentials-match", ...);
}However, when the error comes as TYPE_CREATE_PUBLIC_KEY_CREDENTIAL_DOM_EXCEPTION with sub-type TYPE_INVALID_STATE_ERROR, it appears to be caught by a different branch and classified as android-unhandled before reaching this check.
Suggested Fix
iOS
Add a condition for the ASAuthorizationError domain in ErrorExtension.swift:
} else if (error.domain == "com.apple.AuthenticationServices.AuthorizationError" && error.code == 1006) {
code = "exclude-credentials-match"
}Android
Ensure that TYPE_INVALID_STATE_ERROR with the excluded credentials message is also mapped to exclude-credentials-match.
Environment
- passkeys:
2.18.0 - Flutter 3.x