/*! meta-client/modules/webauthn */
/*jslint
browser, long
*/
/*global
AbortController
*/
/**
* webauthn module.
*
* @module meta-client/modules/webauthn
*/
import buffers from "util-web/modules/buffers";
import Logger from "js-logger";
const LOG = Logger.get("meta-client/webauthn");
const authAbortController = new AbortController();
const authAbortSignal = authAbortController.signal;
const webauthn = {};
authAbortSignal.onabort = () => LOG.warn("onabort");
webauthn.decodePublicKeyCredentialCreationOptions = function (request) {
const options = Object.assign(request, {
challenge: buffers.base64UrlToBuffer(request.challenge),
excludeCredentials: request.excludeCredentials.map(function (credential) {
return Object.assign(credential, {id: buffers.base64UrlToBuffer(credential.id)});
}),
user: Object.assign(request.user, {id: buffers.base64UrlToBuffer(request.user.id)})
});
LOG.debug("decodePublicKeyCredentialCreationOptions", options);
return options;
};
webauthn.encodeCreationResponse = function (response) {
LOG.debug("encodeCreationResponse", response);
return {
clientExtensionResults: {},
id: response.id,
response: {
attestationObject: buffers.bufferToBase64Url(response.response.attestationObject),
clientDataJSON: buffers.bufferToBase64Url(response.response.clientDataJSON)
},
type: response.type
};
};
webauthn.createCredential = function (options) {
const publicKey = webauthn.decodePublicKeyCredentialCreationOptions(options);
LOG.debug("createCredential", publicKey);
return navigator.credentials.create({publicKey, signal: authAbortSignal}).then((response) => webauthn.encodeCreationResponse(response));
};
webauthn.decodePublicKeyCredentialRequestOptions = function (request) {
const options = Object.assign(request, {
allowCredentials: request.allowCredentials && request.allowCredentials.map(function (credential) {
const mapped = Object.assign(credential, {id: buffers.base64UrlToBuffer(credential.id)});
delete mapped.transports;
return mapped;
}),
challenge: buffers.base64UrlToBuffer(request.challenge),
extensions: {}
});
LOG.debug("decodePublicKeyCredentialRequestOptions", options);
return options;
};
webauthn.encodeAssertionResponse = function (response) {
LOG.debug("encodeAssertionResponse", response);
return {
clientExtensionResults: {},
id: response.id,
response: {
authenticatorData: buffers.bufferToBase64Url(response.response.authenticatorData),
clientDataJSON: buffers.bufferToBase64Url(response.response.clientDataJSON),
signature: buffers.bufferToBase64Url(response.response.signature),
userHandle: response.response.userHandle && buffers.bufferToBase64Url(response.response.userHandle)
},
type: response.type
};
};
webauthn.getAssertion = function (options) {
const publicKey = webauthn.decodePublicKeyCredentialRequestOptions(options.publicKeyCredentialRequestOptions);
LOG.debug("getAssertion", publicKey);
return navigator.credentials.get({publicKey, signal: authAbortSignal}).then((response) => webauthn.encodeAssertionResponse(response));
};
webauthn.abortAssertion = function () {
LOG.debug("abortAssertion");
authAbortController.abort();
};
export default Object.freeze(webauthn);