Files
crowd-funder-for-time-pwa/src/views/TestView.vue

399 lines
11 KiB
Vue

<template>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Test
</h1>
</div>
<div>
<h2 class="text-xl font-bold mb-4">Notiwind Alerts</h2>
<button
@click="
this.$notify(
{
group: 'alert',
type: 'toast',
text: 'I\'m a toast. Without a timeout, I\'m stuck.',
},
5000,
)
"
class="font-bold uppercase bg-slate-900 text-white px-3 py-2 rounded-md mr-2"
>
Toast
</button>
<button
@click="
this.$notify(
{
group: 'alert',
type: 'info',
title: 'Information Alert',
text: 'Just wanted you to know.',
},
-1,
)
"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Info
</button>
<button
@click="
this.$notify(
{
group: 'alert',
type: 'success',
title: 'Success Alert',
text: 'Congratulations!',
},
-1,
)
"
class="font-bold uppercase bg-emerald-600 text-white px-3 py-2 rounded-md mr-2"
>
Success
</button>
<button
@click="
this.$notify(
{
group: 'alert',
type: 'warning',
title: 'Warning Alert',
text: 'You might wanna look at this.',
},
-1,
)
"
class="font-bold uppercase bg-amber-600 text-white px-3 py-2 rounded-md mr-2"
>
Warning
</button>
<button
@click="
this.$notify(
{
group: 'alert',
type: 'danger',
title: 'Danger Alert',
text: 'Something terrible has happened!',
},
-1,
)
"
class="font-bold uppercase bg-rose-600 text-white px-3 py-2 rounded-md mr-2"
>
Danger
</button>
<button
@click="
this.$notify(
{
group: 'modal',
type: 'notification-permission',
},
-1,
)
"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Notif ON
</button>
<button
@click="
this.$notify(
{
group: 'modal',
type: 'notification-mute',
},
-1,
)
"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Notif MUTE
</button>
<button
@click="
this.$notify(
{
group: 'modal',
type: 'notification-off',
},
-1,
)
"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Notif OFF
</button>
</div>
<div class="mt-8">
<h2 class="text-xl font-bold mb-4">Image Sharing</h2>
Populates the "shared-photo" view as if they used "share_target".
<input type="file" @change="uploadFile" />
<router-link
v-if="showFileNextStep()"
:to="{
name: 'shared-photo',
query: { fileName },
}"
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2 mt-2"
>
Go to Shared Page
</router-link>
</div>
<div class="mt-8">
<h2 class="text-xl font-bold mb-4">Passkeys</h2>
<div>
Register
<button
@click="register()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Simplewebauthn
</button>
</div>
<div>
Create
<button
@click="createJwtSimplewebauthn()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Simplewebauthn
</button>
<button
@click="createJwtNavigator()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Navigator
</button>
</div>
<div>
Verify
<button
@click="verifySimplewebauthn()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
Simplewebauthn
</button>
<button
@click="verifyWebCrypto()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
WebCrypto
</button>
<button
@click="verifyP256()"
class="font-bold uppercase bg-slate-600 text-white px-3 py-2 rounded-md mr-2"
>
p256 - broken
</button>
</div>
</div>
</section>
</template>
<script lang="ts">
import { Base64URLString } from "@simplewebauthn/types";
import { ref } from "vue";
import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "@/components/QuickNav.vue";
import { db } from "@/db/index";
import { generateRandomBytes } from "@/libs/crypto";
import {
createPeerDid,
JWK,
PeerSetup,
registerCredential, verifyJwtP256,
verifyJwtSimplewebauthn,
verifyJwtWebCrypto,
} from "@/libs/didPeer";
import { JWTPayload } from "did-jwt";
const inputFileNameRef = ref<Blob>();
@Component({ components: { QuickNav } })
export default class Help extends Vue {
// for file import
fileName?: string;
// for passkeys
credId?: Base64URLString;
jwt?: string;
peerSetup?: PeerSetup;
publicKeyJwk?: JWK;
publicKeyBytes?: Uint8Array;
rawId?: Uint8Array;
userId?: ArrayBuffer;
async uploadFile(event: Event) {
inputFileNameRef.value = event.target.files[0];
// https://developer.mozilla.org/en-US/docs/Web/API/File
// ... plus it has a `type` property from my testing
const file = inputFileNameRef.value;
if (file != null) {
const reader = new FileReader();
reader.onload = async (e) => {
const data = e.target?.result as ArrayBuffer;
if (data) {
const blob = new Blob([new Uint8Array(data)], {
type: file.type,
});
this.fileName = file.name as string;
const temp = await db.temp.get("shared-photo");
if (temp) {
await db.temp.update("shared-photo", { blob });
} else {
await db.temp.add({ id: "shared-photo", blob });
}
}
};
reader.readAsArrayBuffer(file as Blob);
}
}
showFileNextStep() {
return !!inputFileNameRef.value;
}
public async register() {
this.userId = generateRandomBytes(16).buffer;
const cred = await registerCredential(this.userId as Uint8Array);
console.log("public key", cred);
this.publicKeyJwk = cred.publicKeyJwk;
this.publicKeyBytes = cred.publicKeyBytes;
this.credId = cred.credId as string;
this.rawId = cred.rawId as Uint8Array;
}
public async createJwtSimplewebauthn() {
const did = createPeerDid(this.publicKeyBytes as Uint8Array);
console.log("generated peer did", did);
const payload = {
"@context": "https://schema.org",
type: "GiveAction",
description: "pizza",
};
// from createJWT in did-jwt/src/JWT.ts
const timestamps: Partial<JWTPayload> = {
iat: Math.floor(Date.now() / 1000),
exp: undefined,
};
const fullPayload = { ...timestamps, ...payload, did };
this.peerSetup = new PeerSetup();
this.jwt = await this.peerSetup.createJwtSimplewebauthn(
fullPayload,
this.credId as string,
);
console.log("simple jwt4url", this.jwt);
}
public async createJwtNavigator() {
const did = createPeerDid(this.publicKeyBytes as Uint8Array);
console.log("generated peer did", did);
const payload = {
"@context": "https://schema.org",
type: "GiveAction",
description: "pizza",
};
// from createJWT in did-jwt/src/JWT.ts
const timestamps: Partial<JWTPayload> = {
iat: Math.floor(Date.now() / 1000),
exp: undefined,
};
const fullPayload = { ...timestamps, ...payload, did };
this.peerSetup = new PeerSetup();
this.jwt = await this.peerSetup.createJwtNavigator(
fullPayload,
this.credId as string,
);
console.log("lower jwt4url", this.jwt);
}
public async verifyP256() {
const decoded = await verifyJwtP256(
this.jwt as string,
this.credId as Base64URLString,
this.rawId as Uint8Array,
this.peerSetup.authenticatorData as ArrayBuffer,
this.peerSetup.authenticatorDataBase64Url as Base64URLString,
this.peerSetup.challenge as Uint8Array,
this.peerSetup.clientDataJsonDecoded,
this.peerSetup.clientDataJsonBase64Url as Base64URLString,
this.publicKeyBytes as Uint8Array,
this.publicKeyJwk as JWK,
this.peerSetup.signature as Base64URLString,
);
console.log("decoded", decoded);
}
public async verifySimplewebauthn() {
const decoded = await verifyJwtSimplewebauthn(
this.jwt as string,
this.credId as Base64URLString,
this.rawId as Uint8Array,
this.peerSetup.authenticatorData as ArrayBuffer,
this.peerSetup.authenticatorDataBase64Url as Base64URLString,
this.peerSetup.challenge as Uint8Array,
this.peerSetup.clientDataJsonDecoded,
this.peerSetup.clientDataJsonBase64Url as Base64URLString,
this.publicKeyBytes as Uint8Array,
this.publicKeyJwk as JWK,
this.peerSetup.signature as Base64URLString,
);
console.log("decoded", decoded);
}
public async verifyWebCrypto() {
const decoded = await verifyJwtWebCrypto(
this.jwt as string,
this.credId as Base64URLString,
this.rawId as Uint8Array,
this.peerSetup.authenticatorData as ArrayBuffer,
this.peerSetup.authenticatorDataBase64Url as Base64URLString,
this.peerSetup.challenge as Uint8Array,
this.peerSetup.clientDataJsonDecoded,
this.peerSetup.clientDataJsonBase64Url as Base64URLString,
this.publicKeyBytes as Uint8Array,
this.publicKeyJwk as JWK,
this.peerSetup.signature as Base64URLString,
);
console.log("decoded", decoded);
}
}
</script>