|
@ -172,6 +172,10 @@ |
|
|
|
|
|
|
|
|
<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. |
|
|
|
|
|
<br/> |
|
|
|
|
|
Active DID: {{ activeDid }} |
|
|
|
|
|
{{ credIdHex ? "has passkey ID" : "has no passkey ID" }} |
|
|
<div> |
|
|
<div> |
|
|
Register |
|
|
Register |
|
|
<button |
|
|
<button |
|
@ -222,13 +226,13 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script lang="ts"> |
|
|
<script lang="ts"> |
|
|
|
|
|
import { Buffer } from "buffer/"; |
|
|
import { Base64URLString } from "@simplewebauthn/types"; |
|
|
import { Base64URLString } from "@simplewebauthn/types"; |
|
|
import { ref } from "vue"; |
|
|
import { ref } from "vue"; |
|
|
import { Component, Vue } from "vue-facing-decorator"; |
|
|
import { Component, Vue } from "vue-facing-decorator"; |
|
|
|
|
|
|
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
import { db } from "@/db/index"; |
|
|
import { accountsDB, db } from "@/db/index"; |
|
|
import { generateRandomBytes } from "@/libs/crypto"; |
|
|
|
|
|
import { |
|
|
import { |
|
|
createPeerDid, |
|
|
createPeerDid, |
|
|
PeerSetup, |
|
|
PeerSetup, |
|
@ -238,6 +242,7 @@ import { |
|
|
verifyJwtWebCrypto, |
|
|
verifyJwtWebCrypto, |
|
|
} from "@/libs/didPeer"; |
|
|
} from "@/libs/didPeer"; |
|
|
import { JWTPayload } from "did-jwt"; |
|
|
import { JWTPayload } from "did-jwt"; |
|
|
|
|
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; |
|
|
|
|
|
|
|
|
const inputFileNameRef = ref<Blob>(); |
|
|
const inputFileNameRef = ref<Blob>(); |
|
|
|
|
|
|
|
@ -247,12 +252,30 @@ export default class Help extends Vue { |
|
|
fileName?: string; |
|
|
fileName?: string; |
|
|
|
|
|
|
|
|
// for passkeys |
|
|
// for passkeys |
|
|
credId?: Base64URLString; |
|
|
credIdHex?: string; |
|
|
did?: string; |
|
|
activeDid?: string; |
|
|
jwt?: string; |
|
|
jwt?: string; |
|
|
peerSetup?: PeerSetup; |
|
|
peerSetup?: PeerSetup; |
|
|
rawId?: Uint8Array; |
|
|
rawId?: Uint8Array; |
|
|
userId?: ArrayBuffer; |
|
|
userName?: string; |
|
|
|
|
|
|
|
|
|
|
|
async mounted() { |
|
|
|
|
|
await db.open(); |
|
|
|
|
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY); |
|
|
|
|
|
this.activeDid = (settings?.activeDid as string) || ""; |
|
|
|
|
|
this.userName = settings?.firstName as string; |
|
|
|
|
|
|
|
|
|
|
|
await accountsDB.open(); |
|
|
|
|
|
const account: { identity?: string } | undefined = |
|
|
|
|
|
await accountsDB.accounts.where("did").equals(this.activeDid).first(); |
|
|
|
|
|
if (this.activeDid) { |
|
|
|
|
|
if (account) { |
|
|
|
|
|
this.credIdHex = account.passkeyCredIdHex as string; |
|
|
|
|
|
} else { |
|
|
|
|
|
alert("No account found for DID " + this.activeDid); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
async uploadFile(event: Event) { |
|
|
async uploadFile(event: Event) { |
|
|
inputFileNameRef.value = event.target.files[0]; |
|
|
inputFileNameRef.value = event.target.files[0]; |
|
@ -285,19 +308,26 @@ export default class Help extends Vue { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async register() { |
|
|
public async register() { |
|
|
this.userId = generateRandomBytes(16).buffer; |
|
|
const cred = await registerCredential(this.userName); |
|
|
|
|
|
const publicKeyBytes = cred.publicKeyBytes; |
|
|
const cred = await registerCredential(this.userId as Uint8Array); |
|
|
this.activeDid = createPeerDid(publicKeyBytes as Uint8Array); |
|
|
console.log("public key", cred); |
|
|
this.credIdHex = cred.credIdHex as string; |
|
|
this.publicKeyBytes = cred.publicKeyBytes; |
|
|
|
|
|
this.did = createPeerDid(this.publicKeyBytes as Uint8Array); |
|
|
|
|
|
this.credId = cred.credId as string; |
|
|
|
|
|
this.rawId = cred.rawId as Uint8Array; |
|
|
this.rawId = cred.rawId as Uint8Array; |
|
|
|
|
|
|
|
|
|
|
|
await accountsDB.open(); |
|
|
|
|
|
await accountsDB.accounts.add({ |
|
|
|
|
|
dateCreated: new Date().toISOString(), |
|
|
|
|
|
did: this.activeDid, |
|
|
|
|
|
passkeyCredIdHex: this.credIdHex, |
|
|
|
|
|
publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"), |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// await db.settings.update(MASTER_SETTINGS_KEY, { |
|
|
|
|
|
// activeDid: this.did, |
|
|
|
|
|
// }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async createJwtSimplewebauthn() { |
|
|
public async createJwtSimplewebauthn() { |
|
|
console.log("generated peer did", this.did); |
|
|
|
|
|
|
|
|
|
|
|
const payload = { |
|
|
const payload = { |
|
|
"@context": "https://schema.org", |
|
|
"@context": "https://schema.org", |
|
|
type: "GiveAction", |
|
|
type: "GiveAction", |
|
@ -306,20 +336,19 @@ export default class Help extends Vue { |
|
|
// from createJWT in did-jwt/src/JWT.ts |
|
|
// from createJWT in did-jwt/src/JWT.ts |
|
|
const timestamps: Partial<JWTPayload> = { |
|
|
const timestamps: Partial<JWTPayload> = { |
|
|
iat: Math.floor(Date.now() / 1000), |
|
|
iat: Math.floor(Date.now() / 1000), |
|
|
exp: undefined, |
|
|
|
|
|
}; |
|
|
}; |
|
|
const fullPayload = { ...timestamps, ...payload, iss: this.did }; |
|
|
const fullPayload = { ...timestamps, ...payload, iss: this.activeDid }; |
|
|
|
|
|
|
|
|
this.peerSetup = new PeerSetup(); |
|
|
this.peerSetup = new PeerSetup(); |
|
|
this.jwt = await this.peerSetup.createJwtSimplewebauthn( |
|
|
this.jwt = await this.peerSetup.createJwtSimplewebauthn( |
|
|
fullPayload, |
|
|
fullPayload, |
|
|
this.credId as string, |
|
|
this.credIdHex as string, |
|
|
); |
|
|
); |
|
|
console.log("simple jwt4url", this.jwt); |
|
|
console.log("simple jwt4url", this.jwt); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async createJwtNavigator() { |
|
|
public async createJwtNavigator() { |
|
|
console.log("generated peer did", this.did); |
|
|
console.log("generated peer did", this.activeDid); |
|
|
|
|
|
|
|
|
const payload = { |
|
|
const payload = { |
|
|
"@context": "https://schema.org", |
|
|
"@context": "https://schema.org", |
|
@ -329,23 +358,22 @@ export default class Help extends Vue { |
|
|
// from createJWT in did-jwt/src/JWT.ts |
|
|
// from createJWT in did-jwt/src/JWT.ts |
|
|
const timestamps: Partial<JWTPayload> = { |
|
|
const timestamps: Partial<JWTPayload> = { |
|
|
iat: Math.floor(Date.now() / 1000), |
|
|
iat: Math.floor(Date.now() / 1000), |
|
|
exp: undefined, |
|
|
|
|
|
}; |
|
|
}; |
|
|
const fullPayload = { ...timestamps, ...payload, iss: this.did }; |
|
|
const fullPayload = { ...timestamps, ...payload, iss: this.activeDid }; |
|
|
|
|
|
|
|
|
this.peerSetup = new PeerSetup(); |
|
|
this.peerSetup = new PeerSetup(); |
|
|
this.jwt = await this.peerSetup.createJwtNavigator( |
|
|
this.jwt = await this.peerSetup.createJwtNavigator( |
|
|
fullPayload, |
|
|
fullPayload, |
|
|
this.credId as string, |
|
|
this.credIdHex as string, |
|
|
); |
|
|
); |
|
|
console.log("lower jwt4url", this.jwt); |
|
|
console.log("lower jwt4url", this.jwt); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async verifyP256() { |
|
|
public async verifyP256() { |
|
|
const decoded = await verifyJwtP256( |
|
|
const decoded = await verifyJwtP256( |
|
|
this.credId as Base64URLString, |
|
|
this.credIdHex as Base64URLString, |
|
|
this.rawId as Uint8Array, |
|
|
this.rawId as Uint8Array, |
|
|
this.did 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, |
|
@ -356,9 +384,9 @@ export default class Help extends Vue { |
|
|
|
|
|
|
|
|
public async verifySimplewebauthn() { |
|
|
public async verifySimplewebauthn() { |
|
|
const decoded = await verifyJwtSimplewebauthn( |
|
|
const decoded = await verifyJwtSimplewebauthn( |
|
|
this.credId as Base64URLString, |
|
|
this.credIdHex as Base64URLString, |
|
|
this.rawId as Uint8Array, |
|
|
this.rawId as Uint8Array, |
|
|
this.did 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, |
|
@ -369,9 +397,9 @@ export default class Help extends Vue { |
|
|
|
|
|
|
|
|
public async verifyWebCrypto() { |
|
|
public async verifyWebCrypto() { |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
const decoded = await verifyJwtWebCrypto( |
|
|
this.credId as Base64URLString, |
|
|
this.credIdHex as Base64URLString, |
|
|
this.rawId as Uint8Array, |
|
|
this.rawId as Uint8Array, |
|
|
this.did 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, |
|
|