fido2-server
Version:
A FIDO 2.0 / W3C WebAuthn server
160 lines (144 loc) • 4.42 kB
JavaScript
;
var webauthn = (function () {
const webauthnDB = (function() {
const WEBAUTHN_DB_VERSION = 1;
const WEBAUTHN_DB_NAME = "_webauthn";
const WEBAUTHN_ID_TABLE = "identities";
var db = null;
var initPromise = null;
function initDB() {
return new Promise(function(resolve,reject) {
var req = indexedDB.open(WEBAUTHN_DB_NAME,WEBAUTHN_DB_VERSION);
req.onupgradeneeded = function() {
// new database - set up store
db = req.result;
var store = db.createObjectStore(WEBAUTHN_ID_TABLE, { keyPath: "id"});
};
req.onsuccess = function() {
db = req.result;
resolve();
};
req.onerror = function(e) {
reject(e);
};
});
}
function store(id,data) {
if(!initPromise) { initPromise = initDB(); }
return initPromise.then(function() { doStore(id,data) });
}
function doStore(id,data) {
if(!db) throw "DB not initialised";
return new Promise(function(resolve,reject) {
var tx = db.transaction(WEBAUTHN_ID_TABLE,"readwrite");
var store = tx.objectStore(WEBAUTHN_ID_TABLE);
store.put({id:id,data:data});
tx.oncomplete = function() {
resolve();
}
tx.onerror = function(e) {
reject(e);
};
});
}
function getAll() {
if(!initPromise) { initPromise = initDB(); }
return initPromise.then(doGetAll);
}
function doGetAll() {
if(!db) throw "DB not initialised";
return new Promise(function(resolve,reject) {
var tx = db.transaction(WEBAUTHN_ID_TABLE,"readonly");
var store = tx.objectStore(WEBAUTHN_ID_TABLE);
var req = store.openCursor();
var res = [];
req.onsuccess = function() {
var cur = req.result;
if(cur) {
res.push({id:cur.value.id,data:cur.value.data});
cur.continue();
} else {
resolve(res);
}
}
req.onerror = function(e) {
reject(e);
};
});
}
return {
store: store,
getAll: getAll
};
}());
function makeCredential(accountInfo, cryptoParams, attestChallenge, timeout, blacklist, ext) {
var acct = {rpDisplayName: accountInfo.rpDisplayName, userDisplayName: accountInfo.displayName};
var params = [];
var i;
if (accountInfo.name) { acct.accountName = accountInfo.name; }
if (accountInfo.id) { acct.userId = accountInfo.id; }
if (accountInfo.imageUri) { acct.accountImageUri = accountInfo.imageUri; }
for ( i = 0; i < cryptoParams.length; i++ ) {
if ( cryptoParams[i].type === 'ScopedCred' ) {
params[i] = { type: 'FIDO_2_0', algorithm: cryptoParams[i].algorithm };
} else {
params[i] = cryptoParams[i];
}
}
return msCredentials.makeCredential(acct, params, attestChallenge).then(function (cred) {
if (cred.type === "FIDO_2_0") {
var result = Object.freeze({
credential: {type: "ScopedCred", id: cred.id},
publicKey: JSON.parse(cred.publicKey),
attestation: cred.attestation
});
return webauthnDB.store(result.credential.id,accountInfo).then(function() { return result; });
} else {
return cred;
}
});
}
function getCredList(allowlist) {
var credList = [];
if(allowlist) {
return new Promise(function(resolve,reject) {
allowlist.forEach(function(item) {
if (item.type === 'ScopedCred' ) {
credList.push({ type: 'FIDO_2_0', id: item.id });
} else {
credList.push(item);
}
});
resolve(credList);
});
} else {
return webauthnDB.getAll().then(function(list) {
list.forEach(item => credList.push({ type: 'FIDO_2_0', id: item.id }));
return credList;
});
}
}
function getAssertion(challenge, timeout, allowlist, ext) {
return getCredList(allowlist).then(function(credList) {
var filter = { accept: credList };
var sigParams = undefined;
if (ext && ext["webauthn.txauth.simple"]) { sigParams = { userPrompt: ext["webauthn.txauth.simple"] }; }
return msCredentials.getAssertion(challenge, filter, sigParams).then(function (sig) {
if (sig.type === "FIDO_2_0"){
return Object.freeze({
credential: {type: "ScopedCred", id: sig.id},
clientData: sig.signature.clientData,
authenticatorData: sig.signature.authnrData,
signature: sig.signature.signature
});
} else {
return sig;
}
});
});
}
return {
makeCredential: makeCredential,
getAssertion: getAssertion
};
}());