Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"AttestationObject invalid CBOR" with integrated iOS Passkeys Attestation function #357

Open
androidseb25 opened this issue Dec 19, 2022 · 14 comments

Comments

@androidseb25
Copy link

Hi I'm trying to use the lib with the integrated passkey function from Apple under iOS.
Every time I try to complete the registration I get a CBOR error from the lib with following response "AttestationObject invalid CBOR (Declared definite length of CBOR data item exceeds available buffer size.)"
When I try this in the browser it works.

Is there a solution for this or does this library not work with the iOS passkeys?

@aseigler
Copy link
Collaborator

While I haven't tried it myself, I don't see any reason why it wouldn't work as is right now. I'm curious what you mean by When I try this in the browser it works.. What exactly are you doing when it doesn't work? Are you able to provide a sample of the AttestationObject?

@androidseb25
Copy link
Author

androidseb25 commented Dec 20, 2022

Of course here are a example of my credential option that I get from server with the challenge and the Payload I sent to the server with the AttestationObject from the Passkey verification.

CredentialOption:

{"rp":{"id":"localhost","name":"Fido2 Test"},"user":{"name":"Test","id":"VGVzdA","displayName":"Display Test"},"challenge":"aDL84n7ODBul0JIeriAvqa4Q9n0eR06k7pFZjksdDfK7GQtLD3MoU3EADA9TmPzS24cIN72MuMFlLruj4pL9aA","pubKeyCredParams":[{"type":"public-key","alg":-7},{"type":"public-key","alg":-257},{"type":"public-key","alg":-37},{"type":"public-key","alg":-35},{"type":"public-key","alg":-258},{"type":"public-key","alg":-38},{"type":"public-key","alg":-36},{"type":"public-key","alg":-259},{"type":"public-key","alg":-39},{"type":"public-key","alg":-8}],"timeout":30000,"attestation":"none","authenticatorSelection":{"authenticatorAttachment":"cross-platform","requireResidentKey":false,"userVerification":"preferred"},"excludeCredentials":[],"extensions":{"exts":true,"uvm":true},"status":"ok","errorMessage":""}

Payload (like the object in the api):

{ "rawId" : "m0YHSxE\/3j483XnoGgNLE0Z+fUI=", "id" : "m0YHSxE\/3j483XnoGgNLE0Z+fUI=", "extensions" : { "appid" : false, "authnSel" : false }, "response" : { "attestationObject" : "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViY34zVTIo5whmj4gmSk5rN+JXS7PPo2o1ADVHU6UeNq+FdAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJtGB0sRP94+PN156BoDSxNGfn1CpQECAyYgASFYIA3+DhW9g6WqPnV86oKlHt3MRBJiozU7tdRe56zy0NKYIlggogy23\/bQCr6mhr5x46wnBGCuXbhwt7sAhjQNd+WG3A4=", "clientDataJSON" : "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiWVVSTU9EUnVOMDlFUW5Wc01FcEpaWEpwUVhaeFlUUlJPVzR3WlZJd05tczNjRVphYW10elpFUm1TemRIVVhSTVJETk5iMVV6UlVGRVFUbFViVkI2VXpJMFkwbE9OekpOZFUxR2JFeHlkV28wY0V3NVlVRSIsIm9yaWdpbiI6Imh0dHBzOi8vc2ViYXN0aWFucmFuay5kZSJ9" }, "type" : "public-key" }

And that's the error message that I receive:

{"Result":null,"status":"error","errorMessage":"AttestationObject invalid CBOR (Declared definite length of CBOR data item exceeds available buffer size.)"}

@androidseb25
Copy link
Author

I know, but why the apple function ASAuthorizationPlatformPublicKeyCredentialRegistration send's me this invalid credential in the app as a rawAttestationObject (this Object contains only bytes) that I convert to a base64 string.

I followed the guidelines from here: https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication/supporting_passkeys

@androidseb25
Copy link
Author

I've posted the question on the Apple developer forum now, let's see if there are some ideas why it's not working and the CBOR object is malformed

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

@androidseb25
Copy link
Author

So i decoded the object now by myself, maybe it help to find out why it not work.
That's the results:

