diff --git a/frontend/src/pages/settings/profile/index.tsx b/frontend/src/pages/settings/profile/index.tsx
index 935280425..bb47bb365 100644
--- a/frontend/src/pages/settings/profile/index.tsx
+++ b/frontend/src/pages/settings/profile/index.tsx
@@ -138,6 +138,15 @@ const UserProfile = ({ user }: { user: Types.User }) => {
|
+ 2FA:
+ {user.passkey?.created_at
+ ? "Passkey"
+ : user.totp?.confirmed_at
+ ? "TOTP"
+ : "None"}
+
+ |
+
Admin:
{user.admin ? "True" : "False"}
diff --git a/frontend/src/pages/settings/profile/passkey.tsx b/frontend/src/pages/settings/profile/passkey.tsx
index 14cd59ac0..9ec7e6e3e 100644
--- a/frontend/src/pages/settings/profile/passkey.tsx
+++ b/frontend/src/pages/settings/profile/passkey.tsx
@@ -1,7 +1,7 @@
import { ConfirmButton } from "@components/util";
import { useManageUser, useUserInvalidate } from "@lib/hooks";
import { Button } from "@ui/button";
-import { PlusCircle, Trash } from "lucide-react";
+import { Fingerprint, Trash } from "lucide-react";
import { Types } from "komodo_client";
import { base64urlToArrayBuffer, cn } from "@lib/utils";
import { useToast } from "@ui/use-toast";
@@ -15,7 +15,7 @@ export const EnrollPasskey = ({ user }: { user: Types.User }) => {
{
onSuccess: () => {
userInvalidate();
- toast({ title: "Unenrolled in passkey authentication" });
+ toast({ title: "Unenrolled in passkey 2FA" });
},
}
);
@@ -66,11 +66,11 @@ export const EnrollPasskey = ({ user }: { user: Types.User }) => {
variant="secondary"
className={cn(
"items-center gap-2",
- !!user.passkey?.created_at && "hidden"
+ (user.totp?.confirmed_at || !!user.passkey?.created_at) && "hidden"
)}
onClick={() => begin_enrollment({})}
>
- Enroll Passkey 2FA
+ Enroll Passkey 2FA
{
const userInvalidate = useUserInvalidate();
+ const { toast } = useToast();
const [open, setOpen] = useState(false);
const [submitted, setSubmitted] = useState<{ uri: string; png: string }>();
const [confirm, setConfirm] = useState("");
@@ -34,7 +36,10 @@ export const EnrollTotp = ({ user }: { user: Types.User }) => {
const { mutate: unenroll, isPending: unenroll_pending } = useManageUser(
"UnenrollTotp",
{
- onSuccess: () => userInvalidate(),
+ onSuccess: () => {
+ userInvalidate();
+ toast({ title: "Unenrolled in TOTP 2FA" });
+ },
}
);
const onOpenChange = (open: boolean) => {
@@ -54,10 +59,11 @@ export const EnrollTotp = ({ user }: { user: Types.User }) => {
variant="secondary"
className={cn(
"items-center gap-2",
- !!user.totp?.confirmed_at && "hidden"
+ (user.passkey?.created_at || !!user.totp?.confirmed_at) &&
+ "hidden"
)}
>
- Enroll TOTP 2FA
+ Enroll TOTP 2FA
@@ -86,6 +92,10 @@ export const EnrollTotp = ({ user }: { user: Types.User }) => {
) : submitted ? (
<>
+
+ Scan this QR code with your authenticator app, and enter the 6
+ digit code below.
+
![]()
{
className="w-72"
value={confirm}
onChange={(e) => setConfirm(e.target.value)}
+ autoFocus
/>