One does not simply implement passkeys

One does not simply implement passkeys

Cover image by Neil Moralee: https://www.flickr.com/photos/neilmoralee/49777943373/in/photostream/

(Thanks for Michal Kamensky for proof-reading and providing feedback and discussion on this post 😀)

Table of Contents

  1. Table of Contents
  2. Introduction
  3. Detailed walk-through
    1. The chosen example
    2. Part 1 Creating a mobile passkey
      1. Native App on Android
      2. Now, where are my keys?
    3. Part 2 Creating a passkey on Windows
      1. Firefox on Windows 11
      2. Chrome on Windows 11
    4. Part 3 – Using a mobile Passkey on Windows
      1. Maybe I don’t need a new passkey after all
      2. Geographically embarrassed…
      3. Windows without a new passkey, second attempt
      4. And so it all starts to go wrong…
    5. Part 4 – Why can I not use my Android passkey on windows!?
      1. Maybe there is a bug in the linkage?
      2. Gooooooooooooooood morning, or is it?
      3. Why it’s not working
    6. Part 5 – Can I use my saved passkey directly through my Google account?
    7. Part 6 – Creating a Passkey on Windows
      1. Windows passkey on Android device?
      2. Windows passkey on Windows device?
    8. Part 7 – Using a Windows passkey on an Android device?
      1. Trying natively
      2. Trying via 1Password
  4. Experimentation Summary
  5. What are other people saying?
  6. So what have we learnt?
  7. In conclusion

Introduction

I’ve heard loads and loads of buzz recently about passkeys and how they are bringing about the password-less revolution. However, whilst the technology itself is super-clever, the practicalities and edge-cases have made me hesitant to recommend it to actual organisations who are writing apps for consumers.

(This entire post entirely ignores the business to business or enterprise uses for passkeys as they tend to have a more unified ecosystem, instead of focuses on consumer-facing applications.)

Having opportunity recently to consider recommending it, I decided the best way to figure out whether my concerns were valid or not would be to experiment with a real life implementation.

Detailed walk-through

So this section is pretty long and complicated but if you are someone who cares about how this impacts user experience, I think it would be worth your while following the journey I went through.

If you don’t want to, maybe skip to the summary section at the end of the example part of the blog.

The chosen example

Kayak.com, the travel metasearch engine is one of the case studies which Google themselves highlights as part of their promotion of passkeys so it seemed like they would be a good option.

So, I could have tried to build my own example but I decided it would make more sense to use an implementation from some real developers.

https://developers.googleblog.com/2023/10/how-kayak-reduced-sign-in-time-and-improved-security-with-passkeys.html

In this post, I’ll walk you through my experiences using passkeys with Kayak.com.

I want to make very clear that nothing in here should be considered critical of Kayak.com and it’s engineering organization. My primary aim is to demonstrate various use cases and allow people who are considering implementing passkeys to see the different situations their users might encounter.

Also, note that some of the screenshots are not strictly in order (e.g. I went back and took further screenshots later) but I am describing faithfully the steps I went through.

Part 1 Creating a mobile passkey

Native App on Android

So the first thing I tried was installing the Android native app. I go to login and see this screen:

Almost immediately though, this “Login with Google” screen pops up over it:

I don’t know if this is Kayak or Google making this pop up, but it is not what I want to do in this case so I close it again. It does however make me wonder whether social login is a far simpler way for B2C apps to handle authentication…

So I choose “Continue with email” and now I can enter in my email address. Throughout this, the username of the account I use to login will be a Hotmail account but when I store my passkeys shortly, it will be to a Google account. Hopefully that makes the different identities clearer.

Notice how it hasn’t said anything to me about passkeys. I believe this is a choice on the part of Kayak but I could be wrong.

I hit continue and it tells me I have been sent a verification code to my email.

Here we go, promptly delivered to my inbox.

I enter in my code and now I’m in as a registered user.

The sharp-eyed among you will have noticed that the “Account” option mentions passkeys. Having noticed that and dug into a couple of sub-menus, I can now create myself a passkey.

