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

Provide a method to get the count of the credentials of a rely party on client device on user permission #2255

Closed
bigradish opened this issue Feb 6, 2025 · 15 comments

Comments

@bigradish
Copy link

The method asks the user to release the information and returns a Promise which is resolved with the count when the user permits, and is rejected with a deniedByUser exception when the user denies.
This method can help the website to limit the number of accounts a user can register on it, and at the same time respects users' privacy.

@emlun
Copy link
Member

emlun commented Feb 6, 2025

This will not work the way you want, it will be trivial to circumvent:

window.PublicKeyCredential.getNumberOfCredentialsWithUserPermission = async function (options) {
  return 0;
};

Sure, not all users will know to do this. But once it becomes commonly known that websites use this technique, it will be equally trivial to create a browser extension that does this, or share it as a scriptlet that you can just paste into the console to bypass such site restrictions. Which is in itself harmful too: normalizing the idea of running strangers' code will lead to all kinds of malicious abuse.

The problem is that you do not trust your users to obey your terms of service, so you're asking for the browser to enforce your ToS. But the browser is the user's agent, in the user's control, so you cannot trust the browser to do it either. The user can just choose a browser that doesn't enforce your demands. This approach can never work, because the premise contradicts itself.

Therefore I am against this. Even with a permission prompt, this would be a net loss for privacy since we don't even gain any benefit in exchange, given that it wouldn't serve its purpose anyway.

@emlun
Copy link
Member

emlun commented Feb 6, 2025

(See also previous discussion in #2222)

@yackermann
Copy link
Contributor

@bigradish @emlun Not only that, but there are technical limitations as well.

  1. Platforms are no longer monolith, but a plugin ecosystem, that allows third party providers, like Dashlane, 1Password, etc to provide passkeys. This means that they would have to have API, that allows non-authorized enumeration of the credentials, which is not only technically might not be possible (see encryption), but would be a gross privacy violation (see russian govt wanting to know where u have accounts).
  2. Passkey providers might not even know how many credentials they have. If they do non-exportable non-discoverable credentials, that are stored in secure enclave, and they don't allow user manage them, like it works in FIDO2/U2F, then it might not even know that it has those credentials.
  3. Security keys exist, and user can plug them in after you request authentication. And again, if they are non-discoverable, then security keys won't be able to enumerate them.

Passkeys are not meant to deal with T&C of the website. It's a tool to sign challenges, that happens to be useful as a part of authentication.

@bigradish
Copy link
Author

@emlun @yackermann Thank you very much for your reasonable explanation.
I'm thinking this solution: In the CredentialsContainer.create() method, add an option to ask the user to let the authenticator return its GUID in the response. If the user denies or the auhenticator fails to do this, the create method fails with exceptions.
This requires that all authenticators have their GUIDs.
How do you think of this?

@Firstyear
Copy link
Contributor

@bigradish What are you trying to achieve here? What's the end goal? I feel like your making technical suggestions to solve a problem you have, but without explaining what your problem is.

@bigradish
Copy link
Author

@Firstyear Hi, I use pure webauthn to let users register accounts on my site and try to find a way to limit the number of accounts a user can register.
If authenticators have their GUIDs and provide them in the result of the create method, they can be identified on the server side, and then the goal can be achieved.

@nicksteele
Copy link
Contributor

By GUID do you mean the AAGUID?

@nicksteele
Copy link
Contributor

Assuming you mean the AAGUID, that is not actually a unique identifier of the specific authenticator that is being used. For instance, 1Password's AAGUID just identifies that the request was handled by an instance of 1Password

@Firstyear
Copy link
Contributor

@Firstyear Hi, I use pure webauthn to let users register accounts on my site and try to find a way to limit the number of accounts a user can register. If authenticators have their GUIDs and provide them in the result of the create method, they can be identified on the server side, and then the goal can be achieved.

You can't achieve this with webauthn. There is no way to limit or track users based on the authenticator they register.

You need to find other ways to limit account sign ups.

@yackermann
Copy link
Contributor

@bigradish

That would disclose privacy sensitive information, as well as wont solve anything else.

Use can have multiple passkey providers. Each would have to ask user consent, or you will have limited scope, one password manager. User can as well export credential, delete it, register, re-import.

Or user can custom credential provider. Or passkey manager decides to lie because of privacy.

And again, this does not solves issue of non-discoverable credentials, and security keys.

And lastly, what if the same laptop is used by both wife, and husband? In that case you would stop husband from registering?

So to summarise:

  • Technically difficult (or impossible)
  • Privacy horrible
  • Easily bypassed
  • Effectiveness little
  • Value, little.

If you want to prevent users re-registering, aka ensure user uniqueness, aka personhood, KYC like iProve can solve it much better.

Again, webauthn is a tool for generating assertions, not account management and enforcement police.

@bigradish
Copy link
Author

I just ask whether it is possible that each authenticator is given a GUID (not AAGUID), which can be returned in the result of the create method if the user permits.
Thank you very much.

@emlun
Copy link
Member

emlun commented Feb 8, 2025

That would be even worse for privacy (as others have already pointed out) and still have the same problem that it's trivial to bypass. Again: why would the user be honest about returning a genuine GUID (remember, the user can just choose a browser that returns a random GUID on every call) if you've already assumed they're not honest about only registering one account? Even if we assume the GUID feature was implemented and worked flawlessly with all authenticators in all browsers, why wouldn't the user just get a second authenticator to register a second account?

It would not solve your problem, would not respect user privacy, and would not be backwards compatible with existing hardware security keys. There are no benefits to this, only downsides.

@bigradish
Copy link
Author

bigradish commented Feb 11, 2025 via email

@yackermann
Copy link
Contributor

yackermann commented Feb 11, 2025

  1. Are you referring to excludeCredentials. Again this would only prevent user from re-registering the same device for the same account.
  2. That would disclose that user does not want to share information.
  3. Again WebAuthn API is not account management system lol. It's a key management API.

And lastly, as stated before, web security model is based on no trust to the user side. Server must at all times be aware of that nothing that comes from the browser can be trusted.

Making stuff read-only, etc, does not matter since extensions will just override your JS, and send you false information.

Most importantly, malicious actors won't care for the browser, specs, what ever. They will simply run broken version of the browser, with "fixed" api, and abuse your system to the end.

Best you can do is correctly build your threat model, use KYC techniques, like iProve, etc, register people by phone number, and many many other ways to limit attack vector.

OWASP is your friend https://cheatsheetseries.owasp.org/cheatsheets/Web_Service_Security_Cheat_Sheet.html

@bigradish
Copy link
Author

bigradish commented Feb 12, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants