Page MenuHomePhabricator

Unable to login on iPhone with Passkey Enabled
Closed, ResolvedPublicSecurity

Assigned To
Authored By
Tonymetz
Feb 29 2024, 2:53 PM
Referenced Files
F49146881: IMG_0075.jpeg
Apr 28 2024, 5:33 PM
Restricted File
Mar 6 2024, 1:15 AM
F42406441: wikipedia iphone passkey debug fix.mp4
Mar 6 2024, 1:10 AM
F42406337: image.png
Mar 6 2024, 1:02 AM
F42404183: image.png
Mar 5 2024, 10:22 PM
Restricted File
Mar 5 2024, 9:21 PM
F42399376: Screenshot 2024-03-05 081320.png
Mar 5 2024, 4:57 PM
F42262907: Untitled video (2).mp4
Feb 29 2024, 8:35 PM

Description

Passkeys (webauthn) were enabled and working on desktop . Now I’m unable to login on mobile safari. I can still login on safari “in desktop mode” but that login session ends when switching back “to mobile mode”

IMPACT

  1. unable to login on 2nd windows desktop device (not containing original windows passkey)
  2. unable to login on iphone

STEPS

  1. Enable web authn / passkey and add an iPhone passkey
  2. Try logging in on iPhone
  3. Enter creds
  4. Observe error

ACTUAL RESULTS

“Authentication process was interrupted . Reload page “

EXPECTED RESULTS

I should log in

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

screenshot evidence. video inbound
{F42406516}

debug session showing how to fix

Aha

https://forums.developer.apple.com/forums/thread/710784

The QR code flow will be publicly formalized in an upcoming version of the CTAP2 spec. It uses the "hybrid" transport (formerly known as "caBLE").

final public const AUTHENTICATOR_TRANSPORT_CABLE = 'cable';

Which was added in https://github.com/web-auth/webauthn-lib/commit/6634a25e60c3a791f156673b82bb27c21ba7a562 (4.0.5+)

Can you run your test again for me, and see if cable indeed works instead of hybrid?

I'd be happier hard coding cable, with a TODO left to replace it with the proper upstream usage later...

Great, I appreciate the debugging. This makes a patch fairly easy. Though, I will admit upfront, I don't know how well this will behave with stuff saved in the DB...

Change 1008987 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/WebAuthn@master] WebAuthnKey: Add "cable" to credentialTransports

https://gerrit.wikimedia.org/r/1008987

happy to help -- great partnership on this

with stuff saved in the DB...

I'll let you know if the transports reflects the new commit or if I need to re-install the credential (it's from the db)

can I help testing out the change on the test env?

can I help testing out the change on the test env?

Not really, yet. I'm pretty sure your testing confirms it's the right fix, at least for new DB entries. It's obviously currently unclear how that works for existing rows, and whether we need to do anything about it (yet).

It needs merging (ie C+2) in our version control, then it'll be live on the Beta-Cluster-Infrastructure...

what's a good way to track the launch status for this fix? i'm sorry I don't know too much about the deployment process

Change 1008987 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/WebAuthn@master] WebAuthnKey: Add "cable" to credentialTransports

https://gerrit.wikimedia.org/r/1008987

There'll be a comment like ^ saying this has been merged. Then depending on when it is merged, it should be rolled out on Wikimedia wikis within a week, or two at the most, depending on whether it is merged before the branch cut.

There may be another variant of the issue when logging in on meta.wikipedia.org. It seems that the viable webauthn credential list is being filtered either by site or by login device before being presented to the browser. I get a different experience on different browsers.

STEPS

  1. use iPAD (safari) to log into "wikipedia library" via oauth e.g. https://meta.wikimedia.org/w/index.php?returnto=Special:OAuth/authenticate&returntoquery=%26oauth_consumer_key%3xxxxxbaf%26oauth_token%3Dxxxexxxxxxxx&title=Special:UserLogin&uselang=en&centralAuthAutologinTried=1&centralAuthError=Not+centrally+logged+in
  2. enter username + password
  3. try to use usb-c token or iphone passkey