I hit “Create” and this screen tells me that I am creating a passkey for “KAYAK” for my Hotmail account, and storing it into my gmail account. (I could also choose other Google accounts from my phone to store it in.)

Now, this is important, something on my device has to be able to store/manage the passkey. Since I am on an Android phone, Google will be managing it. If I was on an iPhone, it would be going into my iCloud Keychain. If I was on a Windows machine then Microsoft would be handling it. This page shows which devices/manufacturers support what features:

https://passkeys.dev/device-support/

Simples? Not so much…

Anyway, a swipe of my fingerprint and now I have a passkey created.

So, now what can I do with this?

So if I log out of the app and then go to login, instead of the “Login with Google” pop-up, I now see a different pop-up.

I can hit “Continue”, swipe my finger again and I am back in again!

In terms of user experience, that was great! Nice and easy.

Now, where are my keys?

So, how can I find the passkeys on my device? Well they aren’t in a specific app.

What about in my settings screen?

Well, “Credential Storage” doesn’t have anything to do with this type of credentials and the mysterious “Passkey linked devices” doesn’t seem to do anything at all. Maybe this is specific to my device manufacturer though…?

Turns out, it is on the “Password Manager” screen

So much for our passwordless future…

How do you know which of these are passwords and which are passkeys? Only by clicking on each one to see.

Not ideal but hopefully we shouldn’t need to use this page very often.

Part 2 Creating a passkey on Windows

Firefox on Windows 11

So, now let’s move to my Windows PC. My usual browser is Firefox so let’s try and login here.

Nothing pops up immediately until I hit “Continue with email” at which point 1Password pops up offering to let me use a passkey. That is interesting, turns out that 1Password also supports passkeys.

Well I don’t have a passkey on 1Password so that makes sense.

What happens if I open that site on Firefox without the 1Password extension installed?

Nothing.

Well, that’s not true, actually it initially flashed up a pop-up strongly encouraging me to login using Google (like when I first opened the app) but it only showed me in Hebrew so I decided a screenshot would not be super helpful 🙂

Chrome on Windows 11

What about Chrome?

Well that is interesting, Chrome is offering me two options. Use a passkey or use passwords saved in my Google account. Now, again that word “password” even through I think it would let me use the passkey stored in my Google account. (Actually, I’m pretty sure it would not 🤷‍♂️). But that’s irrelevant because I am not logged into the correct Google account on this browser and I am not going to start changing things around now.

So let’s look at “Use a passkey”.

(By the way, 1Password on Firefox also gave me this option to use a passkey from Windows itself by clicking on this teeny tiny icon on the screen that popped up, see if you can spot it in the Firefox screenshot above!)

Anyway, back to Chrome, a new screen appears.

Part 3 – Using a mobile Passkey on Windows

Maybe I don’t need a new passkey after all

So, now Windows is offering to let me use a passkey from a different device. Except I thought the passkey was in my Google account, which is none of those options.

Ok, well the Android device is the only thing that makes sense there so let’s try it.

So I now get a QR code flashed up to me, I guess I just scan that with a regular QR code app from my phone?

So I scan the code and browse to the URI which it contains.

I guess I want my devices to remember each other so that make sense, and now my devices are connected.

(Sure enough, if I do that, my phone appears on the original Windows Security screen above and the next few menus on the phone appear automagically, without having to scan a barcode. I actually don’t know how that works and can’t be bothered to go and look it up right now but it seems cool.) (Ed note: This aged poorly)

I click through the next few screens on a best guess basis because honestly the wording is quite confusing and I get the disappointing answer of “computer says no“.

So, why did that happen. Again, sharp eyed readers might have figured it out.

Geographically embarrassed…

For whatever reason, my Kayak app on my phone is set to a region of UK but on my PC I am trying to login to the Israeli version of the site (which Kayak pushes me to automatically based on my location.)

