Determining if user has passkey for service already?

I'm working my way through adding passkey support to my app. At app launch, I'd like to test to see if the user has already created a passkey for the service, and if not, immediately present the account creation UI.

Is there an API call I can make to see if the user already has a credential? From the examples I’ve found, it seems I should just try to sign in, and I’ll get an error callback if there are no stored credentials. Is that right?

When I try to just sign in without any credentials, it presents a QR code. That is, when it doesn't report an error that the app site association is bad (seems to alternate with subsequent attempts).

I talked about a few different options for how to handle this in the passkeys session video :)

I should clarify: My app will use only passkeys for signin. No username/password. I kinda don’t want usernames to be visible to the user at all, but I suppose they're necessary to allow different users to use the same device.

I'm watching the video now, looking for those options. I have some other feedback too:

Avoiding Typing Wherever Possible

In the example where you want to log into your account on your friend’s PC, the flow requires you to type in your username first. I don't know if that's a WebAuthn requirement, or something that site implemented, but I think a better experience would be for there to be a "Log in as Someone Else" button that presents the QR code without requiring me to type something (it can be very hard to type on some devices). The QR code can identify the relying party, device, and challenge to whatever other device is used for authentication. That latter device can then provide the username and signed challenge to the server (presenting the owner with options for different usernames), which can complete the loop with the PC.

Before I learned about passkeys, I built a similar flow for CNC machines that have awful user interfaces.

Streamlining

Ah, it looks like .preferImmediatelyAvailableCredentials might help me!

The only thing I think I might like to have is a "Create Account" button on the OS sign-in form that calls back my delegate so I can lead the user through creating an(other) account.

As I've thought about my app’s use case a bit more, I'm beginning to think I don't even need a passkey. I’m not 100% sure about this, though.

All of this thinking is in the context of my app and server using Apple App Attestation to ensure it’s the only thing making requests.

My app needs to interact with its server to provide some background processing for the user that I can't rely on iOS to provide: it needs to wake up at a specified time, do some small network calls to a third party that can take some time to complete (waiting for the other end), and then, depending on the result of those network calls, notify the user. (I had initially coded this using the the available iOS APIs, and found them unreliable. I then used OneSignal to schedule background push notifications that were more reliable, but iOS wouldn't let my app wake long enough to complete the network requests. This, coupled with OneSignal changes, led me to making my own server). By pushing the scheduling and network calls to my server, I didn't have to rely on iOS.

But now the server has to differentiate users and store a per-user auth token for the third-party server. That made me think I needed passkeys to safely identify each user.

But now I'm thinking perhaps not. During onboarding, my app can request an identifying token from the server (much like the auth token it gets after a successful passkey ceremony). It then sends that on all subsequent requests. Stored in iCloud Keychain, that should allow them to connect their other devices to the same account, right?

I think this is secure, in that no unauthorized person should be able to access a given user’s account on my server. There may be a risk that the user loses access to their account state on the server, if they ever lose that auth token. But in this application, the server state is fairly easy to re-create from scratch, I think.

Thoughts?

• App Attestation ensures all requests come only from my app. • Server generates a user-identifying token, app stores it in iCloud Keychain. • App sends that token with all user-centric requests.

At no point does the user have to concern themselves with creating or remembering a user account, or even using passkeys.

(I do hate that I’ll be discarding all that lovely passkey work I did, but I’ll need it on another project soon enough).

Determining if user has passkey for service already?
 
 
Q