ACTUAL RESULTS
iphone passkey does not work despite it being connected to the account. error message "Passkey was not found" (not exact)

EXPECTED RESULTS
both usb-c token and iphone passkey should work

No, if there were any updates they would be here.

Can I ask what the blocker is?

There is no "blocker", only lack of unlimited time and lack of unlimited developer resources and lack of empty to-do lists - see also https://www.mediawiki.org/wiki/Bug_management/Development_prioritization

Reedy and I already got this fixed and he submitted a patch. So we're just waiting for it to get merged. What is blocking that?

It seems the commit was made Mar 5 so it's been 6 weeks. Can you guess how many more weeks it is going to be?

@Aklapper I don't appreciate the dismissive tone being used. I invested a lot of effort working together with Reedy to reproduce, debug & help formulate a fix. At the very least you could help clarify exactly what the next steps are here.

As mentioned before, the next step is that some other maintainer must review and approve ("+2") the change. For WebAuthn, that "someone" would most likely be me. However I am not planning to review any WebAuthn patches before I get some patches of my own merged there, and the constant pings in this task are very effective at bringing this patch to the very back of my mental to-do list.

  1. it is a one-line change
  2. it is a back-port of code from the webauthn repo
  3. reedy & I recorded our testing procedure above with video and code samples

What is there to do?

I'm a diligent volunteer and you are burning a bridge here.

@taavi any updates on the webauthn tasks merge progress? Are we looking at another 6 weeks?

Webauthn security tokens are not being passed to wikifunctions.org

I have 2 passkeys (1 windows 11 and 1 iPhone) , and neither are recognized on wikifunctions.org

STEPS

  1. Visit wikifunctions.org —> login
  2. Enter username + cred
  3. Receive 2fa prompt

EXPECTED RESULTS
Existing passkeys should work

ACTUAL RESULTS
No passkeys work

IMG_0075.jpeg (1×988 px, 366 KB)

@taavi are we targeting 2024 or 2025 on this one?

@Tonymetz: Such comments are pretty unhelpful. "We" are not targeting any years.

what would be helpful would be an estimate.

a monthly reminder that ...

  1. it is a one-line change
  2. it is a back-port of code from the webauthn repo
  3. reedy & I recorded our testing procedure above with video and code samples

a monthly reminder that ...

Hi Tony,

there's no one that needs a reminder about this. if you want to do something productive, do Gerrit reviews of other changes on other tasks. in any case, you should not be commenting here.

the people who want to use webauthn do. What's the point of the feature if it's broken?

i did another round of testing and the feature still appears to be broken. The issue is likely locking users out of their accounts. There doesn't seem to be telemetry on the issue, so I worry that wikimedia staff is not paying attention to the number of users who are getting locked out.

In my recent case, I was locked out of mediawiki access. Luckily I had a en-wiki session open that allowed me to disable the webauthn .

I recommend either merging this patch to address the issue or disabling webauthn

2662 (SUL) users using 2FA, 84 of them using WebAuthn (but 196 total devices). Some having as many as 5 devices enrolled. 56 of those 84 have 2 or more devices. Meaning 28 only have 1.

I imagine the number of people affected is probably pretty low, but not zero. Otherwise we'd probably hear about it from more users.

See also: T376021: Migrate WebAuthn on Wikimedia wikis to central domain

I imagine the number of people affected is probably pretty low, but not zero. Otherwise we'd probably hear about it from more users.

See also: T376021: Migrate WebAuthn on Wikimedia wikis to central domain

Thanks these are helpful insights. There still may be a blindspot. We expect the absolute numbers to be small. But what percentage of 2fa / webauthn users are having login issues? That part is unclear.

Users may be enrolling multiple devices to workaround the issue. webauthn is meant to allow enrollment on a single device and login on multiple devices. The current fault condition has potential to lockout users.

We have debugging examples and a patch that shows that multi-enrolled-device login is broken , and a lockout state is possible.

This feature will never reach broader adoption in this state. I guess the question is, does anyone care?

T244088: Logging in at another wiki than WebAuth was set up fails is a probably bigger blocker to uptake of WebAuthn than this. But work is in progress to hopefully fix that underlying issue