The Passkey is attached to a particular domain and the Kayak app is smart enough to make that http://www.kayak.co.uk because it is set to UK region but since that domain doesn’t match what I am trying to log into now, I can’t use my existing passkey.

I now have 3 options:

  1. Just enter in my email address, I’ll get a magic link and be in my app and working and passkeys be damned.
  2. Go and fix my app region and create a new passkey and then try logging on my Windows PC again.
  3. Option 1., but then register a passkey on my Windows PC.

Let’s try option 2 first.

So back in the Kayak Android app I can “revoke” my current passkey. Do I need to? No idea but it seems like the sensible thing to do.

So I revoke it and then sign-out.

I go back to login and get presented with this screen.

That’s weird, didn’t I just revoke this passkey?

Ah, oh dear. There is a problem.

Now, fortunately since I am doing all of this at the same time, it seems obvious to me that the reason I am getting this error is that despite the fact that I revoked the credential in the Kayak app, it still exists in my Google Password Manager.

Looks like I am going to have to go and delete it manually from there. Hope I can still remember how to find it… (see above…)

Once I have done that, I am going to log back into Kayak, again using an OTP sent to my email, change the region to Israel, create a new passkey and then go back into my Google Password Manager to make sure it is the correct domain (because you don’t see the domain in the Kayak app or when you create the passkey).

I’m not going to show you the screenshots, just trust me.

Windows without a new passkey, second attempt

So, back to my Windows PC and to Chrome.

I chose my phone (yes I have a relatively cheap Android phone, laugh all you want) and again there is no QR code because I previously did the automagic pairing.

I get the same Android screens as before but this time it recognises my passkey.

I hit Continue and wait for something to happen on my laptop. It doesn’t.

And so it all starts to go wrong…

I try again and this time my Android device was locked and I mashed some buttons but it didn’t work again for some reason.

Third time, I have the Android device unlocked, next to my laptop, everything ready. Still no dice.

A fourth time, a fifth time, a sixth time, each time before I can click through the multiple screens on my Android device, I get an error message.

Why? No idea. Maybe there is a configurable timeout somewhere? Maybe I am missing something else? Write in and tell me.

So what now? Well remember how I said 1Password also gives me that option through Firefox when I go to the email sign-on page on Kayak…

(I also have the 1Password extension in Chrome but I don’t see the 1Password pop-up in Chrome. Why? I don’t know.)

I go back to Firefox, that 1Password pop-up is no longer showing. Why? I don’t know.

I close Firefox, reopen it. Still nothing.

I close Firefox, lock 1Password, open Firefox, browse back to the email sign-in page on Kayak and now I have something.

I hit the tiny security key icon (despite the fact I am not using a security key) and we are back to this familiar screen.

Same problem on Firefox.

At this point, my finger is getting tired of swiping each time to approve the passkey use only for the process to fail.

Back to Chrome, NOW I get the 1Password thing popping up but not the regular Chrome menu 🤦‍♂️.

I press the tiny security key icon, and this time I scan the QR code rather than relying on the auto-magic pairing. I tap through all the menus on the Android device…

I got this error again.

Why? Because somehow, Chrome had this time NOT redirected me to the Israeli site but rather to the regular .com site.

Part 4 – Why can I not use my Android passkey on windows!?

Maybe there is a bug in the linkage?

I go to clear out my linked devices on both my Windows and Android devices.

On Android, that is *relatively* straightforward after browsing through a bunch of menus I found this.

On Windows, it is not straight forward. You can enjoy the twists and turns of this thread:

https://answers.microsoft.com/en-us/windows/forum/all/how-do-i-remove-an-old-device-from-windows/e4e5fcd5-f281-46b0-b0be-aaa4451a6335

One regedit visit later (90s throwback) and I had the device link deleted.

Went through the whole process again on Chrome and the same failure happened.

At this point, I called it a night and decided that I was going to have to employ advanced troubleshooting.

Gooooooooooooooood morning, or is it?

Ok, it’s morning. Bright eyed and bushy tailed, I’ve restarted my computer so let’s see if I can convince this to work today.

