mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-03-25 10:32:26 +01:00
cbor decoding of attestationObject
This commit is contained in:
428
src/main/resources/META-INF/resources/js/cbor.js
Normal file
428
src/main/resources/META-INF/resources/js/cbor.js
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Patrick Gansterer <paroga@paroga.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function (global, undefined) {
|
||||||
|
"use strict";
|
||||||
|
var POW_2_24 = Math.pow(2, -24),
|
||||||
|
POW_2_32 = Math.pow(2, 32),
|
||||||
|
POW_2_53 = Math.pow(2, 53);
|
||||||
|
|
||||||
|
function encode(value) {
|
||||||
|
var data = new ArrayBuffer(256);
|
||||||
|
var dataView = new DataView(data);
|
||||||
|
var lastLength;
|
||||||
|
var offset = 0;
|
||||||
|
|
||||||
|
function ensureSpace(length) {
|
||||||
|
var newByteLength = data.byteLength;
|
||||||
|
var requiredLength = offset + length;
|
||||||
|
while (newByteLength < requiredLength)
|
||||||
|
newByteLength *= 2;
|
||||||
|
if (newByteLength !== data.byteLength) {
|
||||||
|
var oldDataView = dataView;
|
||||||
|
data = new ArrayBuffer(newByteLength);
|
||||||
|
dataView = new DataView(data);
|
||||||
|
var uint32count = (offset + 3) >> 2;
|
||||||
|
for (var i = 0; i < uint32count; ++i)
|
||||||
|
dataView.setUint32(i * 4, oldDataView.getUint32(i * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
lastLength = length;
|
||||||
|
return dataView;
|
||||||
|
}
|
||||||
|
|
||||||
|
function write() {
|
||||||
|
offset += lastLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeFloat64(value) {
|
||||||
|
write(ensureSpace(8).setFloat64(offset, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUint8(value) {
|
||||||
|
write(ensureSpace(1).setUint8(offset, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUint8Array(value) {
|
||||||
|
var dataView = ensureSpace(value.length);
|
||||||
|
for (var i = 0; i < value.length; ++i)
|
||||||
|
dataView.setUint8(offset + i, value[i]);
|
||||||
|
write();
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUint16(value) {
|
||||||
|
write(ensureSpace(2).setUint16(offset, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUint32(value) {
|
||||||
|
write(ensureSpace(4).setUint32(offset, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUint64(value) {
|
||||||
|
var low = value % POW_2_32;
|
||||||
|
var high = (value - low) / POW_2_32;
|
||||||
|
var dataView = ensureSpace(8);
|
||||||
|
dataView.setUint32(offset, high);
|
||||||
|
dataView.setUint32(offset + 4, low);
|
||||||
|
write();
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeTypeAndLength(type, length) {
|
||||||
|
if (length < 24) {
|
||||||
|
writeUint8(type << 5 | length);
|
||||||
|
} else if (length < 0x100) {
|
||||||
|
writeUint8(type << 5 | 24);
|
||||||
|
writeUint8(length);
|
||||||
|
} else if (length < 0x10000) {
|
||||||
|
writeUint8(type << 5 | 25);
|
||||||
|
writeUint16(length);
|
||||||
|
} else if (length < 0x100000000) {
|
||||||
|
writeUint8(type << 5 | 26);
|
||||||
|
writeUint32(length);
|
||||||
|
} else {
|
||||||
|
writeUint8(type << 5 | 27);
|
||||||
|
writeUint64(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeItem(value) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
if (value === false)
|
||||||
|
return writeUint8(0xf4);
|
||||||
|
if (value === true)
|
||||||
|
return writeUint8(0xf5);
|
||||||
|
if (value === null)
|
||||||
|
return writeUint8(0xf6);
|
||||||
|
if (value === undefined)
|
||||||
|
return writeUint8(0xf7);
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case "number":
|
||||||
|
if (Math.floor(value) === value) {
|
||||||
|
if (0 <= value && value <= POW_2_53)
|
||||||
|
return writeTypeAndLength(0, value);
|
||||||
|
if (-POW_2_53 <= value && value < 0)
|
||||||
|
return writeTypeAndLength(1, -(value + 1));
|
||||||
|
}
|
||||||
|
writeUint8(0xfb);
|
||||||
|
return writeFloat64(value);
|
||||||
|
|
||||||
|
case "string":
|
||||||
|
var utf8data = [];
|
||||||
|
for (i = 0; i < value.length; ++i) {
|
||||||
|
var charCode = value.charCodeAt(i);
|
||||||
|
if (charCode < 0x80) {
|
||||||
|
utf8data.push(charCode);
|
||||||
|
} else if (charCode < 0x800) {
|
||||||
|
utf8data.push(0xc0 | charCode >> 6);
|
||||||
|
utf8data.push(0x80 | charCode & 0x3f);
|
||||||
|
} else if (charCode < 0xd800) {
|
||||||
|
utf8data.push(0xe0 | charCode >> 12);
|
||||||
|
utf8data.push(0x80 | (charCode >> 6) & 0x3f);
|
||||||
|
utf8data.push(0x80 | charCode & 0x3f);
|
||||||
|
} else {
|
||||||
|
charCode = (charCode & 0x3ff) << 10;
|
||||||
|
charCode |= value.charCodeAt(++i) & 0x3ff;
|
||||||
|
charCode += 0x10000;
|
||||||
|
|
||||||
|
utf8data.push(0xf0 | charCode >> 18);
|
||||||
|
utf8data.push(0x80 | (charCode >> 12) & 0x3f);
|
||||||
|
utf8data.push(0x80 | (charCode >> 6) & 0x3f);
|
||||||
|
utf8data.push(0x80 | charCode & 0x3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeTypeAndLength(3, utf8data.length);
|
||||||
|
return writeUint8Array(utf8data);
|
||||||
|
|
||||||
|
default:
|
||||||
|
var length;
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
length = value.length;
|
||||||
|
writeTypeAndLength(4, length);
|
||||||
|
for (i = 0; i < length; ++i)
|
||||||
|
encodeItem(value[i]);
|
||||||
|
} else if (value instanceof Uint8Array) {
|
||||||
|
writeTypeAndLength(2, value.length);
|
||||||
|
writeUint8Array(value);
|
||||||
|
} else {
|
||||||
|
var keys = Object.keys(value);
|
||||||
|
length = keys.length;
|
||||||
|
writeTypeAndLength(5, length);
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
var key = keys[i];
|
||||||
|
encodeItem(key);
|
||||||
|
encodeItem(value[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeItem(value);
|
||||||
|
|
||||||
|
if ("slice" in data)
|
||||||
|
return data.slice(0, offset);
|
||||||
|
|
||||||
|
var ret = new ArrayBuffer(offset);
|
||||||
|
var retView = new DataView(ret);
|
||||||
|
for (var i = 0; i < offset; ++i)
|
||||||
|
retView.setUint8(i, dataView.getUint8(i));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decode(data, tagger, simpleValue) {
|
||||||
|
var dataView = new DataView(data);
|
||||||
|
var offset = 0;
|
||||||
|
|
||||||
|
if (typeof tagger !== "function")
|
||||||
|
tagger = function (value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
if (typeof simpleValue !== "function")
|
||||||
|
simpleValue = function () {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
function read(value, length) {
|
||||||
|
offset += length;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readArrayBuffer(length) {
|
||||||
|
return read(new Uint8Array(data, offset, length), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFloat16() {
|
||||||
|
var tempArrayBuffer = new ArrayBuffer(4);
|
||||||
|
var tempDataView = new DataView(tempArrayBuffer);
|
||||||
|
var value = readUint16();
|
||||||
|
|
||||||
|
var sign = value & 0x8000;
|
||||||
|
var exponent = value & 0x7c00;
|
||||||
|
var fraction = value & 0x03ff;
|
||||||
|
|
||||||
|
if (exponent === 0x7c00)
|
||||||
|
exponent = 0xff << 10;
|
||||||
|
else if (exponent !== 0)
|
||||||
|
exponent += (127 - 15) << 10;
|
||||||
|
else if (fraction !== 0)
|
||||||
|
return fraction * POW_2_24;
|
||||||
|
|
||||||
|
tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);
|
||||||
|
return tempDataView.getFloat32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFloat32() {
|
||||||
|
return read(dataView.getFloat32(offset), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readFloat64() {
|
||||||
|
return read(dataView.getFloat64(offset), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readUint8() {
|
||||||
|
return read(dataView.getUint8(offset), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readUint16() {
|
||||||
|
return read(dataView.getUint16(offset), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readUint32() {
|
||||||
|
return read(dataView.getUint32(offset), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readUint64() {
|
||||||
|
return readUint32() * POW_2_32 + readUint32();
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBreak() {
|
||||||
|
if (dataView.getUint8(offset) !== 0xff)
|
||||||
|
return false;
|
||||||
|
offset += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readLength(additionalInformation) {
|
||||||
|
if (additionalInformation < 24)
|
||||||
|
return additionalInformation;
|
||||||
|
if (additionalInformation === 24)
|
||||||
|
return readUint8();
|
||||||
|
if (additionalInformation === 25)
|
||||||
|
return readUint16();
|
||||||
|
if (additionalInformation === 26)
|
||||||
|
return readUint32();
|
||||||
|
if (additionalInformation === 27)
|
||||||
|
return readUint64();
|
||||||
|
if (additionalInformation === 31)
|
||||||
|
return -1;
|
||||||
|
throw "Invalid length encoding";
|
||||||
|
}
|
||||||
|
|
||||||
|
function readIndefiniteStringLength(majorType) {
|
||||||
|
var initialByte = readUint8();
|
||||||
|
if (initialByte === 0xff)
|
||||||
|
return -1;
|
||||||
|
var length = readLength(initialByte & 0x1f);
|
||||||
|
if (length < 0 || (initialByte >> 5) !== majorType)
|
||||||
|
throw "Invalid indefinite length element";
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendUtf16data(utf16data, length) {
|
||||||
|
for (var i = 0; i < length; ++i) {
|
||||||
|
var value = readUint8();
|
||||||
|
if (value & 0x80) {
|
||||||
|
if (value < 0xe0) {
|
||||||
|
value = (value & 0x1f) << 6
|
||||||
|
| (readUint8() & 0x3f);
|
||||||
|
length -= 1;
|
||||||
|
} else if (value < 0xf0) {
|
||||||
|
value = (value & 0x0f) << 12
|
||||||
|
| (readUint8() & 0x3f) << 6
|
||||||
|
| (readUint8() & 0x3f);
|
||||||
|
length -= 2;
|
||||||
|
} else {
|
||||||
|
value = (value & 0x0f) << 18
|
||||||
|
| (readUint8() & 0x3f) << 12
|
||||||
|
| (readUint8() & 0x3f) << 6
|
||||||
|
| (readUint8() & 0x3f);
|
||||||
|
length -= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0x10000) {
|
||||||
|
utf16data.push(value);
|
||||||
|
} else {
|
||||||
|
value -= 0x10000;
|
||||||
|
utf16data.push(0xd800 | (value >> 10));
|
||||||
|
utf16data.push(0xdc00 | (value & 0x3ff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeItem() {
|
||||||
|
var initialByte = readUint8();
|
||||||
|
var majorType = initialByte >> 5;
|
||||||
|
var additionalInformation = initialByte & 0x1f;
|
||||||
|
var i;
|
||||||
|
var length;
|
||||||
|
|
||||||
|
if (majorType === 7) {
|
||||||
|
switch (additionalInformation) {
|
||||||
|
case 25:
|
||||||
|
return readFloat16();
|
||||||
|
case 26:
|
||||||
|
return readFloat32();
|
||||||
|
case 27:
|
||||||
|
return readFloat64();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
length = readLength(additionalInformation);
|
||||||
|
if (length < 0 && (majorType < 2 || 6 < majorType))
|
||||||
|
throw "Invalid length";
|
||||||
|
|
||||||
|
switch (majorType) {
|
||||||
|
case 0:
|
||||||
|
return length;
|
||||||
|
case 1:
|
||||||
|
return -1 - length;
|
||||||
|
case 2:
|
||||||
|
if (length < 0) {
|
||||||
|
var elements = [];
|
||||||
|
var fullArrayLength = 0;
|
||||||
|
while ((length = readIndefiniteStringLength(majorType)) >= 0) {
|
||||||
|
fullArrayLength += length;
|
||||||
|
elements.push(readArrayBuffer(length));
|
||||||
|
}
|
||||||
|
var fullArray = new Uint8Array(fullArrayLength);
|
||||||
|
var fullArrayOffset = 0;
|
||||||
|
for (i = 0; i < elements.length; ++i) {
|
||||||
|
fullArray.set(elements[i], fullArrayOffset);
|
||||||
|
fullArrayOffset += elements[i].length;
|
||||||
|
}
|
||||||
|
return fullArray;
|
||||||
|
}
|
||||||
|
return readArrayBuffer(length);
|
||||||
|
case 3:
|
||||||
|
var utf16data = [];
|
||||||
|
if (length < 0) {
|
||||||
|
while ((length = readIndefiniteStringLength(majorType)) >= 0)
|
||||||
|
appendUtf16data(utf16data, length);
|
||||||
|
} else
|
||||||
|
appendUtf16data(utf16data, length);
|
||||||
|
return String.fromCharCode.apply(null, utf16data);
|
||||||
|
case 4:
|
||||||
|
var retArray;
|
||||||
|
if (length < 0) {
|
||||||
|
retArray = [];
|
||||||
|
while (!readBreak())
|
||||||
|
retArray.push(decodeItem());
|
||||||
|
} else {
|
||||||
|
retArray = new Array(length);
|
||||||
|
for (i = 0; i < length; ++i)
|
||||||
|
retArray[i] = decodeItem();
|
||||||
|
}
|
||||||
|
return retArray;
|
||||||
|
case 5:
|
||||||
|
var retObject = {};
|
||||||
|
for (i = 0; i < length || length < 0 && !readBreak(); ++i) {
|
||||||
|
var key = decodeItem();
|
||||||
|
retObject[key] = decodeItem();
|
||||||
|
}
|
||||||
|
return retObject;
|
||||||
|
case 6:
|
||||||
|
return tagger(decodeItem(), length);
|
||||||
|
case 7:
|
||||||
|
switch (length) {
|
||||||
|
case 20:
|
||||||
|
return false;
|
||||||
|
case 21:
|
||||||
|
return true;
|
||||||
|
case 22:
|
||||||
|
return null;
|
||||||
|
case 23:
|
||||||
|
return undefined;
|
||||||
|
default:
|
||||||
|
return simpleValue(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = decodeItem();
|
||||||
|
if (offset !== data.byteLength)
|
||||||
|
throw "Remaining bytes";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {encode: encode, decode: decode};
|
||||||
|
|
||||||
|
if (typeof define === "function" && define.amd)
|
||||||
|
define("cbor/cbor", obj);
|
||||||
|
else if (!global.CBOR)
|
||||||
|
global.CBOR = obj;
|
||||||
|
|
||||||
|
})(this);
|
||||||
@@ -220,5 +220,7 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WebAuthn.base64ToBuffer = base64ToBuffer;
|
||||||
|
|
||||||
return WebAuthn;
|
return WebAuthn;
|
||||||
}));
|
}));
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
{#title}Login passwordless{/title}
|
{#title}Login passwordless{/title}
|
||||||
{#add-header}
|
{#add-header}
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script charset="UTF-8" src="/js/cbor.js" type="text/javascript"></script>
|
||||||
<script charset="UTF-8" src="/js/webauthn-debug.js" type="text/javascript"></script>
|
<script charset="UTF-8" src="/js/webauthn-debug.js" type="text/javascript"></script>
|
||||||
<style>
|
<style>
|
||||||
.code {
|
.code {
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step {
|
.step {
|
||||||
@@ -85,16 +87,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section step" id="navigator-response">
|
<div class="section step" id="navigator-attestation">
|
||||||
<div class="col s12 m7">
|
<div class="col s12 m7">
|
||||||
<div class="card horizontal">
|
<div class="card horizontal">
|
||||||
<div class="card-stacked">
|
<div class="card-stacked">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<h6>Attestation</h6>
|
<h6>Attestation</h6>
|
||||||
Which responds:
|
Which responds:
|
||||||
<div class="code" id="navigator-response-body"></div>
|
<div class="code" id="navigator-attestation-body"></div>
|
||||||
The <strong>response.clientDataJSON</strong> are base64 encoded:
|
The <strong>response.clientDataJSON</strong> is base64 encoded:
|
||||||
<div class="code" id="navigator-clientDataJSON"></div>
|
<div class="code" id="navigator-attestation-clientDataJSON"></div>
|
||||||
|
The <strong>response.attestationObject</strong> is <a href="https://cbor.io/">CBOR</a> encoded and contains a public key and metadata:
|
||||||
|
<div class="code" id="navigator-attestationObject" style="height: 150px;"></div>
|
||||||
|
<button class="nextBtn waves-effect waves-light btn full-width">Finish the interaction</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section step" id="navigator-assertion">
|
||||||
|
<div class="col s12 m7">
|
||||||
|
<div class="card horizontal">
|
||||||
|
<div class="card-stacked">
|
||||||
|
<div class="card-content">
|
||||||
|
<h6>Assertion</h6>
|
||||||
|
Which responds:
|
||||||
|
<div class="code" id="navigator-assertion-body"></div>
|
||||||
|
The <strong>response.clientDataJSON</strong> is base64 encoded:
|
||||||
|
<div class="code" id="navigator-assertion-clientDataJSON"></div>
|
||||||
|
The <strong>response.signature</strong> is derived from <strong>clientDataJSON</strong> and <strong>authenticatorData</strong>, using the private key stored on authenticator and validated public key stored on the server
|
||||||
<button class="nextBtn waves-effect waves-light btn full-width">Finish the interaction</button>
|
<button class="nextBtn waves-effect waves-light btn full-width">Finish the interaction</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -217,11 +240,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function traceCredentialsCreateResponse(response) {
|
function traceCredentialsCreateResponse(response) {
|
||||||
$("#navigator-response").showInViewport();
|
$("#navigator-attestation").showInViewport();
|
||||||
$("#navigator-response h6").text("Attestation");
|
$("#navigator-attestation-body").html(JSON.stringify(response, null, 2));
|
||||||
$("#navigator-response-body").html(JSON.stringify(response, null, 2));
|
$("#navigator-attestation-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2));
|
||||||
$("#navigator-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));
|
||||||
return continueButton("#navigator-response", response);
|
return continueButton("#navigator-attestation", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
function traceCredentialsGetRequest(challenge) {
|
function traceCredentialsGetRequest(challenge) {
|
||||||
@@ -231,11 +254,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function traceCredentialsGetResponse(response) {
|
function traceCredentialsGetResponse(response) {
|
||||||
$("#navigator-response").showInViewport();
|
$("#navigator-assertion").showInViewport();
|
||||||
$("#navigator-response h6").text("Assertion");
|
$("#navigator-assertion-body").html(JSON.stringify(response, null, 2));
|
||||||
$("#navigator-response-body").html(JSON.stringify(response, null, 2));
|
$("#navigator-assertion-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2));
|
||||||
$("#navigator-clientDataJSON").html(JSON.stringify(JSON.parse(tryDecodeBase64(response.response.clientDataJSON)), null, 2));
|
return continueButton("#navigator-assertion", response);
|
||||||
return continueButton("#navigator-response", response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function traceGeneric(stage, params) {
|
function traceGeneric(stage, params) {
|
||||||
|
|||||||
Reference in New Issue
Block a user