mirror of
https://github.com/dani-garcia/u2f-rs.git
synced 2026-11-03 18:46:46 +09:00
125 lines
4.8 KiB
HTML
125 lines
4.8 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<script type="text/javascript" src="https://demo.yubico.com/js/u2f-api.js"></script>
|
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/2.1.2/sweetalert.min.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Rust U2F App test</h1>
|
|
<input type="button" value="Register a 2FA key" onClick="register()">
|
|
<p/>
|
|
<input type="button" value="Authenticate" onClick="authenticate()">
|
|
|
|
<script>
|
|
|
|
/* u2f.ErrorCodes is undefined in Firefox v64 default to zero if it is undefined, same as in the u2f spec */
|
|
const U2F_ERROR_CODES_OK = typeof u2f.ErrorCodes === 'undefined' ? 0 : u2f.ErrorCodes['OK'];
|
|
|
|
/* Reject promise if u2f error, translates the error code to an `Error` */
|
|
const rejectU2fError = (resolve, reject, response) => {
|
|
if (typeof response.errorCode === 'undefined' || response.errorCode === U2F_ERROR_CODES_OK) {
|
|
resolve(response);
|
|
} else {
|
|
reject(parseError(response.errorCode));
|
|
}
|
|
}
|
|
|
|
/* Promisify u2f.register usually taking callback function */
|
|
const u2fRegisterAsync = (appId, registerRequests, registeredKeys, opt_timeoutSeconds) =>
|
|
new Promise((resolve, reject) => u2f.register(appId, registerRequests, registeredKeys, response => rejectU2fError(resolve, reject, response), opt_timeoutSeconds));
|
|
|
|
/* Promisify u2f.sign usually taking callback function */
|
|
const u2fSignAsync = (appId, challenge, registeredKeys, opt_timeoutSeconds) =>
|
|
new Promise((resolve, reject) => u2f.sign(appId, challenge, registeredKeys, response => rejectU2fError(resolve, reject, response), opt_timeoutSeconds));
|
|
|
|
/* Get a registration request from the server
|
|
* Register the key
|
|
*/
|
|
async function register() {
|
|
try {
|
|
const req = await fetch('/api/register_request').then(response => response.json());
|
|
|
|
const response = await Promise.race([
|
|
showNotification("Registration"),
|
|
u2fRegisterAsync(req.appId, req.registerRequests, req.registeredKeys, 30)
|
|
]);
|
|
|
|
// null when dialog message is cancelled
|
|
if (response) {
|
|
console.log(response);
|
|
|
|
// Send the results back to server
|
|
// Check if it was successful
|
|
await postJSON('/api/register_response', response);
|
|
swal("Registered!", "Successful registered", "success");
|
|
}
|
|
}
|
|
catch(e) {
|
|
swal("Registration failed", e.message, "error");
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/* Get an authentication request from the server
|
|
* Sign it with the key
|
|
*/
|
|
async function authenticate() {
|
|
try {
|
|
const req = await fetch('/api/sign_request').then(req => req.json());
|
|
|
|
const response = await Promise.race([
|
|
showNotification("Authentication"),
|
|
u2fSignAsync(req.appId, req.challenge, req.registeredKeys, 30)
|
|
]);
|
|
|
|
// null when dialog message is cancelled
|
|
if (response) {
|
|
console.log(response);
|
|
// Verify the results on the server
|
|
await postJSON('/api/sign_response', response);
|
|
swal("Authenticated!", "Successfully authenticated", "success");
|
|
}
|
|
}
|
|
catch(e) {
|
|
swal("Authentication failed", e.message, "error");
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
async function postJSON(url, data){
|
|
const response = await fetch(url, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } });
|
|
if (response.ok) {
|
|
return response.json();
|
|
}
|
|
throw new Error(response.statusText);
|
|
};
|
|
|
|
function parseError(errorCode) {
|
|
var message = "Unknown error: " + errorCode;
|
|
// In Firefox v64 u2f.ErrorCodes is undefined
|
|
if (typeof u2f.ErrorCodes !== 'undefined') {
|
|
for (name in u2f.ErrorCodes) {
|
|
if (u2f.ErrorCodes[name] === errorCode) {
|
|
message = name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return new Error(message);
|
|
}
|
|
|
|
function showNotification(action) {
|
|
return swal({
|
|
title: action,
|
|
text: "Press your key (Yubico) to proceed. Timeout in 30s.",
|
|
buttons: {
|
|
cancel: true,
|
|
confirm: false
|
|
},
|
|
});
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html> |