diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 8c15c234..76456bc6 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -158,7 +158,8 @@ "customPassphrasePlaceholder": "Enter your custom passphrase", "useCustomPassphrase": "Use Custom Passphrase", "invalidPassphraseCharacters": "Invalid passphrase characters. Only English letters, numbers 1-10, and normal symbols are allowed.", - "passphraseTooShort": "Passphrase must be at least 8 characters long." + "passphraseTooShort": "Passphrase must be at least 8 characters long.", + "usePasskeyInstead": "Use passkey instead" }, "hasAccount": "Already have an account? <0>Login here.0>", "login": { @@ -168,7 +169,10 @@ "passphrasePlaceholder": "Passphrase", "submit": "Login", "title": "Login to your account", - "validationError": "Incorrect or incomplete passphrase /ᐠ. .ᐟ\\" + "validationError": "Incorrect or incomplete passphrase /ᐠ. .ᐟ\\", + "usePasskey": "Use passkey", + "or": "or", + "noBackendUrl": "No backend URL" }, "register": { "information": { @@ -209,7 +213,9 @@ "passphraseLabel": "Your 12-word passphrase", "recaptchaFailed": "ReCaptcha validation failed", "register": "Create account", - "title": "Confirm your passphrase" + "title": "Confirm your passphrase", + "passkeyDescription": "Please authenticate with your passkey to complete registration.", + "authenticatePasskey": "Authenticate with Passkey" } }, "errors": { diff --git a/src/backend/accounts/crypto.ts b/src/backend/accounts/crypto.ts index fa7e045a..f98fc5da 100644 --- a/src/backend/accounts/crypto.ts +++ b/src/backend/accounts/crypto.ts @@ -156,7 +156,12 @@ export function decryptData(data: string, secret: Uint8Array) { // Passkey/WebAuthn utilities export function isPasskeySupported(): boolean { + // Passkeys require HTTPS + const isSecureContext = + typeof window !== "undefined" && window.location.protocol === "https:"; + return ( + isSecureContext && typeof navigator !== "undefined" && "credentials" in navigator && "create" in navigator.credentials && diff --git a/src/pages/parts/auth/LoginFormPart.tsx b/src/pages/parts/auth/LoginFormPart.tsx index ecb2d868..71f6f7d6 100644 --- a/src/pages/parts/auth/LoginFormPart.tsx +++ b/src/pages/parts/auth/LoginFormPart.tsx @@ -117,8 +117,40 @@ export function LoginFormPart(props: LoginFormPartProps) { {t("auth.login.description")}
+ {result.error?.message || passkeyResult.error?.message} +
+ ) : null} {isPasskeySupported() && ( -- {result.error?.message || passkeyResult.error?.message} -
- ) : null}
diff --git a/src/pages/parts/auth/VerifyPassphrasePart.tsx b/src/pages/parts/auth/VerifyPassphrasePart.tsx
index f386d1b3..7b939e85 100644
--- a/src/pages/parts/auth/VerifyPassphrasePart.tsx
+++ b/src/pages/parts/auth/VerifyPassphrasePart.tsx
@@ -188,8 +188,7 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
icon={
@@ -203,8 +202,7 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
onClick={() => authenticatePasskeyFn()}
>