FIDO2 C++ based application using WebAuthn.dll for "YUBIKEY 5 NFC" (External authenticator) gives "This Security Key doesn't look familier. Please try a different one."

Mahaboob Aslam 1 Reputation point
2021-03-09T10:45:32.567+00:00

Hi

I am writing FIDO2 C++ based application using WebAuthn.dll for "YUBIKEY 5 NFC" (External authenticator) using the following WebAutheN APIs of Microsoft from the
https://github.com/microsoft/webauthn/blob/master/webauthn.h

            HRESULT WINAPI WebAuthNAuthenticatorMakeCredential(
                         _In_        HWND                                                hWnd,
                             _In_        PCWEBAUTHN_RP_ENTITY_INFORMATION                    pRpInformation,
                             _In_        PCWEBAUTHN_USER_ENTITY_INFORMATION                  pUserInformation,
                             _In_        PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS               pPubKeyCredParams,
                             _In_        PCWEBAUTHN_CLIENT_DATA                              pWebAuthNClientData,
                             _In_opt_    PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS    pWebAuthNMakeCredentialOptions,
                             _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_ATTESTATION      *ppWebAuthNCredentialAttestation);

            HRESULT WINAPI WebAuthNAuthenticatorGetAssertion(
                            _In_        HWND                                                hWnd,
                            _In_        LPCWSTR                                             pwszRpId,
                            _In_        PCWEBAUTHN_CLIENT_DATA                              pWebAuthNClientData,
                            _In_opt_    PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS      pWebAuthNGetAssertionOptions,
                            _Outptr_result_maybenull_ PWEBAUTHN_ASSERTION                   *ppWebAuthNAssertion);

I am able to get the registration successfully with the IdP (Identity Provider) using C++ API WebAuthNAuthenticatorMakeCredential() in my code.

But when it comes to Authentication, i am facing problem with the api WebAuthNAuthenticatorGetAssertion() as follows:

"This Security Key doesn't look familiar. Please try a different one."

image

Below is my code :
============

            HWND  hWnd = GetForegroundWindow();
            LPCWSTR   pwszRpId = L"tenet.domain.com";

                            //My client data in json format is as below...
            sClientData64 = {"type":"webauthn.get","challenge":"MKB9ApSESppXbU-oVW_M","origin":"https://tenet.domain.com","crossOrigin":true};

            WEBAUTHN_CLIENT_DATA oClientData_in = { WEBAUTHN_CLIENT_DATA_CURRENT_VERSION,
                                static_cast<DWORD>(sClientData64.length()),
                                (PBYTE)(sClientData64.data()),
                                WEBAUTHN_HASH_ALGORITHM_SHA_256 
                                          };

I tried to manipulate the values as in the following link: https://github.com/Yubico/python-fido2/blob/master/fido2/win_api.py to implement
the structure "WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS" below:

My allow list code is as follows:
====================

            std::vector<WEBAUTHN_CREDENTIAL_EX> allowCredentials;             
            WEBAUTHN_CREDENTIAL_EX* pAllowCredentials = nullptr;
            std::vector<WEBAUTHN_CREDENTIAL_EX*> allowCredentialsPtrs;

            WEBAUTHN_CREDENTIAL_LIST allowCredentialList = { 0 };
            WEBAUTHN_CREDENTIAL_LIST* pAllowCredentialList = nullptr;

            DWORD dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4; // the value is 4

            if(dwversion is >= 4)
            {
                DWORD winTransports = 0;

                std::string sAuthenticatorType = "usb";
                int nTransport = 0;
                if(sAuthenticatorType == "usb")
                { 
                    nTransport = 1;
                }

                if (nTransport & U2F_AUTHENTICATOR_TRANSPORT_USB)
                {
                    winTransports |= WEBAUTHN_CTAP_TRANSPORT_USB;
                }                   

                WEBAUTHN_CREDENTIAL_EX webCredEx = {    WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION,
                                    static_cast<DWORD>(sCredentialId.length()),
                                    ((BYTE*)(sCredentialId.c_str())),
                                    WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY,
                                    winTransports
                                   };

                allowCredentials.push_back(webCredEx);              

                pAllowCredentials = allowCredentials.data();
                for (DWORD i = 0; i < allowCredentials.size(); i++)
                {
                    allowCredentialsPtrs.push_back(&pAllowCredentials[i]);
                }
                allowCredentialList.cCredentials = allowCredentials.size();  // original
                allowCredentialList.ppCredentials = allowCredentialsPtrs.data(); // original
                pAllowCredentialList = &allowCredentialList;  // my AllowCredentialList value
            }

