-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
index.html
104 lines (102 loc) · 4.51 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<html>
<head>
<script language="javascript">
function arrayBufferToBase64(a) {
return btoa(String.fromCharCode(...new Uint8Array(a)));
}
function base64ToArrayBuffer(b) {
return Uint8Array.from(atob(b), c => c.charCodeAt(0));
}
function JSONRequest(route, body) {
return new Request(route, {method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(body)});
}
// See https://www.w3.org/TR/webauthn/#registering-a-new-credential
function createCreds() {
var email = document.webauthn_input.email.value;
fetch(JSONRequest("getCredentialCreateOptions", {email}))
.then(function(res) {
return res.json()
}).then(function(options) {
options.challenge = base64ToArrayBuffer(options.challenge);
options.user.id = new TextEncoder().encode(options.user.name);
console.log("Credential create options:");
console.dir(options);
navigator.credentials.create({publicKey: options}).then(function (newCredentialInfo) {
console.log("Created credential:");
console.dir(newCredentialInfo);
// Send new credential info to server for verification and registration
var dataForServer = {};
["attestationObject", "clientDataJSON"].map(f => {
dataForServer[f] = arrayBufferToBase64(newCredentialInfo.response[f]);
});
dataForServer.email = btoa(email);
fetch(JSONRequest("registerCredential", dataForServer)).then(function(res) {
console.log("Response from registerCredential:");
console.dir(res);
return res.blob();
}).then(function(body) {
var reader = new FileReader();
reader.onload = function() {
document.getElementById("result").innerHTML = reader.result;
}
reader.readAsText(body);
});
}).catch(function (err) {
console.log("Error in navigator.credentials.create: " + err);
console.dir(err); // No acceptable authenticator or user refused consent
});
});
}
// See https://www.w3.org/TR/webauthn/#verifying-assertion
function login() {
var email = document.webauthn_input.email.value;
fetch(JSONRequest("getCredentialGetOptions", {email}))
.then(function(res) {
return res.json()
}).then(function(options) {
options.challenge = base64ToArrayBuffer(options.challenge);
for (let cred of options.allowCredentials) {
cred.id = Uint8Array.from(atob(cred.id), c => c.charCodeAt(0));
}
console.log("Credential get options:");
console.dir(options);
navigator.credentials.get({publicKey: options}).then(function (assertion) {
// Send assertion to server for verification
console.log("Got assertion:");
console.dir(assertion);
var dataForServer = {};
["authenticatorData", "clientDataJSON", "signature", "userHandle", "rawId"].map(f => {
dataForServer[f] = arrayBufferToBase64(assertion.response[f]);
});
dataForServer.email = btoa(email);
fetch(JSONRequest("verifyAssertion", dataForServer)).then(function(res) {
console.log("Response from verifyAssertion:");
console.dir(res);
return res.blob();
}).then(function(body) {
var reader = new FileReader();
reader.onload = function() {
document.getElementById("result").innerHTML = reader.result;
}
reader.readAsText(body);
});
}).catch(function (err) {
console.log("Error in navigator.credentials.get: " + err);
console.dir(err); // No acceptable credential or user refused consent
});
});
}
</script>
</head>
<body>
<a href="https://github.com/pyauth/pywarp">PyWARP</a> WebAuthn demo
<form name="webauthn_input" onsubmit="event.preventDefault()">
Email: <input type="text" name="email">
<button onclick="createCreds()">Create account</button>
<button onclick="login()">Log in</button>
</form>
<div id="result"></div>
</body>
</html>