app/static/assets/js/vendors/webauthn.js

138 lines
4.1 KiB
JavaScript
Raw Normal View History

2020-05-05 16:32:49 +08:00
// Copyright (c) 2017 Duo Security, Inc. All rights reserved.
// Under BSD 3-Clause "New" or "Revised" License
// https://github.com/duo-labs/py_webauthn/
function b64enc(buf) {
return base64js
.fromByteArray(buf)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
}
function b64RawEnc(buf) {
return base64js.fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_");
}
function hexEncode(buf) {
return Array.from(buf)
.map(function (x) {
return ("0" + x.toString(16)).substr(-2);
})
.join("");
}
const transformCredentialRequestOptions = (
credentialRequestOptionsFromServer
) => {
let { challenge, allowCredentials } = credentialRequestOptionsFromServer;
challenge = Uint8Array.from(
atob(challenge.replace(/\_/g, "/").replace(/\-/g, "+")),
(c) => c.charCodeAt(0)
);
allowCredentials = allowCredentials.map((credentialDescriptor) => {
let { id } = credentialDescriptor;
id = id.replace(/\_/g, "/").replace(/\-/g, "+");
id = Uint8Array.from(atob(id), (c) => c.charCodeAt(0));
return Object.assign({}, credentialDescriptor, { id });
});
const transformedCredentialRequestOptions = Object.assign(
{},
credentialRequestOptionsFromServer,
{ challenge, allowCredentials }
);
return transformedCredentialRequestOptions;
};
/**
* Transforms items in the credentialCreateOptions generated on the server
* into byte arrays expected by the navigator.credentials.create() call
* @param {Object} credentialCreateOptionsFromServer
*/
const transformCredentialCreateOptions = (
credentialCreateOptionsFromServer
) => {
2020-05-18 13:05:37 +08:00
let { challenge, user, excludeCredentials } = credentialCreateOptionsFromServer;
2020-05-05 16:32:49 +08:00
user.id = Uint8Array.from(
atob(
credentialCreateOptionsFromServer.user.id
.replace(/\_/g, "/")
.replace(/\-/g, "+")
),
(c) => c.charCodeAt(0)
);
challenge = Uint8Array.from(
atob(
credentialCreateOptionsFromServer.challenge
.replace(/\_/g, "/")
.replace(/\-/g, "+")
),
(c) => c.charCodeAt(0)
);
2020-05-18 13:05:37 +08:00
excludeCredentials = excludeCredentials.map((credentialDescriptor) => {
let { id } = credentialDescriptor;
id = id.replace(/\_/g, "/").replace(/\-/g, "+");
id = Uint8Array.from(atob(id), (c) => c.charCodeAt(0));
return Object.assign({}, credentialDescriptor, { id });
});
2020-05-05 16:32:49 +08:00
const transformedCredentialCreateOptions = Object.assign(
{},
credentialCreateOptionsFromServer,
2020-05-18 13:05:37 +08:00
{ challenge, user, excludeCredentials }
2020-05-05 16:32:49 +08:00
);
return transformedCredentialCreateOptions;
};
/**
* Transforms the binary data in the credential into base64 strings
* for posting to the server.
* @param {PublicKeyCredential} newAssertion
*/
const transformNewAssertionForServer = (newAssertion) => {
const attObj = new Uint8Array(newAssertion.response.attestationObject);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const registrationClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: b64enc(rawId),
type: newAssertion.type,
attObj: b64enc(attObj),
clientData: b64enc(clientDataJSON),
registrationClientExtensions: JSON.stringify(registrationClientExtensions),
};
};
/**
* Encodes the binary data in the assertion into strings for posting to the server.
* @param {PublicKeyCredential} newAssertion
*/
const transformAssertionForServer = (newAssertion) => {
const authData = new Uint8Array(newAssertion.response.authenticatorData);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const sig = new Uint8Array(newAssertion.response.signature);
const assertionClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: b64enc(rawId),
type: newAssertion.type,
authData: b64RawEnc(authData),
clientData: b64RawEnc(clientDataJSON),
signature: hexEncode(sig),
assertionClientExtensions: JSON.stringify(assertionClientExtensions),
};
};