// Credentials is as follows:
==================

            WEBAUTHN_CREDENTIALS webCredentials = {0,NULL};

            DWORD dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3; // the value is 3

            if(dwversion is >= 3)
            {
                std::vector<WEBAUTHN_CREDENTIAL> vCredential;
                std::vector<WEBAUTHN_CREDENTIAL*> pCredential;
                WEBAUTHN_CREDENTIAL webAuthCredential = {WEBAUTHN_CREDENTIAL_CURRENT_VERSION,
                                 static_cast<DWORD>(sCredentialId.length()),
                                 ((BYTE*)(sCredentialId.c_str())),
                                 WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY
                                };
                WEBAUTHN_CREDENTIAL *pwebCredential;
                vCredential.push_back(webAuthCredential);
                pwebCredential = vCredential.data();
                for (DWORD i = 0; i < vCredential.size(); i++)
                {
                    pCredential.push_back(&pwebCredential[i]);
                }
                webCredentials.cCredentials = vCredential.size();
                webCredentials.pCredentials = pwebCredential;
            }

// filling this structure based on the dwVersion.. as the code above.

            WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS   oWebAuthNGetAssertionOptions = { 
                       dwVersion,  // version
                       10000,  // time in milliseconds
                       webCredentials,  //WEBAUTHN_CREDENTIALS  
                       {0, NULL},  //WEBAUTHN_EXTENSIONS
                       dwAuthenticatorAttachement,  // for Platform (Windows Hello) vs Cross platform authenticator (Yubikey)
                       winUserVerificationReq,  // user Verification Required (preferred)
                       0,  // dwFlags
                       NULL, // as json data received it is null
                                               pbU2fAppIdUsed, //(FALSE) this is a pointer
                       NULL,  // pCancellationId
                       pAllowCredentialList  // allowList if (dwversion is >= 4) else allowlist is null
                               };

            WEBAUTHN_ASSERTION* pWebAuthNAssertion = nullptr;  // this is an output parameter, 

             // on calling, I get a dialog popup saying  " This Security key doesn't look familiar. please try a different one."

            hResult = WebAuthNAuthenticatorGetAssertion(hWnd, pwszRpId &oClientData_in, &oWebAuthNAssertionOptions, &pWebAuthNAssertion);  

I took the python code for reference from the https://github.com/Yubico/python-fido2/blob/master/fido2/win_api.py

            if (dwVersion >= 3)
                    self.pCancellationId = cancellationId  (NULL)

                if self.dwVersion >= 4:
                    clist = WebAuthNCredentialList(credentials)
                    self.pAllowCredentialList = ctypes.pointer(clist)
                else:

self.CredentialList = WebAuthNCredentials(credentials)

Please let me know, if any thing has to added in my code.

Thankyou.

Windows 10 Security
Windows 10 Security
Windows 10: A Microsoft operating system that runs on personal computers and tablets.Security: The precautions taken to guard against crime, attack, sabotage, espionage, or another threat.
2,747 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Teemo Tang 11,331 Reputation points
    2021-03-10T06:56:56.93+00:00

    Please note: for development related issue, you could ask for help from github forum.
    https://github.com/topics/webauthn
    The reason why we recommend posting appropriately is you will get the most qualified pool of respondents, and other partners who read the forums regularly can either share their knowledge or learn.
    Thanks for your understanding and cooperating.
    Windows 10 security forum is used for discussing the issue which is related to Windows 10 built-in security features such as Windows Defender.

    -------------------------------------------------------------------------------------

    If the Answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Alex Seigler 1 Reputation point
    2021-03-10T15:23:27.937+00:00

    Do you get any further if you replace webCredentials with {0, NULL} and/or set pAllowCredentialList to NULL in the oWebAuthNGetAssertionOptions? I would start there and work forward.

    0 comments No comments