Top
Best
New

Posted by emadda 12/22/2025

Things I learnt about passkeys when building passkeybot(enzom.dev)
173 points | 146 commentspage 2
PunchyHamster 12/23/2025|
> But much of the recommendations say to use the counter as a heuristic rather than evidence of a cloned authenticator because there are many legitimate reasons the counter can be wrong.

I'm curious on why there would be any legitimate reason for that. Security wise it should not happen, it's just some implementations being crappy or some bad practice like reusing same passkey with different devices ?

js2 12/23/2025||
BTW, if you're looking for something minimal that you can self host, say for a home lab environment, I landed on Pocket ID:

https://pocket-id.org/

wewewedxfgdf 12/23/2025||
Learning and building an outsourced security system at the same time ..... urgh.
WolfeReader 12/23/2025|
For coders, building can be a great source of learning.

Example: this article.

boombapoom 12/22/2025||
i wish passkeys could replace passwords, not suppliment them
spockz 12/22/2025||
Why? Passwords can be remembered and entered on other devices for recovery. The plethora of passkeys out there cannot.

A bit the same why although I love the keychain in macOS, it also makes me uncomfortable. Lose your phone and laptop in a theft or fire and you are locked out from your Apple account. Goodbye online presence.

wkat4242 12/22/2025|||
That's exactly the issue I have with passkeys. All that lockin to big tech. I tried bit warden but most sites with passkeys didn't work with it (like Amazon and PayPal). And on android it only wants to use the Google version (I don't use a Google account on my phone so that's not possible).
izacus 12/22/2025|||
None of what you wrote is true though, is it?

Amazon, PayPal work just fine on my 3rd party 1Password extension. And it works just fine on Android as a default passkey provider as well.

wkat4242 12/23/2025||
It does not work for me on my Linux PC with Firefox, PayPal simply refuses to enrol passkeys and Amazon tries but then gives an error. I haven't tried chromium as I don't have it installed.

I'll give it another try though. The last time was 1 year ago. I don't normally use Bitwarden so I have to set it up from scratch with vaultwarden etc.

ximm 12/23/2025||
This is probably a Linux issue. Mac OS and Windows implement the FIDO2 Platform API, which allows them to act as authenticators themselves. Linux does not. See https://github.com/linux-credentials.
wkat4242 12/25/2025|||
With macOS and Windows I'm still stuck in corporate ecosystems though which was my point. I used to use Mac but I couldn't deal with the increasing iOSification and I only use windows now for gaming (VR) because it's such an awful OS.

But that's another point, I do use many OSes so being locked in to one ecosystem is not an option. I must also have the option to back up my credentials at all times (eg a cloud service will never suffice)

But yeah I should have mentioned Linux. I thought it was the norm here really especially among people advocating against corporate ecosystems.

nixosbestos 12/27/2025|||
Jfc the quality of information shared on this site is abysmal nowadays.

I use Bitwarden, I use Android, I use Firefox on Linux. Passkeys work just perfectly fine on all of the sites listed here thus far.

jeroenhd 12/23/2025|||
Bitwarden works just fine for Amazon. Works on my phone too. Even when supplying passkeys over QR code+Bluetooth to another computer, Bitwarden's Android integration works flawlessly.

I do believe you need Android 14 for that, though, so if your phone has been abandoned by its manufacturer/your ROM of choice, it'll break.

If Bitwarden is bugged out on your computer/phone for whatever reason, there are also alternatives like 1Password.

wkat4242 12/23/2025||
Hm I should try it again, the last time was about a year ago, maybe a little more. I don't normally use bitwarden so I have to set it all up with vaultwarden to make it work.

Is it possible now to export the passkey private key though? That was another thing at the time, apparently the fido consortium didn't want keys to be exportable.

But I'll try it again, good point. I think with paypal the issue was also that they refuse passkeys in firefox and I don't use chrome so I was stuck there too. With Amazon it tried to enroll me but I got a bunch of errors.

