1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00
This commit is contained in:
Oscar Hinton
2021-03-16 17:44:31 +01:00
committed by GitHub
parent 35ecbcc11a
commit 1ea8762eeb
22 changed files with 516 additions and 141 deletions

122
src/connectors/webauthn.ts Normal file
View File

@@ -0,0 +1,122 @@
import { getQsParam } from './common';
import { b64Decode, buildDataString } from './common-webauthn';
// tslint:disable-next-line
require('./webauthn.scss');
document.addEventListener('DOMContentLoaded', () => {
init();
const text = getQsParam('btnText');
if (text) {
document.getElementById('webauthn-button').innerText = decodeURI(text);
}
});
let parentUrl: string = null;
let parentOrigin: string = null;
let stopWebAuthn = false;
let sentSuccess = false;
let obj: any = null;
function init() {
start();
onMessage();
info('ready');
}
function start() {
sentSuccess = false;
if (!('credentials' in navigator)) {
error('WebAuthn is not supported in this browser.');
return;
}
const data = getQsParam('data');
if (!data) {
error('No data.');
return;
}
parentUrl = getQsParam('parent');
if (!parentUrl) {
error('No parent.');
return;
} else {
parentUrl = decodeURIComponent(parentUrl);
parentOrigin = new URL(parentUrl).origin;
}
try {
const jsonString = b64Decode(data);
obj = JSON.parse(jsonString);
}
catch (e) {
error('Cannot parse data.');
return;
}
const challenge = obj.challenge.replace(/-/g, '+').replace(/_/g, '/');
obj.challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0));
// fix escaping. Change this to coerce
obj.allowCredentials.forEach((listItem: any) => {
const fixedId = listItem.id.replace(/\_/g, '/').replace(/\-/g, '+');
listItem.id = Uint8Array.from(atob(fixedId), c => c.charCodeAt(0));
});
stopWebAuthn = false;
if (navigator.userAgent.indexOf(' Safari/') !== -1 && navigator.userAgent.indexOf('Chrome') === -1) {
// TODO: Hide image, show button
} else {
executeWebAuthn();
}
}
function executeWebAuthn() {
if (stopWebAuthn) {
return;
}
navigator.credentials.get({ publicKey: obj })
.then(success)
.catch(err => error('WebAuth Error: ' + err));
}
(window as any).executeWebAuthn = executeWebAuthn;
function onMessage() {
window.addEventListener('message', event => {
if (!event.origin || event.origin === '' || event.origin !== parentOrigin) {
return;
}
if (event.data === 'stop') {
stopWebAuthn = true;
}
else if (event.data === 'start' && stopWebAuthn) {
start();
}
}, false);
}
function error(message: string) {
parent.postMessage('error|' + message, parentUrl);
}
function success(assertedCredential: PublicKeyCredential) {
if (sentSuccess) {
return;
}
const dataString = buildDataString(assertedCredential);
parent.postMessage('success|' + dataString, parentUrl);
sentSuccess = true;
}
function info(message: string) {
parent.postMessage('info|' + message, parentUrl);
}