iosswiftwebauthnpasskey

How do I show passkeys in the autofill prompt when the user taps the "key icon"?


I'm busy implementing passkeys but I'm encountering an issue with the autofill feature.

According to the WWDC video (https://developer.apple.com/videos/play/wwdc2022/10092/ at around 14:30), when the user taps the "key icon" in the quick type bar, the user is presented with a prompt to choose a passkey or password to login, and (very important!) also the ability to "Use Passkey from a Nearby Device...".

Correct modal that I want to show

However, my app (and most others) only gives the user the ability to choose a password.

Incorrect modal that currently gets shown

How can I get my app to show the first modal (that includes passkeys)?


Solution

  • Only passkey requests are allowed on the ASAuthorizationController when using performAutoFillAssistedRequests()

    As per the shiny example:

    // AutoFill-assisted requests only support ASAuthorizationPlatformPublicKeyCredentialAssertionRequest.
    

    PS: Remember to cancel this request afterwards! You can do this by storing a reference to the ASAuthorizationController (ex. self.authController = authController) and when you want to cancel the request then simply call authController.cancel()

    So the complete solution should look something like this:

    var authController: ASAuthorizationController?
    
    func beginAutoFillAssistedPasskeySignIn(anchor: ASPresentationAnchor) {
        self.authenticationAnchor = anchor
        
        let publicKeyCredentialProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain)
        
        // Fetch the challenge from the server. The challenge needs to be unique for each request.
        let challenge = Data()
        let assertionRequest = publicKeyCredentialProvider.createCredentialAssertionRequest(challenge: challenge)
        
        // AutoFill-assisted requests only support ASAuthorizationPlatformPublicKeyCredentialAssertionRequest.
        let authController = ASAuthorizationController(authorizationRequests: [ assertionRequest ] )
        authController.delegate = self
        authController.presentationContextProvider = self
        authController.performAutoFillAssistedRequests()
        self.authController = authController
    }
    
    func cancelAutoFillAssistedPasskeySignIn() {
        if let authController {
            authController.cancel()
            self.authController = nil
        }
    }