T376021: Migrate WebAuthn on Wikimedia wikis to central domain documents many other issues with it.

Does anyone care? That's a harder question. WebAuthn was developed by outside contractors for the WMF, without any sort of long (or even short, frankly) term maintenance plan. Which helps explain the situation we're in with all the issues.

thanks for helping provide the context that is helpful. I'm happy to help provide some support on this if there's interest. I've worked on 2FA efforts before, and users require a bit of education and notification to help move adoption forward.

T244088 -- I believe this ticket is related to T244088 . the fault condition is preventing the complete list of enrolled devices from being presented on alternate wikis. I've personally experienced that state on wikitravel & wikimedia.org

matmarex added subscribers: Tgr, matmarex.

We've talked about this task on the Platform team, and we're happy with the change you're suggesting in principle. @Tgr has already reviewed the patch, and he's happy with it security-wise, so the next step is for someone to test it locally. I volunteered to do that.

So far, I managed to set up OATHAuth and WebAuthn on my local test wiki, and made it available via HTTPS (with a self-signed certificate) under a named .local domain (not just an IP address) – these are both requirements for the Web Authentication API to work.

(By the way, enabling HTTPS on Apache on Ubuntu – what I happen to use – is apparently as easy as sudo a2enmod ssl; sudo a2ensite default-ssl.conf; sudo systemctl restart apache2, but I've read several long articles trying to tell me how to set up everything from scratch, each one suggesting subtly different solutions, before I figured that out.)

I was able to enable Web Authentication as the 2nd factor on a Windows PC (using a Yubikey USB token) and also on an iPhone SE 1st gen (also using the same Yubikey USB token), and then log in on both devices.

However, I am not even getting the option to log in using a passkey on either device, so I haven't been able to reproduce the bug or test the fix yet. I found this article: https://corbado.com/blog/passkeys-ios-15 which says I need to enable Touch ID first on the iPhone. I don't know what I'd need to do on Windows. I'll keep digging into this tomorrow.

One non-obvious thing (at least on Chrome) is that you need a TLS connection that has been established without errors, otherwise the browser rejects the call to initiate passkey check. That means it's not enough to click through the certificate security warning, you need to add it it to browser's CA store. (Some errors are logged to the JS console so that might help figuring out what's wrong.)

One non-obvious thing (at least on Chrome) is that you need a TLS connection that has been established without errors, otherwise the browser rejects the call to initiate passkey check. That means it's not enough to click through the certificate security warning, you need to add it it to browser's CA store. (Some errors are logged to the JS console so that might help figuring out what's wrong.)

Yep, I ran into that when testing on Edge – I had to create a new cert with a SAN field, and then add it to the Windows CA store, before it let me attempt to use passkeys.

It was actually quite difficult to find a device/OS/browser combination that would let me use passkeys. I tested the following:

  • Firefox 131 on Ubuntu 22.04 in a virtual machine – only offers USB security key as an option (I didn't test if it works)
  • Chromium 129 on Ubuntu 22.04 in a virtual machine – only offers USB security key as an option (I didn't test if it works)
  • Firefox 132 on Windows 10 – only offers USB security key as an option (it works!)
  • Edge 129 on Windows 10 – finally, there's an option to use passkeys. It says it can store them locally if I enable Windows Hello (I didn't try), or using a separate authenticator device connected by QR code and Bluetooth (I tried it).
    • When the authenticator device is an iPhone SE 1st gen running iOS 15: does not work, the process gets stuck on "connecting" (with or without the patch)
    • When the authenticator device is some Android phone I borrowed: potentially works! It went further than the iPhone. But I didn't finish the process since I didn't want to store random credentials in another person's phone.
  • Safari on iPhone SE 1st gen running iOS 15 (by itself, not as an auth device for desktop): after enabling Touch ID (for password autofill only) and iCloud keychain, it works! However, when I applied your patch, it stopped working – I was no longer able to log in using the stored passkey or remove it. I un-applied the patch and it worked again.

Now, this is not a representative set of devices, but it seems that applying the patch could also lock some users out of their accounts. Unless we can explain why this happened and resolve it, we probably shouldn't merge it.

I think the main thing I learned on this adventure is that passkeys are a technical support nightmare, and we should make sure we disable support for them as thoroughly as we can, until at least a few more years pass and browser/OS vendors figure them out better. USB security keys work well though.

@Tonymetz Also, I am having trouble understanding what is the actual workflow that doesn't work for you. Maybe I'm just confused, but you seem to be talking about several different ways to log in. Can you test things again and write down step-by-step 1) how do you create the second factor and 2) how do you use it to log in?

I'm blocked by another variant of this issue: login from a separate windows machine. I'm being prompted to "insert usb security key" but i have two passkeys registered : (1) from iphone and (1) from another windows machine. I would expect the option to pop a QR-CODE to proceed using iphone passkey

STEPS TO REPEAT (2 windows machine variant)
  1. create (2) passkeys on windows machine-A
  2. try to login on windows machine-B
ACTUAL RESULTS

I'm prompted "insert your security key into usb port" -- with no alternative credential.

Screenshot 2024-03-05 081320.png (1×1 px, 97 KB)

EXPECTED RESULTS

I should be prompted for qr-code passkey authentication to use my iphone.
{F42403350}

For what it's worth, I saw a similar interface, and clicking "Cancel" in that popup opens a second popup that lets you choose the QR code method. This seems like Windows's fault and not ours.

Adding the new transport also causes an extra prompt to appear when logging in on Edge on Windows, so that's not great either.

This could be fixed by using getTransports() when adding the second factor, and then providing that value in allowCredentials when requesting the second factor during login, as @taavi and @Tgr discussed here on the patch: https://gerrit.wikimedia.org/r/c/mediawiki/extensions/WebAuthn/+/1008987/comment/e210ee68_dfd9b3bd/

If I understand correctly, this would also let us fix the iOS 15 issue. What I'm seeing is that iOS 15 Safari can create the second factor when cable is present, but can't authenticate using it. iOS 15 Safari actually doesn't have the getTransports() method (see MDN, I verified that locally), and it doesn't seem to support cable per my testing above, so we could simply hard-code it to ["usb", "nfc", "ble", "internal"] when the saved second factor doesn't specify it (either because getTransports() was unsupported, or because it was created before this change to the extension).

So, I think doing that would let us proceed with this change. I don't really understand how that would be done, though. web-auth/webauthn-lib doesn't seem to do anything related to that, is it something we'd have to implement ourselves?

@Tonymetz Also, I am having trouble understanding what is the actual workflow that doesn't work for you. Maybe I'm just confused, but you seem to be talking about several different ways to log in.
Can you test things again and write down step-by-step

I'm happy to help test and support this. thanks for giving it some attention. it's been a few months so i'll try to reproduce a better test case.

  1. how do you create the second factor and 2) how do you use it to log in?

IIRC from the earlier test case, it was something like this.

  1. successfully add iphone token on windows-device-desktop
  2. attempt login on a 2nd windows device, "windows-device-laptop", where I expected a QR code prompt (presentation of iphone token)

Step 2 failed. Instead of the presentation of iphone token qr code, the browser tried generic webauthn credentails (e.g. the windows-device-laptop's hello login, which didn't contain any tokens for wikipedia).

This is what led to a possible "locked out "case . Other variations have also failed, e.g. trying to log in on wikimedia. They are not recognizing the iphone token added on en.wikipedia.org.

I don't really understand how that would be done, though. web-auth/webauthn-lib doesn't seem to do anything related to that, is it something we'd have to implement ourselves?

Yeah, AIUI the library is basically just a heap of value objects that serialize to and from the JSON structures used by the navigator.credentials browser APIs, so you can interact with those APIs with easy-to-read code. I think what would have to be done is:

  • add transport setters to WebAuthnKey
  • read the transports in mw.ext.webauthn.Registrator.prototype.formatCredential() and put it into the JSON string that gets submitted from the server
  • read them from the JSON data and plug them into the newly created WebAuthnKey in Authenticator::continueRegistration()
  • be able to load the data back in WebAuthnKey::setDataFromEncodedDBData()

Transports might not be the only thing for which this needs to be done, WebAuthnKey::setDataFromEncodedDBData() is suspiciously thin.

webauthn-lib has an AppleAttestationStatementSupport class, but we are not including it for registrations nor for authentication. Might be another thing to look at.

I think I misunderstood the impact of the cable issue. We do not send the list of transports on WebAuthn key creation, only when the user is trying to log in and we send the list of known keys to the browser. Which makes sense wrt the spec - transports are only included AuthenticatorAttestationResponse (the data the browser returns after the user finished creating a new WebAuthn key) and PublicKeyCredentialDescriptor (the data we send to the browser before starting the WebAuthn check during login). It also seems to match my testing - on current master (in Wikimedia production), I can pick the "phone or tablet" option (on Chrome/Ubunto) to use the QR code scanning option when creating a new passkey, but then cannot login with that passkey. If I manipulate the the data passed to navigator.credentials.get() to add cable to the list of transports, then logging in works.

So this bug (not storing the transports) actually leads to users locking themselves out when setting up a certain type of WebAuthn key, right now, in production. We should fix it ASAP.

Change #1008987 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@master] WebAuthnKey: Use PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORTS

https://gerrit.wikimedia.org/r/1008987

Change #1191728 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/WebAuthn@REL1_44] WebAuthnKey: Use PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORTS

https://gerrit.wikimedia.org/r/1191728

Change #1191729 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/WebAuthn@REL1_43] WebAuthnKey: Use PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORTS

https://gerrit.wikimedia.org/r/1191729

Change #1191728 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@REL1_44] WebAuthnKey: Use PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORTS

https://gerrit.wikimedia.org/r/1191728

Change #1191729 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@REL1_43] WebAuthnKey: Use PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORTS

https://gerrit.wikimedia.org/r/1191729

The patch has been merged. but it's unclear if this helped with iPhones, or even made things worse (as per T358771#10219134). Needs to be re-tested (preferably with $wgWebAuthnLimitPasskeysToRoaming turned off).

@Tonymetz are you able to re-test (in a week once the patch is in production) whether the issue you were experiencing is fixed now?

Change #1192307 had a related patch set uploaded (by Bartosz Dziewoński; author: Bartosz Dziewoński):

[mediawiki/extensions/WebAuthn@master] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192307

Change #1192307 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@master] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192307

Change #1192586 had a related patch set uploaded (by Reedy; author: Bartosz Dziewoński):

[mediawiki/extensions/WebAuthn@REL1_44] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192586

Change #1192587 had a related patch set uploaded (by Reedy; author: Bartosz Dziewoński):

[mediawiki/extensions/WebAuthn@REL1_43] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192587

Change #1192586 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@REL1_44] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192586

Change #1192587 merged by jenkins-bot:

[mediawiki/extensions/WebAuthn@REL1_43] Remember key transports during registration and request them during authentication

https://gerrit.wikimedia.org/r/1192587

matmarex claimed this task.
matmarex removed a project: Patch-For-Review.

It works for me. Given no response from @Tonymetz, I assume this is fixed (but if it isn't, please reopen).

hi guys i'll see if I can repo. thanks for the continued effort . i've since removed tokens but i'll try to help confirm the resolution.

Microsoft Edge	145.0.3800.22 (Official build) beta (64-bit) 
Revision	7be60baa68d705e70f501a1837f69b4ddf671159
Chromium version	145.0.7632.18
Operating system	Windows 11 Version 25H2 (Build 26220.7653)

iOS Version  26.2

I tested the new Passkeys feature for Wikipedia/Wikimedia -- which shares some code with webauthn. Here are the flows I tested and are working. The "login with passkey created on another device" was the reason for this ticket -- and it works with the Passkeys feature.

  • ✅ Create Windows Hello (local TPM) passkey on MS Edge
  • ✅ Create iPhone Passkey on MS Edge
  • ✅ Login with Windows Hello Passkey on MS Edge
  • ✅ Login with iPhone Passkey (created via MS Edge) on MS Edge
  • ✅ Login with iPhone Passkey (created via MS Edge) on Iphone / Safari