corbado / flutter-passkeys

Easily provide passkey authentication based on FIDO2 / WebAuthn for Flutter apps (iOS & Android) via a dedicated Flutter package
https://www.corbado.com/passkeys/flutter
BSD 3-Clause "New" or "Revised" License
156 stars 35 forks source link

Removing credential from client #172

Closed rjsoph closed 1 month ago

rjsoph commented 1 month ago

I have a use case where for whatever reason a credential that was previously registered for a client becomes invalid (RP server purged it for whatever reason). This can be caused by any number of scenarios causing the server side datastore to be out of synch with the clients. Not an issue if the client loses one of its credentials (hard reset, install uninstall, but when the server loses/purges a credential in one of its clients it becomes and issue if the client has no way to remove the credential.

In my use case I allow the client to register a new credential, but this leaves it in a state where it has two credentials for the same user on the client keychain. User is asked to choose one each time they login, and if the choose the wrong one their login fails.

I would like to be able to remove/revoke a credential from the client once I detect it is no longer valid.

rjsoph commented 1 month ago

I have implemented a workaround you may want to consider.... change the code to allow findByUsername with empty username and have that method implement the random return of a Credential if username not found.... or not. That way the change is not breaking....

            List<WebAuthnCredentialRecord> credentials = authProvider.findByUsername(username).await().indefinitely();

            List<PublicKeyCredentialDescriptor> allowedCredentials;
            if (credentials.isEmpty()) {
                credentials = authProvider.findByUsername(null).await().indefinitely();
                //throw new RuntimeException("No credentials found for " + finalUsername);
            }
Dopeamin commented 1 month ago

@rjsoph Thank you for taking the time and sharing your thoughts with us.

To answer the question about credentials deletion on the client side. Sadly so far Webauthn APIs for Android and iOS don't offer any way to programmatically delete the passkeys just like you can't delete passwords when you delete your account and the user needs to manually go to his settings and delete it => thus the only solution/workaround is to rely on the server to detect the correct credential and if the credential doesn't exist then you can return an error from the server side and cancel the flow however i would not recommend returning a random credential as it might lead to unexpected behavior for the user. Ofc this all depends on your application and the UX you want to enforce in your app as someone else wouldn't mind this issue and would prefer for the users to be able to use any of their credentials thus return an empty allowCredentials.

I hope this answered your question and made things clear.

rjsoph commented 1 month ago

Anyone who needs the server to send empty credentials should initiate a challenge without a username. That said, if they provide a username and you return empty allowCredentials or even throw an error, you have not addressed the concern that some have with exposing a way for unauthenticated users to identify valid/invalid usernames opening a security vulnerability that will aid brute force attackers.... my proposal simply allow the server to return fake credentials if they so choose for a user that does not exist.... it does not force this behavior, the server could continue to return empty credentials or even throw an error as you suggest, but it gives them options.

Dopeamin commented 1 month ago

@rjsoph just to clarify, it seems to me that you are talking in a general manner and this conversation is unrelated to our packages themselves. Is anything in our packages (passkeys or corbado_auth) blocking you from implementing these behaviors ? if that is the case then please explain the issue to me.

Dopeamin commented 1 month ago

Since this topic seems to be stale. I will be closing this issue feel free to reopen it or open a new one if there are any updates or suggestions .