AlotOfReading 12/22/2025||||
The "standard" answer is that you should either use synced passkeys, or enroll multiple passkeys with the provider. The problem is that some providers (e.g. Paypal, some banks) only support one passkey, and synced passkeys aren't supposed to be trusted for attestation (unless they're synced by Apple/Google/Microsoft).
epaulson 12/22/2025||
And every couple of days we see a post or a tweet about "Google/Apple/Microsoft just nuked my account with no notice and no recourse" so trusting them to sync passkeys rightfully makes some people nervous.
stavros 12/22/2025||
Whereas we never see a horror story involving passwords.
AlotOfReading 12/22/2025||
There are two problems with passwords. Reuse, and site breaches. The solution to the former is the same as passkeys: credential managers. Passkeys genuinely solve the second, in exchange for a vastly less comprehensible system (see all the uncertainty people have even here on HN) that doesn't support many of the ways people want to use authentication tokens.
stavros 12/22/2025|||
No, the biggest issue with passwords is phishing. You can't phish a passkey.
bgbntty2 12/23/2025|||
The problem with this is requiring everyone to own a device with a secure enclave or similar hardware capabilities because some people are prone to being phished. Let me choose the level of risk I find acceptable.
stavros 12/23/2025||
Passkeys don't require this.
bgbntty2 12/23/2025||
How else would you make the private key unexportable and the passkey uncopyable?
stavros 12/23/2025||
You wouldn't, and still passkeys don't require this.
coldpie 12/23/2025|||
Passkeys don't require it, but relying-parties may: https://github.com/keepassxreboot/keepassxc/issues/10407#iss... If enough RPs ban clients that let users manage their own data in the name of "security," then it is effectively required by passkeys. The passkey spec could have been written to be resilient against this type of abuse, but instead this abuse is explicitly considered a feature of the spec.
bgbntty2 12/23/2025|||
[dead]
NoGravitas 12/23/2025||||
Sort of. Passkeys push the phishing to the account recovery or passkey enrollment process.
stavros 12/23/2025||
How do you phish the account recovery or enrollment process?
AlotOfReading 12/23/2025|||
Are there any credential managers that don't validate the domain with passwords? Sure, there are issues with PSL subdomain matching, but at the end of the day it's good enough in the real world. All the other stuff (MITM, malicious site, etc) falls under the other case I already mentioned.
stavros 12/23/2025||
There's a big difference between "generally doesn't get phished" and "it's impossible to be phished".
AlotOfReading 12/23/2025|||
It's security, so we're not discussing impossibility. You can still phish a passkey, we're just hoping the cryptography is good enough that it remains astronomically unlikely to succeed. Since we're all reasonable people, that chance is low enough that we're fine accepting it. What I'm saying is that the chance with passwords is still low enough that I'm fine accepting, even though it's much higher than the cryptographic security of passkeys. We're simply disagreeing about where we draw the line of "good enough".
stavros 12/23/2025||
How can you phish a passkey?
AlotOfReading 12/23/2025||
You crack the private key and forge the challenge? Maybe the other IDs sent alongside it are hard to get for some reason, but the security of passkeys comes down to the cryptography. Cryptography can always be broken, but a good cryptosystem makes the probability low enough that any reasonable person considers it good enough.
otterley 12/23/2025||
If you trust that the cryptography employed in passkeys is effectively unbreakable, then it follows that for all intents and purposes, passkeys cannot be phished. It’s the same thing as trusting that your browsing sessions cannot be MITMed because the end to end encryption is sufficiently strong.
immibis 12/23/2025|||
What happens if i drop my phone in a river? Am I unpersoned, or is there a way to recover all my accounts? Just phish that flow instead.
stavros 12/23/2025|||
That's not what phishing is. Phishing is convincing someone to give you a credential with a page that looks like the one they're supposed to give the credential on. Passkeys cannot be phished.
immibis 12/23/2025||
They must be paired with an alternative mechanism, unless you plan to unperson everyone who accidentally drops their phone in a river (this may be the plan for high-security services but it can't be the plan in general) and that mechanism can be phished.

Session cookies can't be phished either, so why aren't those sufficient?

ianburrell 12/22/2025|||
Passkeys work well with password manager. The password manager also stores the long random password to get in without passkey. The advantage is that passkeys are immune to phishing. Sites also turn off 2FA for passkeys which reduces the hassle.
coldpie 12/22/2025||
Unless the spec authors declare your password manager to be on the official naughty list[1] and relying-parties choose to block clients on that list.

[1] https://passkeys.dev/docs/reference/known-issues/

jeroenhd 12/23/2025|||
I think it's more than fair to document that some implementations lie about their intentional violation of the spec, even if that violation is done to make the login process smoother.

Still, I've never seen a website try to block Bitwarden's passkey management (though I've had plenty of issues because of its partial implementation of the API, especially in early versions) despite its spec violations.

For some of the implementations, user verification is a massive pain (as browser extensions often only have long and complicated passwords to authenticate) but for KeepassXC a quick and simple fingerprint/facial scan is an option, as it already offers integration into the native OS biometrics anyway.

coldpie 12/23/2025|||
> Still, I've never seen a website try to block Bitwarden's passkey management

Ideally it shouldn't be possible, or at least it should clearly be an ugly hack for a website to be doing something like this. Instead the spec authors explicitly endorse blocking clients that they feel are non-compliant. I'm not going to use a login spec that encourages websites to ban me because of the software I choose to use.

> for KeepassXC a quick and simple fingerprint/facial scan is an option, as it already offers integration into the native OS biometrics anyway.

Man don't get me started on the passkey environment's bizarre obsession with biometrics. My desktop computer doesn't have a fingerprint reader or a camera, and if my OS (Arch Linux) supports that junk I've certainly got no interest in doing the work to set it up just so I can log in to a website.

immibis 12/23/2025|||
Documenting is fine, but the passkey spec author has been recommending blacklisting these so they don't work. It will end in a situation where only the Apple, Google and Microsoft passkey managers are the only way to log into any website.
yawaramin 12/23/2025|||
As I said earlier, this is functionally impossible because Apple devices don't offer device attestation data.
coldpie 12/23/2025||
Then I look forward to them removing the anti-feature and no longer maintaining the naughty client list.
AlotOfReading 12/22/2025|||
And I wish passkeys could cover all the use cases of passwords, yet here we are. Passwords are simple and well understood. Passkeys have all sorts of sharp edges that you won't discover until you're hurt by them.
yawaramin 12/23/2025||
Passwords are also simply phished, and many people have discovered those sharp edges by getting their accounts hacked.
EGreg 12/22/2025||
The authenticator GUI only shows “sign in to your_domain.com”. It never allows a more general “sign this content for your_domain.com”. E.g. “sign this transaction request to move £50 to Bob's account”.

That is why you should ship a pristine HTML+CSS+JS environment that can use subtle web crypto. YOU show what is being signed. And then the device can sign its hash using the secure enclave.

And you CAN do attestation even on consumer devices, by using the Device or AppAttest framework (I think that’s what it’s called). I did it myself in our app. It does show up 100% of the time but when it does it’s useful.

PS: being the web3 / blockchain geek that I am, I will tell you stuff that triggers anticryptobros on HN.

The Web3 ecosystem already has a standard called EIP712 for signing structured data. If you want to stick to standards, use that!

The secure enclaves all use P-256 (sometimes called R-256) while Bitcoin / Web3 uses K-256 (the Koeblitz curve, they distrust the NIST curve or whatever).

So that means you’re going to have to use Abstract Accounts and the new precompiled smart contracts to verify P256 signatures, which only Binance Smart Chain and a handful of other chains have deployed. Luckily BSC is the most widely used chain by volume and has plenty of money sloshing around so you can build your trustless programs there. If you want to be totally trustless — LET THE SMART CONTRACTS GENERATE THE CHALLENGE TO BE SIGNED BY THE AUTHENTICATOR. Then have it sign the temporary k256 public key (from the keypair) to use, as long as your session is open you can then add use your private key to sign transactions. As usual, do this for small amounts per day, transactions that move larger amounts should still require use of multisig keys etc.)

QGQBGdeZREunxLe 12/22/2025||
Computerphile added a passkey video today https://www.youtube.com/watch?v=xYfiOnufBSk
emadda 12/23/2025|
I just watched this, it is very good.
tptacek 12/22/2025|
Regarding PKCE, the way I remember it is that OAuth2 was deliberately designed to eliminate as much actual cryptography as possible, relying instead on same-origin and TLS security; PKCE is one of the few things that introduces an actual cryptography primitive.