I am implementing a simple PoC application in React Native for iOS and trying to attest an authenticator using react-native-passkey
library, however, I am struggling to verify the attestation response I am getting from my client to my Nest.JS server that utilizes @simplewebauthn/server
dependency for generating responses. The issue appears to be a mismatch in the provided clientDataJSON challenge field and the one generated on the server.
Here's the challenge I am generating:
i-1E5Fhg0so0Xd3CInFzHG7EVQfWqazTgf-m26flrsQ
And here's the client data challenge that I've extracted by first converting the base64 string to a utf8 one and parsed it via JSON.parse
:
{
type: 'webauthn.create',
challenge: 'aS0xRTVGaGcwc28wWGQzQ0luRnpIRzdFVlFmV3FhelRnZi1tMjZmbHJzUQ',
origin: <redacted>
}
The origin is redacted on purpose. It is a valid domain that is used by my EC2 instance and has all of the endpoints needed for proper attestation/assertion flows.
I have read on the W3C spec that Apple inject some sort of client data hash in the challenge before signing it. I am not sure what to make of those specification details as they are simply too high tech for my dumbass to understand.
So, my question would be, what bytes do I need to concatenate to my challenge to make it appear the same as the one returned by my iOS app?
I tried fetching an endpoint on my server, getting that information to the iOS authenticator, and returning its response back to the server. I expected the challenge returned in client data to match the one generated by the server.
Down in the comments to the correct answer of this particular question I have spawned a conversation about verification difficulties of the assertion signature.
Here's the new question for it.
In your response you have
{
type: 'webauthn.create',
challenge: 'aS0xRTVGaGcwc28wWGQzQ0luRnpIRzdFVlFmV3FhelRnZi1tMjZmbHJzUQ',
origin: <redacted>
}
And here, the aS0xRTVGaGcwc28wWGQzQ0luRnpIRzdFVlFmV3FhelRnZi1tMjZmbHJzUQ
would be base64 encoded.
If I decode it I get i-1E5Fhg0so0Xd3CInFzHG7EVQfWqazTgf-m26flrsQ
which is the same as you pasted in as i-1E5Fhg0so0Xd3CInFzHG7EVQfWqazTgf-m26flrsQ
and you say you generated.
So, the problem according to the comment the question also seems to included how to validate a Apple Anonymous Attestation Statement so including this as part of the answer.
As per Webauthn Apple is validated a bit differently than your standard cryptographic signature, or as per the step list
So from the list we can see that we need to get a hold of authenticatorData, which is part of the response, and the clientDataHash, which is part of the request. Both are accessible through fields in Webauthn as per your comment. So for you the concat would be correct and you would then check the hash value of it versus the credCert part of the x5c in the attStmt of the response as per step 3 and 4.