diff --git a/Makefile b/Makefile
index 4750b17ef..f04e8dac8 100644
--- a/Makefile
+++ b/Makefile
@@ -129,7 +129,7 @@ gen: gen-build gen-clean gen-client-ts
web-build: web-install
cd web && npm run build
-web: web-lint-fix web-lint web-check-compile
+web: web-lint-fix web-lint web-check-compile web-i18n-extract
web-install:
cd web && npm ci
diff --git a/web/src/common/helpers/webauthn.ts b/web/src/common/helpers/webauthn.ts
index 01b1f05f6..c10edff17 100644
--- a/web/src/common/helpers/webauthn.ts
+++ b/web/src/common/helpers/webauthn.ts
@@ -1,5 +1,7 @@
import * as base64js from "base64-js";
+import { msg } from "@lit/localize";
+
export function b64enc(buf: Uint8Array): string {
return base64js.fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}
@@ -14,6 +16,16 @@ export function u8arr(input: string): Uint8Array {
);
}
+export function checkWebAuthnSupport() {
+ if ("credentials" in navigator) {
+ return;
+ }
+ if (window.location.protocol === "http:" && window.location.hostname !== "localhost") {
+ throw new Error(msg("WebAuthn requires this page to be accessed via HTTPS."));
+ }
+ throw new Error(msg("WebAuthn not supported by browser."));
+}
+
/**
* Transforms items in the credentialCreateOptions generated on the server
* into byte arrays expected by the navigator.credentials.create() call
diff --git a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts
index fdb749981..12e9b0a60 100644
--- a/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts
+++ b/web/src/flow/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts
@@ -1,4 +1,5 @@
import {
+ checkWebAuthnSupport,
transformAssertionForServer,
transformCredentialRequestOptions,
} from "@goauthentik/common/helpers/webauthn";
@@ -57,6 +58,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage<
// request the authenticator to create an assertion signature using the
// credential private key
let assertion;
+ checkWebAuthnSupport();
try {
assertion = await navigator.credentials.get({
publicKey: this.transformedCredentialRequestOptions,
diff --git a/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts b/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
index a82f10bce..dd056da66 100644
--- a/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
+++ b/web/src/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
@@ -1,5 +1,6 @@
import {
Assertion,
+ checkWebAuthnSupport,
transformCredentialCreateOptions,
transformNewAssertionForServer,
} from "@goauthentik/common/helpers/webauthn";
@@ -47,6 +48,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage<
if (!this.challenge) {
return;
}
+ checkWebAuthnSupport();
// request the authenticator(s) to create a new credential keypair.
let credential;
try {
diff --git a/web/xliff/de.xlf b/web/xliff/de.xlf
index 593f5c9b2..dbf951574 100644
--- a/web/xliff/de.xlf
+++ b/web/xliff/de.xlf
@@ -5904,6 +5904,27 @@ Bindings to groups/users are checked against the user of the event.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+