Back to Chrome on Windows, phone is unlocked and I am on the correct domain for my passkey. The 1Password thing pops up instead of the Chrome native one again, I still don’t know how it decides which to show. I click the tiny icon, go through the same flow to use the passkey from my Android device and…

Still fails with exactly the same behaviour.

I go back to my Android device. I am still logged into the Kayak app and I can see the passkey is registered there. I can see the passkey still exists in my Google Password Manager. I log out of the Kayak app and try to login again with my passkey. I get the same cryptic error message as when I had revoked the key in Kayak and it doesn’t let me in.

I force close the app and try again, this time it works fine and I am logged in again. That was weird but maybe just some sort of glitch? Who knows?

So my passkey definitely works (on Android). I try again with Chrome on Windows and same failure again. It seems to get the stage where I need to swipe my fingerprint and then fails on Chrome before I even have chance to swipe.

In my desperation, I even open up a different laptop and try to login to Kayak using Chrome on that. But it’s running Windows 10, not Windows 11 so I don’t get the pop-up and I don’t feel like trying to figure out what is actually possible under Windows 10. (Spoiler alert, I’m pretty sure nothing is natively possible there).

Alright, I am out of ideas. No idea why this is not working.

Why it’s not working

At a later date, I managed to find another Android phone and another Windows 11 PC and bottom line is is that the QR code flow to use my Android passkey on another device just flatly seems to not work on my cheap Android device (which honestly wasn’t THAT cheap, I’m not talking Aliexpress $5 phone here).

Doesn’t matter what site, the flow doesn’t work. I even tried using adb and logcat to debug but couldn’t find any useful information and Googling didn’t help either.

Looks like this is a known issue: https://community.oneplus.com/thread/1501854721621622793

Part 5 – Can I use my saved passkey directly through my Google account?

So, I decide that in the interests of fairness, I will try option 4 which is to create a new Chrome profile on my Windows 11 laptop using the Google account where I have stored the passkey. (Remember that I am logged into that account on Firefox but for whatever reason I can’t directly use my stored passkeys from my Google Password Manager in Firefox).

I do that and get presented with this.

This screen is letting me use passkeys via the Windows mechanism (which we have seen just doesn’t seem to work) but it isn’t showing me the “Use passwords saved in your Google account” option that I saw on my other Chrome profile.

I am definitely logged into a Google account, and the correct Google account.

So why didn’t I get the “Use passwords saved in your Google account” pop-up?

So I go to the “Google Password Manager” and…

My passkey is not there. It is definitely in the list on my Android device. I guess this kinda makes sense because it is supposed to be tied to my device but I don’t think it is unreasonable that someone would expect that given how obsessed Google is with synchronising all your stuff everywhere, that your Google Password Manager would also be the same everywhere.

Part 6 – Creating a Passkey on Windows

Let’s go back to option 3 for Windows which was to enter in my email address, get a magic code, get into the app and then register a passkey on my Windows PC.

So, I still really want to use Firefox so back to that. It again tries to get me login with my passkey and again fails so instead sends me a magic code to my email address. (This is all being done using the same Hotmail address for the Kayak account).

Enter in the magic code and I am logged into the app, nice and easy.

So I dig into a few screens and now I am offered to add a passkey.

Once again 1Password pops up, offering to store my passkey. Let’s leave that for later.

For now I click the tiny security key icon to be taken to the Windows passkey mechanism.

This pops me up a Windows security screen with a few interesting options.

Now, I have Windows Hello and a fingerprint scanner so I can save it on Windows but intriguingly I also have an option for use another device. Presumably, someone who doesn’t have Windows Hello on the their laptop would need to use this?

Windows passkey on Android device?

I am going to try and store it on my Android device because I have no idea what that actually means or entails 🙂

I go through a very similar flow to trying to use a passkey from my device with a QR code (if I don’t use the saved version of my phone) but I am seeing the same failure behaviour so let’s leave this for now.

Windows passkey on Windows device?

I go back and select to store using fingerprint on my laptop.

