help with passkey authentication

I'm trying to implement passkey authenticator on iOS.

while register works perfectly I'm still struggling with authenticating.

let's say this is the code I'm using to authenticate:

override func provideCredentialWithoutUserInteraction(for credentialRequest: ASCredentialRequest){

    guard let req: ASPasskeyCredentialRequest = credentialRequest as? ASPasskeyCredentialRequest else { return }

    let hashedRp = hashRP(req.credentialIdentity.serviceIdentifier.identifier)

    do {
        let privateKey: P256.Signing.PrivateKey = try P256.Signing.PrivateKey(derRepresentation: Data(base64Encoded: CredentialProviderViewController.base64PrivateString) ?? Data([]))

        let ad = hashedRp + [29, 0, 0, 0, 0]
        let sig = try privateKey.signature(
            for: SHA256.hash(data: Data(ad + req.clientDataHash))
        )

        let res: ASPasskeyAssertionCredential = ASPasskeyAssertionCredential(
            userHandle: Data(hashedRp[0..<16]),
            relyingParty: req.credentialIdentity.serviceIdentifier.identifier,
            signature: sig.rawRepresentation,
            clientDataHash: req.clientDataHash,
            authenticatorData: Data(ad),
            credentialID: Data(hashedRp[0..<16])
        )

        extensionContext.completeAssertionRequest(using: res)

    } catch {}
}

this will produce:

authentication failed: 1 validation error for authenticationCredential __root__ string argument should contain only ascii characters.

what am i doing wrong?

Replies

here is the error:

Are your userHandle and credentialId same? You need to fetch the userHandle and credentialId from the previously stored credential which was generated during registration ceremony. Not sure if that can be causing the issue.

Hi @letsbondiway1986 thank you for your response! It's just a PoC so I just used something I can regenerate easily without a database or something like that (I took the first 16 bytes of the hash of the rp id). But you are right this is what causes the problem. So the following question is: what should I use as the userHandle?

  • You should generate credentialIDs randomly yourself. They should not be predictable, as that can leak user information. The userHandle is specified by the website. You should use whatever value the site gives you.

  • thanks! can you tell me where can I find the userHandle in the request?

Add a Comment