summaryrefslogtreecommitdiffhomepage
path: root/packages/browser/src/methods/startAuthentication.ts
diff options
context:
space:
mode:
authorMatthew Miller <matthew@millerti.me>2022-07-04 08:04:44 -0700
committerGitHub <noreply@github.com>2022-07-04 08:04:44 -0700
commit184cbb4457285817db4ded722d7b54528988e2e0 (patch)
tree3b895f8c273e924dd6fdd52c50fd2528575dc41d /packages/browser/src/methods/startAuthentication.ts
parent524e7f881624f36aa17f406bb25fa23d02449652 (diff)
parent5a5b5a3bdf7c709493fc9e63f0f02eed99f25baf (diff)
Merge pull request #214 from MasterKale/feat/conditional-ui
feat/conditional-ui
Diffstat (limited to 'packages/browser/src/methods/startAuthentication.ts')
-rw-r--r--packages/browser/src/methods/startAuthentication.ts43
1 files changed, 40 insertions, 3 deletions
diff --git a/packages/browser/src/methods/startAuthentication.ts b/packages/browser/src/methods/startAuthentication.ts
index ee401a1..7887228 100644
--- a/packages/browser/src/methods/startAuthentication.ts
+++ b/packages/browser/src/methods/startAuthentication.ts
@@ -8,16 +8,21 @@ import bufferToBase64URLString from '../helpers/bufferToBase64URLString';
import base64URLStringToBuffer from '../helpers/base64URLStringToBuffer';
import bufferToUTF8String from '../helpers/bufferToUTF8String';
import { browserSupportsWebauthn } from '../helpers/browserSupportsWebauthn';
+import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsWebAuthnAutofill';
import toPublicKeyCredentialDescriptor from '../helpers/toPublicKeyCredentialDescriptor';
import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError';
+import { webauthnAbortService } from '../helpers/webAuthnAbortService';
/**
* Begin authenticator "login" via WebAuthn assertion
*
- * @param requestOptionsJSON Output from @simplewebauthn/server's generateAssertionOptions(...)
+ * @param requestOptionsJSON Output from **@simplewebauthn/server**'s generateAssertionOptions(...)
+ * @param useBrowserAutofill Initialize conditional UI to enable logging in via browser
+ * autofill prompts
*/
-export default async function startAuthentication(
+export async function startAuthentication(
requestOptionsJSON: PublicKeyCredentialRequestOptionsJSON,
+ useBrowserAutofill = false,
): Promise<AuthenticationCredentialJSON> {
if (!browserSupportsWebauthn()) {
throw new Error('WebAuthn is not supported in this browser');
@@ -37,7 +42,37 @@ export default async function startAuthentication(
allowCredentials,
};
- const options: CredentialRequestOptions = { publicKey };
+ // Prepare options for `.get()`
+ const options: CredentialRequestOptions = {};
+
+ /**
+ * Set up the page to prompt the user to select a credential for authentication via the browser's
+ * input autofill mechanism.
+ */
+ if (useBrowserAutofill) {
+ 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;
+ // Conditional UI requires an empty allow list
+ publicKey.allowCredentials = [];
+ }
+
+ // Finalize options
+ options.publicKey = publicKey;
+ // Set up the ability to cancel this request if the user attempts another
+ options.signal = webauthnAbortService.createNewAbortSignal();
// Wait for the user to complete assertion
let credential;
@@ -45,6 +80,8 @@ export default async function startAuthentication(
credential = (await navigator.credentials.get(options)) as AuthenticationCredential;
} catch (err) {
throw identifyAuthenticationError({ error: err as Error, options });
+ } finally {
+ webauthnAbortService.reset();
}
if (!credential) {