-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcredentials.js
More file actions
118 lines (105 loc) · 3.83 KB
/
Copy pathcredentials.js
File metadata and controls
118 lines (105 loc) · 3.83 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// simple demonstration of the WebAuthn API with a backend RP server
// See README for instructions to run the backend
// run in a recent browser like Chrome over https or http://localhost
// NOTE: in other browsers, you may need some polyfills:
// https://github.com/MasterKale/webauthn-polyfills
// the webauthn API base URI
const api = "http://localhost:8080/v1";
// See http://localhost:8080/swagger-ui/index.html
// convert an ArrayBuffer to a hexstring
function btoh(bin) {
bytes = new Uint8Array(bin);
return [...bytes].map(b => b.toString(16).padStart(2, "0")).join("");
}
// post request data as JSON to endpoint and return parsed JSON result
async function post(uri, request) {
console.log(">> send >>", request);
params = {
method: "POST",
body: JSON.stringify(request),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
};
httpResponse = await fetch(uri, params);
response = await httpResponse.json();
console.log("<< recv <<", response);
if( httpResponse.status != 200 ) {
throw new Error("backend error");
}
return response;
}
/// REGISTER ///
// retrieve challenge and other options for credentials.get
async function createOptions() {
body = {
userName: "john",
displayName: "John Doe",
authenticatorSelection: {
residentKey: "required",
}
};
json = await post(`${api}/attestation/options`, body);
json.publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(json.publicKey);
return json;
}
// post response with attestation to backend for registration
async function postAttestation(requestId, attestation) {
body = {
requestId: requestId,
makeCredentialResult: attestation
};
json = await post(`${api}/attestation/result`, body);
return json;
}
// create a credential
async function register() {
try {
options = await createOptions();
requestId = options.requestId;
attestation = await navigator.credentials.create(options);
console.log(attestation);
result = await postAttestation(requestId, attestation);
if( result.status == "created" ) {
document.getElementById("message").innerHTML +=
`<br/>Created credential with ID <span class="code">${ btoh( (attestation.rawId) )}</span>` +
` for user ID <span class="code">${ btoh((options.publicKey.user.id)) }</span>`;
}
} catch (e) {
document.getElementById("message").innerHTML += `<br/><b>Registration failed</b>: ${ e.message }`;
}
}
/// AUTHENTICATE ///
// retrieve challenge and other options for credentials.get
async function getOptions() {
body = {
publicKey: {}
};
json = await post(`${api}/assertion/options`, body);
json.publicKey = PublicKeyCredential.parseRequestOptionsFromJSON(json.publicKey);
return json;
}
// post response with assertion to backend for validation
async function postAssertion(requestId, assertion) {
body = {
requestId: requestId,
assertionResult: assertion
};
json = await post(`${api}/assertion/result`, body);
return json;
}
// get an assertion
async function authenticate() {
try {
options = await getOptions();
requestId = options.requestId;
assertion = await navigator.credentials.get(options);
console.log(assertion);
result = await postAssertion(requestId, assertion);
document.getElementById("message").innerHTML +=
`<br/>Obtained assertion for credential ID <span class="code">${ btoh((assertion.rawId)) }</span>` +
` and user ID <span class="code">${ btoh((assertion.response.userHandle)) }</span>`;
} catch (e) {
document.getElementById("message").innerHTML += `<br/><b>Authentication failed</b>: ${ e.message }`;
}
}