You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.4 KiB

import { base64url } from "rfc4648";
export async function registerByWebAuthn(input) {
// Check if WebAuthn is supported by this browser
if (!window.PublicKeyCredential) {
returnFailure(input.errmsg);
return;
}
const publicKey = {
challenge: base64url.parse(input.challenge, {loose: true}),
rp: {id: input.rpId, name: input.rpEntityName},
user: {
id: base64url.parse(input.userid, {loose: true}),
name: input.username,
displayName: input.username
},
pubKeyCredParams: getPubKeyCredParams(input.signatureAlgorithms),
};
if (input.attestationConveyancePreference !== 'not specified') {
publicKey.attestation = input.attestationConveyancePreference;
}
const authenticatorSelection = {};
let isAuthenticatorSelectionSpecified = false;
if (input.authenticatorAttachment !== 'not specified') {
authenticatorSelection.authenticatorAttachment = input.authenticatorAttachment;
isAuthenticatorSelectionSpecified = true;
}
if (input.requireResidentKey !== 'not specified') {
if (input.requireResidentKey === 'Yes') {
authenticatorSelection.requireResidentKey = true;
} else {
authenticatorSelection.requireResidentKey = false;
}
isAuthenticatorSelectionSpecified = true;
}
if (input.userVerificationRequirement !== 'not specified') {
authenticatorSelection.userVerification = input.userVerificationRequirement;
isAuthenticatorSelectionSpecified = true;
}
if (isAuthenticatorSelectionSpecified) {
publicKey.authenticatorSelection = authenticatorSelection;
}
if (input.createTimeout !== 0) {
publicKey.timeout = input.createTimeout * 1000;
}
const excludeCredentials = getExcludeCredentials(input.excludeCredentialIds);
if (excludeCredentials.length > 0) {
publicKey.excludeCredentials = excludeCredentials;
}
try {
const result = await doRegister(publicKey);
returnSuccess(result, input.initLabel, input.initLabelPrompt);
} catch (error) {
returnFailure(error);
}
}
function doRegister(publicKey) {
return navigator.credentials.create({publicKey});
}
function getPubKeyCredParams(signatureAlgorithmsList) {
const pubKeyCredParams = [];
if (signatureAlgorithmsList.length === 0) {
pubKeyCredParams.push({type: "public-key", alg: -7});
return pubKeyCredParams;
}
for (const entry of signatureAlgorithmsList) {
pubKeyCredParams.push({
type: "public-key",
alg: entry
});
}
return pubKeyCredParams;
}
function getExcludeCredentials(excludeCredentialIds) {
const excludeCredentials = [];
if (excludeCredentialIds === "") {
return excludeCredentials;
}
for (const entry of excludeCredentialIds.split(',')) {
excludeCredentials.push({
type: "public-key",
id: base64url.parse(entry, {loose: true})
});
}
return excludeCredentials;
}
function getTransportsAsString(transportsList) {
if (!Array.isArray(transportsList)) {
return "";
}
return transportsList.join();
}
function returnSuccess(result, initLabel, initLabelPrompt) {
document.getElementById("clientDataJSON").value = base64url.stringify(new Uint8Array(result.response.clientDataJSON), {pad: false});
document.getElementById("attestationObject").value = base64url.stringify(new Uint8Array(result.response.attestationObject), {pad: false});
document.getElementById("publicKeyCredentialId").value = base64url.stringify(new Uint8Array(result.rawId), {pad: false});
if (typeof result.response.getTransports === "function") {
const transports = result.response.getTransports();
if (transports) {
document.getElementById("transports").value = getTransportsAsString(transports);
}
} else {
console.log("Your browser is not able to recognize supported transport media for the authenticator.");
}
let labelResult = window.prompt(initLabelPrompt, initLabel);
if (labelResult === null) {
labelResult = initLabel;
}
document.getElementById("authenticatorLabel").value = labelResult;
document.getElementById("register").submit();
}
function returnFailure(err) {
document.getElementById("error").value = err;
document.getElementById("register").submit();
}