103 lines
2.7 KiB
Svelte
103 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
import { Alert, Button, Input, Label, Spinner } from "flowbite-svelte";
|
|
import { startRegistration } from "@simplewebauthn/browser";
|
|
import InternalAPI from "../../../../helper/api";
|
|
|
|
import { createEventDispatcher } from "svelte";
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
let stage = "get-name";
|
|
let name: string = "";
|
|
|
|
let creating = false;
|
|
let error = undefined;
|
|
|
|
async function register() {
|
|
creating = true;
|
|
error = undefined;
|
|
try {
|
|
let challenge_data = await InternalAPI.TwoFactor.AddWebauthn(name);
|
|
let challenge = JSON.parse(challenge_data.challenge);
|
|
stage = "verify";
|
|
|
|
creating = false;
|
|
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
|
|
console.log(challenge);
|
|
let response = await startRegistration(challenge);
|
|
|
|
await InternalAPI.TwoFactor.VerifyWebAuthn(
|
|
challenge_data.id,
|
|
JSON.stringify(response)
|
|
);
|
|
|
|
stage = "done";
|
|
dispatch("reload");
|
|
} catch (err) {
|
|
error = err.message;
|
|
console.error(err);
|
|
} finally {
|
|
creating = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
{#if error}
|
|
<Alert color="red">
|
|
<h2 class="text-lg font-bold">Error</h2>
|
|
<p class="mt-2">An unknown error occured.</p>
|
|
</Alert>
|
|
{:else if stage == "get-name"}
|
|
<h3 class="text-xl font-medium text-gray-900 dark:text-white p-0">
|
|
Select a name
|
|
</h3>
|
|
<div class="mb-6">
|
|
<Label for="name-input" class="block mb-2">Name</Label>
|
|
<Input id="name-input" placeholder="Name" bind:value={name} />
|
|
</div>
|
|
|
|
<Button disabled={creating} on:click={register}>
|
|
{#if creating}
|
|
<Spinner class="mr-3" size="4" color="white" /> Creating...
|
|
{:else}
|
|
Create
|
|
{/if}
|
|
</Button>
|
|
{:else if stage == "verify"}
|
|
<h3 class="text-xl font-medium text-gray-900 dark:text-white p-0">
|
|
Select device to add
|
|
</h3>
|
|
<!-- <div class="flex flex-col justify-center items-center">
|
|
<img class="w-64" src={totp.qr} alt="Secret {totp.secret}" />
|
|
<div>Manually:</div>
|
|
<div class="text-sm">
|
|
{totp.secret}
|
|
</div>
|
|
</div>
|
|
<div class="mb-6">
|
|
<Label for="code-input" class="block mb-2">Code</Label>
|
|
<Input id="code-input" placeholder="Code" bind:value={code} />
|
|
</div>
|
|
|
|
{#if verifyError}
|
|
<Alert color="red">
|
|
<h2 class="text-lg font-bold">Error</h2>
|
|
<p class="mt-2">{verifyError}</p>
|
|
</Alert>
|
|
{/if}
|
|
|
|
<Button disabled={verifing} on:click={verifyTOTP}>
|
|
{#if verifing}
|
|
<Spinner class="mr-3" size="4" color="white" /> Verify...
|
|
{:else}
|
|
Verify
|
|
{/if}
|
|
</Button> -->
|
|
{:else if stage == "done"}
|
|
<Alert color="green">
|
|
<h2 class="text-lg font-bold">Success</h2>
|
|
<p class="mt-2">Your WebAuthn device has been registered.</p>
|
|
</Alert>
|
|
{/if}
|