|
@ -173,59 +173,65 @@ |
|
|
<div class="mt-8"> |
|
|
<div class="mt-8"> |
|
|
<h2 class="text-xl font-bold mb-4">Passkeys</h2> |
|
|
<h2 class="text-xl font-bold mb-4">Passkeys</h2> |
|
|
See console for results. |
|
|
See console for results. |
|
|
<br/> |
|
|
<br /> |
|
|
|
|
|
See existing passkeys in Chrome at: chrome://settings/passkeys |
|
|
|
|
|
<br /> |
|
|
Active DID: {{ activeDid }} |
|
|
Active DID: {{ activeDid }} |
|
|
{{ credIdHex ? "has passkey ID" : "has no passkey ID" }} |
|
|
{{ credIdHex ? "has passkey ID" : "has no passkey ID" }} |
|
|
|
|
|
|
|
|
<div> |
|
|
<div> |
|
|
Register |
|
|
Register Passkey |
|
|
<button |
|
|
<button |
|
|
@click="register()" |
|
|
@click="register()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
Simplewebauthn |
|
|
Simplewebauthn |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div> |
|
|
<div> |
|
|
Create |
|
|
Create JWT |
|
|
<button |
|
|
<button |
|
|
@click="createJwtSimplewebauthn()" |
|
|
@click="createJwtSimplewebauthn()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
Simplewebauthn |
|
|
Simplewebauthn |
|
|
</button> |
|
|
</button> |
|
|
<button |
|
|
<button |
|
|
@click="createJwtNavigator()" |
|
|
@click="createJwtNavigator()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
Navigator |
|
|
Navigator |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div v-if="jwt"> |
|
|
<div v-if="jwt"> |
|
|
Verify |
|
|
Verify New JWT |
|
|
<button |
|
|
<button |
|
|
@click="verifySimplewebauthn()" |
|
|
@click="verifySimplewebauthn()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
Simplewebauthn |
|
|
Simplewebauthn |
|
|
</button> |
|
|
</button> |
|
|
<button |
|
|
<button |
|
|
@click="verifyWebCrypto()" |
|
|
@click="verifyWebCrypto()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
WebCrypto |
|
|
WebCrypto |
|
|
</button> |
|
|
</button> |
|
|
<button |
|
|
<button |
|
|
@click="verifyP256()" |
|
|
@click="verifyP256()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
p256 - broken |
|
|
p256 - broken |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div v-else>Verify New JWT -- requires creation first</div> |
|
|
<button |
|
|
<button |
|
|
@click="verifyMyJwt()" |
|
|
@click="verifyMyJwt()" |
|
|
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2" |
|
|
class="font-bold uppercase bg-slate-500 text-white px-3 py-2 rounded-md mr-2" |
|
|
> |
|
|
> |
|
|
Verify Mine |
|
|
Verify Hard-Coded JWT |
|
|
</button> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
</section> |
|
@ -335,7 +341,7 @@ export default class Help extends Vue { |
|
|
did: this.activeDid, |
|
|
did: this.activeDid, |
|
|
passkeyCredIdHex: this.credIdHex, |
|
|
passkeyCredIdHex: this.credIdHex, |
|
|
publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"), |
|
|
publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"), |
|
|
});`` |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async createJwtSimplewebauthn() { |
|
|
public async createJwtSimplewebauthn() { |
|
@ -360,44 +366,46 @@ export default class Help extends Vue { |
|
|
|
|
|
|
|
|
public async verifyP256() { |
|
|
public async verifyP256() { |
|
|
const decoded = await verifyJwtP256( |
|
|
const decoded = await verifyJwtP256( |
|
|
this.credIdHex as Base64URLString, |
|
|
this.credIdHex as string, |
|
|
this.activeDid as string, |
|
|
this.activeDid as string, |
|
|
this.peerSetup.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup?.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup.challenge as Uint8Array, |
|
|
this.peerSetup?.challenge as Uint8Array, |
|
|
this.peerSetup.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup?.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup.signature as Base64URLString, |
|
|
this.peerSetup?.signature as Base64URLString, |
|
|
); |
|
|
); |
|
|
console.log("decoded", decoded); |
|
|
console.log("decoded", decoded); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async verifySimplewebauthn() { |
|
|
public async verifySimplewebauthn() { |
|
|
const decoded = await verifyJwtSimplewebauthn( |
|
|
const decoded = await verifyJwtSimplewebauthn( |
|
|
this.credIdHex as Base64URLString, |
|
|
this.credIdHex as string, |
|
|
this.activeDid as string, |
|
|
this.activeDid as string, |
|
|
this.peerSetup.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup?.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup.challenge as Uint8Array, |
|
|
this.peerSetup?.challenge as Uint8Array, |
|
|
this.peerSetup.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup?.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup.signature as Base64URLString, |
|
|
this.peerSetup?.signature as Base64URLString, |
|
|
); |
|
|
); |
|
|
console.log("decoded", decoded); |
|
|
console.log("decoded", decoded); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async verifyWebCrypto() { |
|
|
public async verifyWebCrypto() { |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
this.credIdHex as Base64URLString, |
|
|
this.credIdHex as string, |
|
|
this.activeDid as string, |
|
|
this.activeDid as string, |
|
|
this.peerSetup.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup?.authenticatorData as ArrayBuffer, |
|
|
this.peerSetup.challenge as Uint8Array, |
|
|
this.peerSetup?.challenge as Uint8Array, |
|
|
this.peerSetup.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup?.clientDataJsonBase64Url as Base64URLString, |
|
|
this.peerSetup.signature as Base64URLString, |
|
|
this.peerSetup?.signature as Base64URLString, |
|
|
); |
|
|
); |
|
|
console.log("decoded", decoded); |
|
|
console.log("decoded", decoded); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async verifyMyJwt() { |
|
|
public async verifyMyJwt() { |
|
|
|
|
|
const did = |
|
|
|
|
|
"did:peer:0zKMFjvUgYrM1hXwDciYHiA9MxXtJPXnRLJvqoMNAKoDLX9pKMWLb3VDsgua1p2zW1xXRsjZSTNsfvMnNyMS7dB4k7NAhFwL3pXBrBXgyYJ9ri"; |
|
|
const jwt = |
|
|
const jwt = |
|
|
"eyJ0eXAiOiJKV0FOVCIsImFsZyI6IkVTMjU2In0.eyJBdXRoZW50aWNhdGlvbkRhdGFCNjRVUkwiOiJTWllONVlnT2pHaDBOQmNQWkhaZ1c0X2tycm1paGpMSG1Wenp1b01kbDJNRkFBQUFBQSIsIkNsaWVudERhdGFKU09OQjY0VVJMIjoiZXlKMGVYQmxJam9pZDJWaVlYVjBhRzR1WjJWMElpd2lZMmhoYkd4bGJtZGxJam9pWlhsS01sbDVTVFpsZVVwcVkyMVdhMXBYTlRCaFYwWnpWVE5XYVdGdFZtcGtRMGsyWlhsS1FWa3lPWFZrUjFZMFpFTkpOa2x0YURCa1NFSjZUMms0ZG1NeVRtOWFWekZvVEcwNWVWcDVTWE5KYTBJd1pWaENiRWxxYjJsU01td3lXbFZHYW1SSGJIWmlhVWx6U1cxU2JHTXlUbmxoV0VJd1lWYzVkVWxxYjJsalIydzJaVzFGYVdaWU1ITkpiV3hvWkVOSk5rMVVZM2hQUkZVMFRtcHJOVTFEZDJsaFdFNTZTV3B2YVZwSGJHdFBia0pzV2xoSk5rMUljRXhVVlZweFpHeFdibGRZU2s1TlYyaFpaREJTYW1GV2JFbGhWVVUxVkZob1dXUkZjRkZYUnpWVFZFVndNbU5YT1U1VWEwWk1ZakJTVFZkRWJIZFRNREZZVkVkSmVsWnJVbnBhTTFab1RWaEJlV1ZzWTNobFJtaFRZekp3WVZVeFVrOWpNbG95VkZjMVQyVlZNVlJPTWxKRFRrZHpNMVJyUm05U2JtUk5UVE5DV1ZGdVNrTlhSMlExVjFWdk5XTnRhMmxtVVNJc0ltOXlhV2RwYmlJNkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk9EQTRNQ0lzSW1OeWIzTnpUM0pwWjJsdUlqcG1ZV3h6WlgwIiwiaWF0IjoxNzE4NTg2OTkyLCJpc3MiOiJkaWQ6cGVlcjowektNRmp2VWdZck0xaFh3RGNpWUhpQTlNeFh0SlBYblJMSnZxb01OQUtvRExYOXBLTVdMYjNWRHNndWExcDJ6VzF4WFJzalpTVE5zZnZNbk55TVM3ZEI0azdOQWhGd0wzcFhCckJYZ3lZSjlyaSJ9.MEUCIQDJyCTbMPIFnuBoW3FYnlgtDEIHZ2OrkCEvqVnHU7kJDQIgVxjBjfW1TwQfcSOYwK8Z7AdCWGJlyxtLEsrnPif7caE"; |
|
|
"eyJ0eXAiOiJKV0FOVCIsImFsZyI6IkVTMjU2In0.eyJBdXRoZW50aWNhdGlvbkRhdGFCNjRVUkwiOiJTWllONVlnT2pHaDBOQmNQWkhaZ1c0X2tycm1paGpMSG1Wenp1b01kbDJNRkFBQUFBQSIsIkNsaWVudERhdGFKU09OQjY0VVJMIjoiZXlKMGVYQmxJam9pZDJWaVlYVjBhRzR1WjJWMElpd2lZMmhoYkd4bGJtZGxJam9pWlhsS01sbDVTVFpsZVVwcVkyMVdhMXBYTlRCaFYwWnpWVE5XYVdGdFZtcGtRMGsyWlhsS1FWa3lPWFZrUjFZMFpFTkpOa2x0YURCa1NFSjZUMms0ZG1NeVRtOWFWekZvVEcwNWVWcDVTWE5KYTBJd1pWaENiRWxxYjJsU01td3lXbFZHYW1SSGJIWmlhVWx6U1cxU2JHTXlUbmxoV0VJd1lWYzVkVWxxYjJsalIydzJaVzFGYVdaWU1ITkpiV3hvWkVOSk5rMVVZM2hQUkZVMFRtcHJOVTFEZDJsaFdFNTZTV3B2YVZwSGJHdFBia0pzV2xoSk5rMUljRXhVVlZweFpHeFdibGRZU2s1TlYyaFpaREJTYW1GV2JFbGhWVVUxVkZob1dXUkZjRkZYUnpWVFZFVndNbU5YT1U1VWEwWk1ZakJTVFZkRWJIZFRNREZZVkVkSmVsWnJVbnBhTTFab1RWaEJlV1ZzWTNobFJtaFRZekp3WVZVeFVrOWpNbG95VkZjMVQyVlZNVlJPTWxKRFRrZHpNMVJyUm05U2JtUk5UVE5DV1ZGdVNrTlhSMlExVjFWdk5XTnRhMmxtVVNJc0ltOXlhV2RwYmlJNkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk9EQTRNQ0lzSW1OeWIzTnpUM0pwWjJsdUlqcG1ZV3h6WlgwIiwiaWF0IjoxNzE4NTg2OTkyLCJpc3MiOiJkaWQ6cGVlcjowektNRmp2VWdZck0xaFh3RGNpWUhpQTlNeFh0SlBYblJMSnZxb01OQUtvRExYOXBLTVdMYjNWRHNndWExcDJ6VzF4WFJzalpTVE5zZnZNbk55TVM3ZEI0azdOQWhGd0wzcFhCckJYZ3lZSjlyaSJ9.MEUCIQDJyCTbMPIFnuBoW3FYnlgtDEIHZ2OrkCEvqVnHU7kJDQIgVxjBjfW1TwQfcSOYwK8Z7AdCWGJlyxtLEsrnPif7caE"; |
|
|
const pieces = jwt.split("."); |
|
|
const pieces = jwt.split("."); |
|
|
console.log("pieces", typeof pieces[1], pieces); |
|
|
|
|
|
const payload = JSON.parse(Buffer.from(pieces[1], "base64").toString()); |
|
|
const payload = JSON.parse(Buffer.from(pieces[1], "base64").toString()); |
|
|
const authData = Buffer.from(payload["AuthenticationDataB64URL"], "base64"); |
|
|
const authData = Buffer.from(payload["AuthenticationDataB64URL"], "base64"); |
|
|
const clientJSON = Buffer.from( |
|
|
const clientJSON = Buffer.from( |
|
@ -408,8 +416,8 @@ export default class Help extends Vue { |
|
|
const challenge = clientData.challenge; |
|
|
const challenge = clientData.challenge; |
|
|
const signatureB64URL = pieces[2]; |
|
|
const signatureB64URL = pieces[2]; |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
this.credIdHex as Base64URLString, |
|
|
this.credIdHex as string, |
|
|
this.activeDid as string, |
|
|
did, |
|
|
authData, |
|
|
authData, |
|
|
challenge, |
|
|
challenge, |
|
|
payload["ClientDataJSONB64URL"], |
|
|
payload["ClientDataJSONB64URL"], |
|
|