webauthn authentication javascript formatting assistance

泪湿孤枕 提交于 2020-05-17 08:49:19

问题


I have been trying to figure out how to do 2fa with webauthn and I have the registration part working. The details are really poorly documented, especially all of the encoding payloads in javascript. I am able to register a device to a user, but I am not able to authenticate with that device. For reference, I'm using these resources:

https://github.com/cedarcode/webauthn-ruby

https://www.passwordless.dev/js/mfa.register.js

And specifically, for authentication, I'm trying to mimic this js functionality:

https://www.passwordless.dev/js/mfa.register.js

In my user model, I have a webauthn_id, and several u2f devices, each of which has a public_key and a webauthn_id.

In my Rails app, I do:

options = WebAuthn::Credential.options_for_get(allow: :webauthn_id)
session[:webauthn_options] = options

In my javascript, I try to mimic the js file above and I do (this is embedded ruby):

options = <%= raw @options.as_json.to_json %>
options.challenge = WebAuthnHelpers.coerceToArrayBuffer(options.challenge);
options.allowCredentials = options.allowCredentials.map((c) => {
    c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
    return c;
});

navigator.credentials.get({ "publicKey": options }).then(function (credentialInfoAssertion) 
{
            // send assertion response back to the server
            // to proceed with the control of the credential
alert('here');
}).catch(function (err) 
{
    debugger
    console.error(err);   /*  THIS IS WHERE THE ERROR IS THROWN */
});

The problem is, I cannot get past navigator.credentials.get, I get this error in the javascript console:

TypeError: CredentialsContainer.get: Element of 'allowCredentials' member of PublicKeyCredentialRequestOptions can't be converted to a dictionary

options at the time navigator.credentials.get is called looks like this:

I've tried every which way to convert my db-stored user and device variables into javascript properly encoded and parsed variables but cannot seem to get it to work. Anything obvious about what I'm doing wrong?

Thanks for any help, Kevin

UPDATE -

Adding options json generated by the server:

"{\"challenge\":\"SSDYi4I7kRWt5wc5KjuAvgJ3dsQhjy7IPOJ0hvR5tMg\",\"timeout\":120000,\"allowCredentials\":[{\"type\":\"public-key\",\"id\":\"OUckfxGNLGGASUfGiX-1_8FzehlXh3fKvJ98tm59mVukJkKb_CGk1avnorL4sQQASVO9aGqmgn01jf629Jt0Z0SmBpDKd9sL1T5Z9loDrkLTTCIzrIRqhwPC6yrkfBFi\"},{\"type\":\"public-key\",\"id\":\"Fj5T-WPmEMTz139mY-Vo0DTfsNmjwy_mUx6jn5rUEPx-LsY51mxNYidprJ39_cHeAOieg-W12X47iJm42K0Tsixj4_Fl6KjdgYoxQtEYsNF-LPhwtoKwYsy1hZgVojp3\"}]}"

回答1:


This is an example of the serialised JSON data returned by our implementation:

{
    "challenge": "MQ1S8MBSU0M2kiJqJD8wnQ",
    "timeout": 60000,
    "rpId": "identity.acme.com",
    "allowCredentials": [
        {
            "type": "public-key",
            "id": "k5Ti8dLdko1GANsBT-_NZ5L_-8j_8TnoNOYe8mUcs4o",
            "transports": [
                "internal"
            ]
        },
        {
            "type": "public-key",
            "id": "LAqkKEO99XPCQ7fsUa3stz7K76A_mE5dQwX4S3QS6jdbI9ttSn9Hu37BA31JUGXqgyhTtskL5obe6uZxitbIfA",
            "transports": [
                "usb"
            ]
        },
        {
            "type": "public-key",
            "id": "nbN3S08Wv2GElRsW9AmK70J1INEpwIywQcOl6rp_DWLm4mcQiH96TmAXSrZRHciZBENVB9rJdE94HPHbeVjtZg",
            "transports": [
                "usb"
            ]
        }
    ],
    "userVerification": "discouraged",
    "extensions": {
        "txAuthSimple": "Sign in to your ACME account",
        "exts": true,
        "uvi": true,
        "loc": true,
        "uvm": true
    }
}

This is parsed to an object and the code used to coerce those base64url encoded values is:

credentialRequestOptions.challenge = WebAuthnHelpers.coerceToArrayBuffer(credentialRequestOptions.challenge);

credentialRequestOptions.allowCredentials = credentialRequestOptions.allowCredentials.map((c) => {
    c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
    return c;
});

Hope that helps. The JSON data is retreived via a fetch() call and the byte[] fields are encoded as base64url on the serverside.



来源:https://stackoverflow.com/questions/61798641/webauthn-authentication-javascript-formatting-assistance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!