The decoded attestationObject:
{ fmt: "none", attStmt: nil, authData: [223, 140, 213, 76, 138, 57, 194, 25, 163, 226, 9, 146, 147, 154, 205, 248, 149, 210, 236, 243, 232, 218, 141, 64, 13, 81, 212, 233, 71, 141, 171, 225, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 155, 70, 7, 75, 17, 63, 222, 62, 60, 221, 121, 232, 26, 3, 75, 19, 70, 126, 125, 66, 165, 1, 2, 3, 38, 32, 1, 33, 88, 32, 13, 254, 14, 21, 189, 131, 165, 170, 62, 117, 124, 234, 130, 165, 30, 221, 204, 68, 18, 98, 163, 53, 59, 181, 212, 94, 231, 172, 242, 208, 210, 152, 34, 88, 32, 162, 12, 182, 223, 246, 208, 10, 190, 166, 134, 190, 113, 227, 172, 39, 4, 96, 174, 93, 184, 112, 183, 187, 0, 134, 52, 13, 119, 229, 134, 220, 14] // <-- Byte Array }

decoded authData:

Is that the publickey?

{ "3": -6, "-2": "ogy23/bQCr6mhr5x46wnBGCuXbhwt7sAhjQNd+WG3A4=", // <-- Byte array as Base64 "-0": 1, "1": 2, "-1": "Df4OFb2Dpao+dXzqgqUe3cxEEmKjNTu11F7nrPLQ0pg=" // <-- Byte array as Base64 }

The rest of the authData Object:
{ "rpIdHash": "34zVTIo5whmj4gmSk5rN+JXS7PPo2o1ADVHU6UeNq+E=", // <-- Byte array as Base64 "counterBuffer": 0, "flags": { "UserPresence": true, "UserVerification": true, "AttestationData": true, "ExtensionData": false, "flagsInt": 93 }, "counterBuffer": "AAAAAA==", // <-- Byte array as Base64 "AAGUID"; "00000000-0000-0000-0000-000000000000", "cosePublicKeyBuffer": nil, "coseExtensionsDataBuffer": nil, "restOfDatainBufferAvailable": "pQECAyYgASFYIA3+DhW9g6WqPnV86oKlHt3MRBJiozU7tdRe56zy0NKYIlggogy23/bQCr6mhr5x46wnBGCuXbhwt7sAhjQNd+WG3A4=" //<-- Byte Count (77); Byte array as Base64 }

@aseigler
Copy link
Collaborator

By padding out the end with zeroes until the decoder is happy I can see we have format none, no attestation statement, then this for the authData:

DF8CD54C8A39C219A3E20992939ACD2574BB3CFA36A3500354753A51E36A15D000000000000000000000000000000000000000000149B46074B113FDE0F375E7A0680D2C4D19F9F50A9404080C988004856080370E15BD83A5AA3E757CEA82A51EDDCC441262A3353BB5D45EE7ACF2D0D298225820A20CB6DFF6D00ABEA686BE71E3AC270460AE5DB870B7BB0086340D7561B70300000000

Further tearing that apart, the first 32 bytes are the rpId hash:

DF8CD54C8A39C219A3E20992939ACD2574BB3CFA36A3500354753A51E36A15D0

That much looks reasonable, then everything goes sideways, because flags is zero and that doesn't make sense because there is more stuff at the end. I can't spot anything in there that resembles a passable credential public key.

@androidseb25
Copy link
Author

mmmmh that's not good 😅
In the Apple Developer forum, no one reports on this either :/

What can I do so that we can find a solution to this problem?
I really want it to work from the app with the API ^^

@androidseb25
Copy link
Author

androidseb25 commented Jan 9, 2023

@aseigler I got a response on the apple developer forum, can you please take a look?

He is saying that when we disable the "URL Decode" and "To Hex" steps in the cyberchef test, the attestation object return correct.

result from cyberchef:

{ "fmt": "none", "attStmt": {}, "authData": { "type": "Buffer", "data": [ 223, 140, 213, 76, 138, 57, 194, 25, 163, 226, 9, 146, 147, 154, 205, 248, 149, 210, 236, 243, 232, 218, 141, 64, 13, 81, 212, 233, 71, 141, 171, 225, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 155, 70, 7, 75, 17, 63, 222, 62, 60, 221, 121, 232, 26, 3, 75, 19, 70, 126, 125, 66, 165, 1, 2, 3, 38, 32, 1, 33, 88, 32, 13, 254, 14, 21, 189, 131, 165, 170, 62, 117, 124, 234, 130, 165, 30, 221, 204, 68, 18, 98, 163, 53, 59, 181, 212, 94, 231, 172, 242, 208, 210, 152, 34, 88, 32, 162, 12, 182, 223, 246, 208, 10, 190, 166, 134, 190, 113, 227, 172, 39, 4, 96, 174, 93, 184, 112, 183, 187, 0, 134, 52, 13, 119, 229, 134, 220, 14 ] } }

It look the same that I have decoded above.

@aseigler
Copy link
Collaborator

aseigler commented Jan 9, 2023

Looking at it again now the problem is obvious: all of the various fields that are required by spec to be base64 URL encoded are all standard base64 encoded instead. No clue why I didn't see that before.

@abergs
Copy link
Collaborator

abergs commented Jan 16, 2023

@aseigler I will try to figure out a way to discover this and help users figure it out. This is such a source of confusion and so easy to get wrong.

@androidseb25
Copy link
Author

@abergs have you already found something how to get it working in my iOS project?

@abergs
Copy link
Collaborator

abergs commented Feb 7, 2023

@androidseb25 Actually @aseigler already found your problem, the data is base64 encoded when it should be base64url encoded.

My comment was rather a way for us to discover this on the server and return a better error message.

@filipw
Copy link
Contributor

filipw commented Apr 5, 2023

thank you for this thread. I ran into the exact same invalid CBOR problem when integrating iOS, and indeed switching from base64 to base64urlencoded resolved the issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants