Posts

Post not yet marked as solved
15 Replies
@garrett-davidson I tried a huge number of variations, and one factor that proved to be key was that of the aaguid. In an earlier iteration I was using 00000000-0000-0000-0000-000000000000, but then at some point I thought it seemed weird that that would work better than a real UUID that actually uniquely identified the device, so I made the switch but was still blocked by other issues. After resolving all of those other issues, everything finally worked when I eventually set the aaguid back to 00000000-0000-0000-0000-000000000000 as I had had it many iterations prior.
Post not yet marked as solved
15 Replies
Here I've attached the system logs that lead up to the failure, in the hopes that the golden nugget of insight that I so desperately need is in there... The very last line is the one I mentioned above: error 14:02:18.222529+0100 AuthenticationServicesAgent 19621528 <Missing Description> Request cancelled due to AuthenticatorManager::cancelRequest being called. Scrolling upward (backwards in time) from that last line there are a number of logs that seem to me potentially relevant. For example: default 14:02:18.222589+0100 CredentialProvider-macOS 0 connection [0x12a8c5b50] invalidated after getting a no-senders notification - client is gone default 14:02:18.222505+0100 AuthenticationServicesAgent 19593644 Authorization Received internal cancel. Dropping. default 14:02:18.222248+0100 AuthenticationServicesAgent 19593645 Authorization Asked to cancel operation 0420A06B-1595-4B97-9FB9-6915EA2EDDD8, override error: Error Domain=com.apple.AuthenticationServicesCore.AuthorizationError Code=12 "(null)" logs.txt
Post not yet marked as solved
15 Replies
P.S. You said in your last reply: "Your extension should have received an error if those weren't set" but I'm not aware of how errors are propagated back to my extension. extensionContext.completeAssertionRequest(using:) is not a throwing function, and the completion handler variant does not pass any error value into the completion handler. If there's some mechanism for receiving errors in my extension that I am unaware of I would love to know about it!
Post not yet marked as solved
15 Replies
There is actually one more error message that shows up in the console that I hope might quickly lead to the answer of how to solve this (hopefully final) roadblock: Request cancelled due to AuthenticatorManager::cancelRequest being called. This message appears directly after the other message I mentioned: Assertion failed: Error Domain=WKErrorDomain Code=31 "(null)". They are separated by about half a second. I believe the second error message is coming from this function that I found in WebKit: void AuthenticatorManager::cancelRequest() { invokePendingCompletionHandler(ExceptionData { ExceptionCode::NotAllowedError, "This request has been cancelled by the user."_s }); RELEASE_LOG_ERROR(WebAuthn, "Request cancelled due to AuthenticatorManager::cancelRequest being called."); clearState(); m_requestTimeOutTimer.stop(); } @garrett-davidson, if you're willing, please let me know if you know of anything that I should check for that would cause this function to be called. My extension initially invokes extensionContext.cancel(withErrorCode: .userInteractionRequired) to trigger the UI to appear, but that is not when the error appears. It is after my extension calls extensionContext.completeAssertionRequest(using:) that the message appears. I am not waiting a long time to trigger this call, so I don't think that any timeouts are being reached. After completing the assertion request, my extension does not invoke the cancel function itself. I'm experiencing this on google.com, and I doubt that they're accidentally invoking the cancel function in a place where they shouldn't. Note that the same error appears in the console if I click "Cancel" on the initial system modal instead of clicking "Continue" in order to summon my extension. One final possible-relevant clue that I'll mention is that when I initiate the authentication operation I am actually still seeing the error: No matched credentials are found in the platform attached authenticator. despite the fact that the system modal successfully identifies my extension as having the requested passkey and allows me to proceed. Thank you for reading 🙏
Post not yet marked as solved
15 Replies
These are the flags I'm passing: generateAuthDataFlags( userIsPresent: true, userHasBeenVerified: true, passkeyIsEligibleForBackup: true, passkeyIsBackedUp: true, includesAttestedCredentialData: false, includesExtensionData: false ) where the function is defined as: func generateAuthDataFlags( userIsPresent: Bool, userHasBeenVerified: Bool, passkeyIsEligibleForBackup: Bool, passkeyIsBackedUp: Bool, includesAttestedCredentialData : Bool, includesExtensionData: Bool ) -> UInt8 { /// UInt8(0b00000000) .plus(userIsPresent ? 0b00000001 : 0) .plus(false ? 0b00000010 : 0) .plus(userHasBeenVerified ? 0b00000100 : 0) .plus(passkeyIsEligibleForBackup ? 0b00001000 : 0) .plus(passkeyIsBackedUp ? 0b00010000 : 0) .plus(false ? 0b00100000 : 0) .plus(includesAttestedCredentialData ? 0b01000000 : 0) .plus(includesExtensionData ? 0b10000000 : 0) } Also, you mentioned that the relying party identifier could be wrong, but I'm simply taking the value directly from the incoming ASPasskeyCredentialRequest.credentialIdentity.relyingPartyIdentifier. Again, I'm providing additional info just in case the answer to my problem occurs to you easily, since you've been generously helping me debug this, not because I'm expecting you to wrack your brain trying to find the needle in my haystack from afar.
Post not yet marked as solved
15 Replies
Thank you, this is very helpful. So far it hasn't led me any obvious answers, but I'll keep investigating. At first glance: If I understand correctly, the error would be coming from the authenticatorGetAssertion operation. In the specification, there seem to be only two possible triggers: Step 6: If credentialOptions is now empty, return an error code equivalent to "NotAllowedError" and terminate the operation. or step 7, which ends in: If the user does not consent, return an error code equivalent to "NotAllowedError" and terminate the operation. I think that the fact that the system modal offers the passkey via my extension means that step 6 should not be triggering an error. Regarding step 7, the flags I'm returning have both bit 0 ("User Present") and bit 2 ("User Verified") set to true. Perhaps those two bits are not necessarily sufficient to prevent the error from being thrown in step 7? I just thought I'd write this here in case it reveals some obvious flaw in my reasoning that's easy for you to spot and point out. Thanks for everything.
Post not yet marked as solved
15 Replies
Thank you @garrett-davidson, your various pieces of insight and advice both emboldened and empowered me to figure out the mistake I was making, and that problem is now resolved... 🎉 However, I have run into a new error which has left me with a new question that I would love your feedback on if you're willing. Now, the system recognizes that my extension can provide the passkey, and therefore the system modal displays my app icon and allows me to proceed. It shows my extension UI which prompts the user to authenticate. After my extension has called extensionContext.completeAssertionRequest(using:) the webpage tells me that an error has occurred. In the system console I see only this error: Assertion failed: Error Domain=WKErrorDomain Code=31 "(null)" I tried searching for the string "Assertion failed" in WebKit, and found three results but none of them seemed like the source of the error. This error does not appear when I authenticate on webauthn.me, so I am limited in terms of the feedback I receive about what exactly is going wrong. At the moment the only lead I have in mind is that I realized that the ASPasskeyCredentialRequest value that my extension receives does not have any property named challenge or anything similar. It has clientDataHash which comes with a documentation comment Hash of client data for credential provider to sign as part of the assertion/registration operation., so that's what I am currently signing with the passkey. The ASPasskeyAssertionCredential that my extension passes to extensionContext.completeAssertionRequest(using:) contains the signature, and the documentation for that property describes it as the signature for the assertion challenge.. I'm hoping that I'm signing the wrong thing and that that is why the assertion is failing. Is there some other place that I'm supposed to be accessing the challenge data? Thanks so much for all of your help so far and any more help that you provide.
Post not yet marked as solved
15 Replies
Thank you! This is very encouraging. Being able to see the code that is deciding to throw this error makes the task of resolving the issue feel much more in my control. I'll add that I'm experiencing this error on google.com and kayak.com, which are the main two sites that I'm testing with so far. Is there any way to step through the WebKit code as it executes or in any way gain access to the values of some the variables in play in that section of the code? If not it still seems like it may be enough of a lead to allow me to research my way to a solution, but some live inspection of values would presumably be extremely enlightening. Thanks for everything.
Post not yet marked as solved
15 Replies
Thanks so much for getting back to me @garrett-davidson . I've filed a request through the Feedback Assistant, and I hope you don't mind that I also ask you a little bit more in this thread. Firstly, the passkey logs via the terminal didn't yield anything very informative (I've pasted the logs all the way at the bottom). Secondly, I realized that in my original post I didn't mention that there is a potentially relevant error that appears in the system console when I attempt to authenticate using the newly created passkey: error 15:12:15.084213+0100 AuthenticationServicesAgent 0 <Missing Description> No matched credentials are found in the platform attached authenticator. Here is the error in the context of the surrounding console errors (just in case any of these other errors reveal something that I'm not picking up on): error 15:12:15.082058+0100 nfcd 0 Logging -[_NFHardwareManager listener:shouldAcceptNewConnection:]:84 PID 1573 () missing entitlement: com.apple.nfcd.hwmanager error 15:12:15.082315+0100 AuthenticationServicesAgent 0 Logging -[NFHardwareManager updateHWSupportWithXPC:waitForInit:]:361 Failed to get HW support : Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.nfcd.hwmanager" UserInfo={NSDebugDescription=connection to service named com.apple.nfcd.hwmanager} error 15:12:15.082503+0100 nfcd 0 Logging -[_NFHardwareManager listener:shouldAcceptNewConnection:]:84 PID 1573 () missing entitlement: com.apple.nfcd.hwmanager error 15:12:15.082819+0100 nfcd 0 Logging -[_NFHardwareManager listener:shouldAcceptNewConnection:]:84 PID 1573 () missing entitlement: com.apple.nfcd.hwmanager error 15:12:15.082673+0100 AuthenticationServicesAgent 0 Logging -[NFHardwareManager updateHWSupportWithXPC:waitForInit:]:361 Failed to get HW support : Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.nfcd.hwmanager" UserInfo={NSDebugDescription=connection to service named com.apple.nfcd.hwmanager} error 15:12:15.082986+0100 AuthenticationServicesAgent 0 Logging -[NFHardwareManager controllerInfoWithError:]:558 Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.nfcd.hwmanager" UserInfo={NSDebugDescription=connection to service named com.apple.nfcd.hwmanager} error 15:12:15.084213+0100 AuthenticationServicesAgent 0 <Missing Description> No matched credentials are found in the platform attached authenticator. error 15:12:15.101763+0100 pkd 2232554 ls could not create extension point record for <private>: Error Domain=NSOSStatusErrorDomain Code=-10814 UserInfo={_LSLine=85, _LSFunction=<private>} error 15:12:15.309050+0100 com.apple.WebKit.WebContent 0 ProcessSuspension 0x10a040100 - [sessionID=9223372036854775944] WebProcess::markAllLayersVolatile: Failed to mark layers as volatile for webPageID=37958 error 15:12:15.724853+0100 CredentialProviderExtensionHelper 2232557 NSExtension errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled} I'll finish by briefly breaking down my understanding of the situation, in the hopes that it can narrow down the conversation: My extension's Info.plist contains NSExtension -> NSExtensionAttributes -> ASCredentialProviderExtensionCapabilities -> ProvidesPasskeys: YES, which is demonstrably working as evidenced by the fact that I can use my extension to create a passkey via a webpage (google.com, for example). When creating a passkey, the system invokes prepareInterfaceToProvideCredential(for credentialRequest: ASCredentialRequest) on my extension, passing in a value which I am successfully able to cast as an ASPasskeyCredentialRequest. My job is then to create the passkey, save it according to the business rules of my app, insert the corresponding credential identity into the ASCredentialIdentityStore, and finally call extensionContext.completeAssertionRequest(using:) passing in an ASPasskeyAssertionCredential that contains a correctly formatted binary blob of authenticatorData (among other things). Based on my current knowledge and understanding, it seems to me that the only possible point of failure that could cause what I'm seeing is that, despite the ASCredentialIdentityStore accepting the credential identity without error, there is some issue with that identity which is causing it to not be recognized when I subsequently attempt to authenticate with the corresponding passkey. The main point I'm making here is that I think that if the authenticatorData binary blob is accepted by google.com and leads to a new passkey being added to my Google account, then that's not where the problem could lie. Is that a correct assumption? When I call extensionContext.completeAssertionRequest(using:) after creating the passkey does the system remember things about the ASPasskeyAssertionCredential that I pass in that could lead to my extension not being offered in the system modal when I try to authenticate later? Thank you so much for any advice/feedback you can offer me - I've been stuck with this issue for quite a long time now and I'll feel so relieved when I have resolved it. Very best, Jeremy Passkey Logs from terminal command AuthenticationServicesAgent: (AuthenticationServicesCore) [com.apple.AuthenticationServicesCore:Authorization] Initializing ASCAgent 0x1826a1e30. 1573 AuthenticationServicesAgent: AuthenticationServicestore [com.apple.AuthenticationServicesCore:Authorization] Received connection from com.apple.Safari 1573 AuthenticationServicesAgent: (AuthenticationServicesCore) [com.apple.AuthenticationServicesCore:Authorization] Allowing request from web browser. AuthenticationServicesAgent: (AuthenticationServices) [com.apple.AuthenticationServices:Authorization] Beginning operation 6363A0C7-039-4FDC-A650-31912795FEE5 for com.apple.Safari. 1573 AuthenticationServicesAgent: (AuthenticationServices) [com.apple.AuthenticationServices:Authorization] Creating panel 0x103d2f5b0 for 6363A0C7-039-4FDC-A650-31912795FEE5.
Post not yet marked as solved
15 Replies
Is there any information that I could add here to make this request more actionable? Is there anything I could clarify either about the information at hand or about what it is I’m asking? Thanks very much 🙏
Post marked as solved
5 Replies
You are exactly right, thank you! Evidently I was not careful enough when comparing the working Mac extension to the not-working iOS extension - in the iOS Info.plist I was using NSExtension > ASCredentialProviderExtensionCapabilities > ProvidesPasskeys = YES. Now the system offers my extension when creating passkeys. Now my iOS extension is suffering the same problem as my Mac extension, so if you have a chance to lend a helping hand on that one I would be hugely appreciative.
Post not yet marked as solved
1 Replies
I was struggling with this exact thing since yesterday, and was dismayed to see that no one had answered your question in 4 months. I just figured out what my issue was, which was that the minimum deployment version of the extension target was set to 15.4 and my phone is running something slightly lower than that. The minimum deployment version of the app itself was low enough, which resulted in the app installing and running fine on my phone, but the extension silently failing to show up in the list. I set the minimum deployment of the extension to 15.0 an re-ran the app on my iPhone and the extension immediately showed up in Settings -> Passwords -> Autofill passwords