summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/browser/src/helpers/browserSupportsConditionalMediation.ts15
-rw-r--r--packages/browser/src/methods/startAuthentication.ts25
2 files changed, 40 insertions, 0 deletions
diff --git a/packages/browser/src/helpers/browserSupportsConditionalMediation.ts b/packages/browser/src/helpers/browserSupportsConditionalMediation.ts
new file mode 100644
index 0000000..e3fbcea
--- /dev/null
+++ b/packages/browser/src/helpers/browserSupportsConditionalMediation.ts
@@ -0,0 +1,15 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+export async function browserSupportsWebAuthnAutofill(): Promise<boolean> {
+ // Just for Chrome Canary right now; the PublicKeyCredential logic below is the real API
+ // @ts-ignore
+ if (navigator.credentials.conditionalMediationSupported) {
+ return true;
+ }
+
+ return (
+ // @ts-ignore
+ PublicKeyCredential.isConditionalMediationAvailable
+ // @ts-ignore
+ && PublicKeyCredential.isConditionalMediationAvailable()
+ );
+}
diff --git a/packages/browser/src/methods/startAuthentication.ts b/packages/browser/src/methods/startAuthentication.ts
index a08e3a3..a12c8fd 100644
--- a/packages/browser/src/methods/startAuthentication.ts
+++ b/packages/browser/src/methods/startAuthentication.ts
@@ -8,6 +8,7 @@ import bufferToBase64URLString from '../helpers/bufferToBase64URLString';
import base64URLStringToBuffer from '../helpers/base64URLStringToBuffer';
import bufferToUTF8String from '../helpers/bufferToUTF8String';
import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn';
+import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsConditionalMediation';
import toPublicKeyCredentialDescriptor from '../helpers/toPublicKeyCredentialDescriptor';
import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError';
@@ -42,6 +43,30 @@ export default async function startAuthentication(
const options: CredentialRequestOptions = { publicKey };
+ /**
+ * Set up the page to prompt the user to select a credential for authentication via the browser's
+ * input autofill mechanism.
+ */
+ if (supportBrowserAutofill) {
+ if (!(await browserSupportsWebAuthnAutofill())) {
+ throw Error('Browser does not support WebAuthn autofill');
+ }
+
+ // Check for an <input> with "webauthn" in its `autocomplete` attribute
+ const eligibleInputs = document.querySelectorAll("input[autocomplete*='webauthn']");
+
+ // WebAuthn autofill requires at least one valid input
+ if (eligibleInputs.length < 1) {
+ throw Error('No <input> with `"webauthn"` in its `autocomplete` attribute was detected');
+ }
+
+ // `CredentialMediationRequirement` doesn't know about "conditional" yet as of
+ // typescript@4.6.3
+ options.mediation = 'conditional' as CredentialMediationRequirement;
+ // Massage options into a suitable structure
+ delete options.publicKey?.allowCredentials;
+ }
+
// Wait for the user to complete assertion
let credential;
try {