141 lines
4.4 KiB
JavaScript
141 lines
4.4 KiB
JavaScript
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();
|
|
}
|