That seems to have saved ok and I can see the new passkey on my list in Kayak.

I logout, go back to login with email, the 1Password pop-up appears, I click the tiny security key icon and now it shows that I can login with my passkey.

Swipe my fingerprint on my laptop and I am golden.

Did you notice that the passkey I just created is named “Firefox”.

Can I use it on Chrome?

Yep, so not a great name but interesting none the less.

Part 7 – Using a Windows passkey on an Android device?

Trying natively

Now, is there any way to use my Windows passkey on my Android device?

I am going to revoke my Android passkey on Kayak and delete it from my Google Password Manager so that we can find out.

With that done, I clear the Kayak Android app’s data to log me out and open it up on my Android device. I go to login and it doesn’t say anything about passkeys. Looks like that isn’t possible.

But wait, I have 1Password on my phone, maybe that will make it work?

Trying via 1Password

I go back to Kayak and revoke my Windows passkey, the one that is actually called Firefox.

I also delete it from my Windows passkey store (it is the bottom one).

I logout and log back in again in Firefox.

It actually prompts me again to use my passkey. (I took the screenshot above but forgot to actually do the deletion). I swipe my fingerprint and it silent fails with no error message, presumably because I DID revoke the passkey in Kayak.

This time I actually remember to delete the passkey so now I need to login using a magic code again. I get in, back to the accounts screen and adding a passkey.

This time, I am going to store the passkey in 1Password.

Job done, that is now added.

I can logout, go back to login and 1Password tells me I have a passkey I can use.

Click the magic button and I’m in.

So now, I go back to my Android Device.

(Remember I deleted my passkey on that device.)

I open up Kayak and see if I get told about a passkey by 1Password, but nope nothing there.

Maybe it doesn’t know the App is Kayak so it doesn’t present it to me. I uninstall the app and browse to the site manually.

So in the browser, 1Password knows it has something for this site and will fill in the email address.

But the next screen I get is from Android and gives me two confusing options, neither of which help me in this case.

It turns out that doing this via 1Password basically isn’t possible until Android 14 which I don’t have and was only released a couple of months ago. Seems like it isn’t going to be a realistic solution in the short to mid term.

Experimentation Summary

So what is the summary of this experiment?

  • First of all, I want to reiterate once again that none of this is critical of Kayak.com, they have made a good-faith effort to make this work but they aren’t responsible for the surrounding ecosystem issues.
  • There is currently a lot of confusing UX around passkeys, even for very basic operations. Different combinations of browsers and devices lead to a variety of different (and sometimes unpredictable) user journeys.
  • Creating a passkey on a device (and using it on that device) is relatively slick although the weird UX differences still apply.
  • Once you start trying to use an account on multiple devices, the UX really breaks down. Passkeys don’t synchronise where you might expect them to synchronise and the QR code flow that is supposed to work around that appears to be unusable on my device and maybe all OnePlus devices…
  • Most places that talk about Passkeys assume that you are using a biometric mechanism like face or fingerprint to use a passkey which in theory should provide proof your are physically present. However, the FIDO Alliance (the main industry body that defined the passkey standard) clearly says that this may be a biometric or a device PIN. Practically speaking, on my Android phone I could use my phone pattern instead of a biometric so that eliminates proof of presence and instead relies on the complexity of your pattern or your your PIN or whatever. I don’t think this is a passkey specific thing but it is worth considering when you talk about using biometrics.
  • At pretty much every stage of this experiment, I could have fallen back on to a code being sent to my email address. In some cases, I was forced to fall back on to this.
  • Ecosystem improvements will probably require Operating System upgrades. For example, 3rd party password managers which would probably greatly simplify the cross-device ecosystem will only be supported by Android 14+ which was only released very recently.

What are other people saying?

At this point, in my experimentation, I had pretty much gotten to here:

So I decided to ask a few people in the industry. I am not going to name names but here are a couple of examples. I guess this section would have been more convincing if I had gotten signed affidavits and done video interviews but that wasn’t really practical 🙂 so I am paraphrasing a lot below.

I spoke to a very well known web security researcher who is also involved with a SaaS product. They said that they had not been asked for passkeys by customers, didn’t have much of a plan to implement them and overall didn’t see them as of immediate importance.

I also spoke to someone who was going to be shortly giving a talk about passkeys. They were sympathetic to my ecosystem concerns and saw the current goal as building awareness of passkeys rather than expecting significant roll-out in the near future. They then told me that one of the demos from the talk that they were about to give had broken the previous day. The reason appeared to be some weird bug in Android 14 that had suddenly stopped 3rd party password managers working.

This feedback seemed to confirm my usability concerns and I am therefore led to the following conclusions.

So what have we learnt?

Technically a dream

The technical aspects of passkeys are super cool. Purely using passkeys effectively mitigates phishing and requires no remembered secrets.

Ecosystem is a nightmare

The current ecosystem is really problematic! If you are using end-to-end Apple devices then you are probably okay, otherwise you are going to see a whole range of compatibility issues and differences in what is supported where.

The exception becomes the rule

We will often see fallback options, where a particular security option is not possible.

In the case of passkeys, the fallback option tends to be a magic link sent to email or a code sent to email, and as soon as you introduce any complexity at all then the fallback option almost becomes the norm. The ecosystem complexity means that in order to make sure your app is usable cross-platform, or by devices which don’t support passkeys, you are pretty much forced to make fallback options a first-class citizen.

Kayak in particular rushed to fallback to an email code or link as soon as something did not go smoothly with the passkeys flow. https://www.passkeys.io/ is entirely usable without passkeys, just email codes. https://passkeys.eu is entirely usable without passcodes, just email codes.

Now you might say, well I could use any app with standard authentication with just an email code if I activate the forgot password process. But there are two problems with that. Firstly, forgot password would be considered a non-standard login and cause noise, in this case the code/link login seems to be considered like any other login. Secondly, with standard authentication, if MFA is enabled then the forgot password process should not work just from an email link anyway.

Another fallback example I mentioned above was that on my Android phone I could use my phone pattern instead of a biometric so that eliminates proof of presence and instead relies on the complexity of your pattern or your your PIN or whatever.

What does this mean for security

Well, basically this means that you are only as secure as your weakest fallback option. Passkeys don’t mean anything if the user’s email is compromised and that is the fallback option. Biometrics don’t mean anything if the fallback is using the phone’s PIN.

Passkeys are super secure, current authentication flows using passkeys, not much more so than classic authentication flows.

But the user experience is great, right?

In a simple scenario, the user experience is fabulous. Really simple flows and super easy to log in.

Unfortunately, as I hope I have demonstrated above, once scenarios get more complex or you have device compatibility issues or there is some weird bug that breaks things, user experience is going to plummet and you need to decide if your organization is ready for this.

How much effort it all of this for developers?

Well, you could bring pay a 3rd party service to do this for you, but do you really want another 3rd party service? Odds are you are already using a 3rd party service for your authentication mechanism, maybe they support it?

I have a client using Google Identity Platform (which appears to be a souped-up version of Firebase Authentication). Now, Google have been major advocates for passkeys so I assumed that Google Identity natively supporting it would be a no-brainer.

Somewhere I found a support ticket explaining that this was not yet supported but I can’t find it now, probably because they are embarrassed, as well they should be.

So anyway, if your 3rd party provider supports it then maybe it is easier. If not, then there are going to be a lot of flows, edge-cases and management screens and functionality that your developers are suddenly going to have to deal with.

Discovering Google Identity Platform didn’t support it put the final nail in the coffin for me and this particular client, there was no way I was going to suggest my client to get bogged down in this or buy another 3rd party.

In conclusion

Look, this is a really cool piece of tech but until the ecosystem gets itself together, it is going to be hard to justify the return on development investment.

Definitely learn about it, try it out and make sure you understand it but when it comes to implementing it in production, maybe leave it to the curious or the early adopters for now.