mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-01-11 14:30:48 +01:00
decoding webauthn
This commit is contained in:
@@ -221,6 +221,7 @@
|
||||
};
|
||||
|
||||
WebAuthn.base64ToBuffer = base64ToBuffer;
|
||||
WebAuthn.bufferToBase64 = bufferToBase64;
|
||||
|
||||
return WebAuthn;
|
||||
}));
|
||||
@@ -239,6 +239,8 @@
|
||||
This is a base64 encoded binary representation of an attestation statement. The attestation statement is produced by the authenticator to prove to the relying party (e.g., a website) that a new public key credential has been created in the authenticator. It typically contains details about the authenticator, a freshly generated public key for the user, some metadata, and a signature from the authenticator. It is <a href="https://cbor.io/">CBOR</a> encoded.
|
||||
</p>
|
||||
<div class="code" id="navigator-attestationObject" style="height: 150px; overflow-y: scroll;"></div>
|
||||
<p class="button-label">The authData is <a href="https://www.w3.org/TR/webauthn-2/#sctn-attested-credential-data">binary encoded</a> and contain the actual public key, but also more flags and info about the authentication:</p>
|
||||
<div class="code" id="navigator-authData"></div>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p class="emphasis"><b>clientDataJSON</b></p>
|
||||
@@ -345,6 +347,8 @@
|
||||
<p>
|
||||
This contains information about the authentication event. It typically includes the hash of the <b>clientDataJSON</b>, a sign count (to protect against clone attacks), and other data relevant to the authentication process.
|
||||
</p>
|
||||
<p class="button-label">It is <a href="https://www.w3.org/TR/webauthn-2/#sctn-attested-credential-data">binary encoded</a> and this time does not contain the public key:</p>
|
||||
<div class="code" id="navigator-authenticatorData"></div>
|
||||
</li>
|
||||
<li class="collection-item">
|
||||
<p class="emphasis"><b>signature</b></p>
|
||||
@@ -418,6 +422,63 @@
|
||||
}
|
||||
}
|
||||
|
||||
function readHexString(view, start, len){
|
||||
const hash = new Uint8Array(len);
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
hash[i] = view.getUint8(i+start);
|
||||
}
|
||||
|
||||
return Array.from(hash).map(byte => {
|
||||
return ('0' + byte.toString(16)).slice(-2); // Ensure two-digit hex representation
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function parseCredentialPubKey(array) {
|
||||
console.log(array)
|
||||
let view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
||||
let credentialIdLength = view.getUint16(16, false);
|
||||
return {
|
||||
"aaguid": readHexString(view, 0, 16),
|
||||
"credentialIdLength": credentialIdLength,
|
||||
"credentialId": WebAuthn.bufferToBase64(array.slice(18, credentialIdLength).buffer),
|
||||
"credentialPublicKey": WebAuthn.bufferToBase64(array.slice(18+credentialIdLength).buffer)
|
||||
}
|
||||
}
|
||||
|
||||
function parseAuthenticatorData(array) {
|
||||
try {
|
||||
console.log(array)
|
||||
let view = new DataView(array.buffer, array.byteOffset, array.byteLength);
|
||||
let flags = view.getInt8(32);
|
||||
const hashHex = readHexString(view, 0, 32);
|
||||
|
||||
const result = {
|
||||
"rpIdHash": hashHex,
|
||||
"flags": {
|
||||
"userPresent": !!(flags & 1),
|
||||
"userVerified": !!(flags & (1 << 2)),
|
||||
"attestedCredentialData": !!(flags & (1 << 6)),
|
||||
"extensionDataIncluded": !!(flags & (1 << 7))
|
||||
},
|
||||
"signCount": view.getUint32(33, false),
|
||||
}
|
||||
|
||||
try {
|
||||
if (result.flags.attestedCredentialData) {
|
||||
result['credentialPubKey'] = parseCredentialPubKey(array.slice(37));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
return "Unable to parse: " + e;
|
||||
}
|
||||
}
|
||||
|
||||
function tracer(stage, params) {
|
||||
console.log(stage, params)
|
||||
|
||||
@@ -498,7 +559,10 @@
|
||||
$("#navigator-attestation").showInViewport();
|
||||
$("#navigator-attestation-body").html(JSON.stringify(response, null, 2));
|
||||
$("#navigator-attestation-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2));
|
||||
$("#navigator-attestationObject").html(JSON.stringify(CBOR.decode(WebAuthn.base64ToBuffer(response.response.attestationObject)), null, 2));
|
||||
let attestationObject = CBOR.decode(WebAuthn.base64ToBuffer(response.response.attestationObject));
|
||||
let authData = parseAuthenticatorData(attestationObject.authData);
|
||||
$("#navigator-attestationObject").html(JSON.stringify(attestationObject, null, 2));
|
||||
$("#navigator-authData").html(JSON.stringify(authData, null, 2));
|
||||
return continueButton("#navigator-attestation", response);
|
||||
}
|
||||
|
||||
@@ -512,6 +576,9 @@
|
||||
$("#navigator-assertion").showInViewport();
|
||||
$("#navigator-assertion-body").html(JSON.stringify(response, null, 2));
|
||||
$("#navigator-assertion-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2));
|
||||
let authenticatorData = WebAuthn.base64ToBuffer(response.response.authenticatorData);
|
||||
let authData = parseAuthenticatorData(new Uint8Array(authenticatorData));
|
||||
$("#navigator-authenticatorData").html(JSON.stringify(authData, null, 2));
|
||||
return continueButton("#navigator-assertion", response);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user