fix: 修复关闭SSH终端标签页时会话状态未更新的问题

This commit is contained in:
2026-04-18 02:35:38 +08:00
commit 6e2e2f9387
43467 changed files with 5489040 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2020 Matthew Miller
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+64
View File
@@ -0,0 +1,64 @@
# @simplewebauthn/browser <!-- omit in toc -->
![WebAuthn](https://img.shields.io/badge/WebAuthn-Simplified-blueviolet?style=for-the-badge&logo=WebAuthn)
[![npm (scoped)](https://img.shields.io/npm/v/@simplewebauthn/browser?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@simplewebauthn/browser)
[![JSR](https://jsr.io/badges/@simplewebauthn/browser?style=for-the-badge)](https://jsr.io/@simplewebauthn/browser)
![Browser Support](https://img.shields.io/badge/Browser-ES2021+-brightgreen?style=for-the-badge&logo=Mozilla+Firefox)
![Browser Support](https://img.shields.io/badge/Browser-ES5-brightgreen?style=for-the-badge&logo=Mozilla+Firefox)
- [Installation](#installation)
- [Node LTS 20.x and higher](#node-lts-20x-and-higher)
- [Deno v1.43 and higher](#deno-v143-and-higher)
- [UMD](#umd)
- [ES2021](#es2021)
- [ES5](#es5)
- [Documentation](#documentation)
## Installation
This package can be installed from **[NPM](https://www.npmjs.com/package/@simplewebauthn/browser)**
and **[JSR](https://jsr.io/@simplewebauthn/browser)**:
### Node LTS 20.x and higher
```sh
npm install @simplewebauthn/browser
```
### Deno v1.43 and higher
```sh
deno add jsr:@simplewebauthn/browser
```
### UMD
This package can also be installed via **unpkg** by including the following script in your page's
`<head>` element. The library's methods will be available on the global **`SimpleWebAuthnBrowser`**
object.
> NOTE: The only difference between the two packages below is that the ES5 bundle includes some
> polyfills for older browsers. This adds some bundle size overhead, but _does_ enable use of
> `browserSupportsWebAuthn()` in older browsers to show appropriate UI when WebAuthn is unavailable.
#### ES2021
If you only need to support modern browsers, include the `ES2021` version:
```html
<script src="https://unpkg.com/@simplewebauthn/browser/dist/bundle/index.umd.min.js"></script>
```
#### ES5
If you need to support WebAuthn feature detection in deprecated browsers like IE11 and Edge Legacy,
include the `ES5` version:
```html
<script src="https://unpkg.com/@simplewebauthn/browser/dist/bundle/index.es5.umd.min.js"></script>
```
## Documentation
You can find in-depth documentation on this package here:
https://simplewebauthn.dev/docs/packages/browser
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
export declare function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;
//# sourceMappingURL=base64URLStringToBuffer.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"base64URLStringToBuffer.d.ts","sourceRoot":"","sources":["../../src/helpers/base64URLStringToBuffer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAyB5E"}
@@ -0,0 +1,29 @@
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
export function base64URLStringToBuffer(base64URLString) {
// Convert from Base64URL to Base64
const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/');
/**
* Pad with '=' until it's a multiple of four
* (4 - (85 % 4 = 1) = 3) % 4 = 3 padding
* (4 - (86 % 4 = 2) = 2) % 4 = 2 padding
* (4 - (87 % 4 = 3) = 1) % 4 = 1 padding
* (4 - (88 % 4 = 0) = 4) % 4 = 0 padding
*/
const padLength = (4 - (base64.length % 4)) % 4;
const padded = base64.padEnd(base64.length + padLength, '=');
// Convert to a binary string
const binary = atob(padded);
// Convert binary string to buffer
const buffer = new ArrayBuffer(binary.length);
const bytes = new Uint8Array(buffer);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return buffer;
}
@@ -0,0 +1,12 @@
/**
* Determine if the browser is capable of Webauthn
*/
export declare function browserSupportsWebAuthn(): boolean;
/**
* Make it possible to stub the return value during testing
* @ignore Don't include this in docs output
*/
export declare const _browserSupportsWebAuthnInternals: {
stubThis: (value: boolean) => boolean;
};
//# sourceMappingURL=browserSupportsWebAuthn.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"browserSupportsWebAuthn.d.ts","sourceRoot":"","sources":["../../src/helpers/browserSupportsWebAuthn.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAKjD;AAED;;;GAGG;AACH,eAAO,MAAM,iCAAiC;sBAC1B,OAAO;CAC1B,CAAC"}
@@ -0,0 +1,14 @@
/**
* Determine if the browser is capable of Webauthn
*/
export function browserSupportsWebAuthn() {
return _browserSupportsWebAuthnInternals.stubThis(globalThis?.PublicKeyCredential !== undefined &&
typeof globalThis.PublicKeyCredential === 'function');
}
/**
* Make it possible to stub the return value during testing
* @ignore Don't include this in docs output
*/
export const _browserSupportsWebAuthnInternals = {
stubThis: (value) => value,
};
@@ -0,0 +1,9 @@
/**
* Determine if the browser supports conditional UI, so that WebAuthn credentials can
* be shown to the user in the browser's typical password autofill popup.
*/
export declare function browserSupportsWebAuthnAutofill(): Promise<boolean>;
export declare const _browserSupportsWebAuthnAutofillInternals: {
stubThis: (value: Promise<boolean>) => Promise<boolean>;
};
//# sourceMappingURL=browserSupportsWebAuthnAutofill.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"browserSupportsWebAuthnAutofill.d.ts","sourceRoot":"","sources":["../../src/helpers/browserSupportsWebAuthnAutofill.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAAC,OAAO,CAAC,CAyBlE;AAGD,eAAO,MAAM,yCAAyC;sBAClC,OAAO,CAAC,OAAO,CAAC;CACnC,CAAC"}
@@ -0,0 +1,26 @@
import { browserSupportsWebAuthn } from './browserSupportsWebAuthn.js';
/**
* Determine if the browser supports conditional UI, so that WebAuthn credentials can
* be shown to the user in the browser's typical password autofill popup.
*/
export function browserSupportsWebAuthnAutofill() {
if (!browserSupportsWebAuthn()) {
return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
}
/**
* I don't like the `as unknown` here but there's a `declare var PublicKeyCredential` in
* TS' DOM lib that's making it difficult for me to just go `as PublicKeyCredentialFuture` as I
* want. I think I'm fine with this for now since it's _supposed_ to be temporary, until TS types
* have a chance to catch up.
*/
const globalPublicKeyCredential = globalThis
.PublicKeyCredential;
if (globalPublicKeyCredential?.isConditionalMediationAvailable === undefined) {
return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
}
return _browserSupportsWebAuthnAutofillInternals.stubThis(globalPublicKeyCredential.isConditionalMediationAvailable());
}
// Make it possible to stub the return value during testing
export const _browserSupportsWebAuthnAutofillInternals = {
stubThis: (value) => value,
};
@@ -0,0 +1,8 @@
/**
* Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
* credential response ArrayBuffers to string for sending back to the server as JSON.
*
* Helper method to compliment `base64URLStringToBuffer`
*/
export declare function bufferToBase64URLString(buffer: ArrayBuffer): string;
//# sourceMappingURL=bufferToBase64URLString.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"bufferToBase64URLString.d.ts","sourceRoot":"","sources":["../../src/helpers/bufferToBase64URLString.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAWnE"}
@@ -0,0 +1,15 @@
/**
* Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
* credential response ArrayBuffers to string for sending back to the server as JSON.
*
* Helper method to compliment `base64URLStringToBuffer`
*/
export function bufferToBase64URLString(buffer) {
const bytes = new Uint8Array(buffer);
let str = '';
for (const charCode of bytes) {
str += String.fromCharCode(charCode);
}
const base64String = btoa(str);
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
@@ -0,0 +1,9 @@
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.get()`
*/
export declare function identifyAuthenticationError({ error, options, }: {
error: Error;
options: CredentialRequestOptions;
}): WebAuthnError | Error;
//# sourceMappingURL=identifyAuthenticationError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"identifyAuthenticationError.d.ts","sourceRoot":"","sources":["../../src/helpers/identifyAuthenticationError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,wBAAwB,CAAC;CACnC,GAAG,aAAa,GAAG,KAAK,CAuDxB"}
@@ -0,0 +1,61 @@
import { isValidDomain } from './isValidDomain.js';
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.get()`
*/
export function identifyAuthenticationError({ error, options, }) {
const { publicKey } = options;
if (!publicKey) {
throw Error('options was missing required publicKey property');
}
if (error.name === 'AbortError') {
if (options.signal instanceof AbortSignal) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)
return new WebAuthnError({
message: 'Authentication ceremony was sent an abort signal',
code: 'ERROR_CEREMONY_ABORTED',
cause: error,
});
}
}
else if (error.name === 'NotAllowedError') {
/**
* Pass the error directly through. Platforms are overloading this error beyond what the spec
* defines and we don't want to overwrite potentially useful error messages.
*/
return new WebAuthnError({
message: error.message,
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
cause: error,
});
}
else if (error.name === 'SecurityError') {
const effectiveDomain = globalThis.location.hostname;
if (!isValidDomain(effectiveDomain)) {
// https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 5)
return new WebAuthnError({
message: `${globalThis.location.hostname} is an invalid domain`,
code: 'ERROR_INVALID_DOMAIN',
cause: error,
});
}
else if (publicKey.rpId !== effectiveDomain) {
// https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 6)
return new WebAuthnError({
message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
code: 'ERROR_INVALID_RP_ID',
cause: error,
});
}
}
else if (error.name === 'UnknownError') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 1)
// https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 12)
return new WebAuthnError({
message: 'The authenticator was unable to process the specified options, or could not create a new assertion signature',
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
cause: error,
});
}
return error;
}
@@ -0,0 +1,9 @@
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.create()`
*/
export declare function identifyRegistrationError({ error, options, }: {
error: Error;
options: CredentialCreationOptions;
}): WebAuthnError | Error;
//# sourceMappingURL=identifyRegistrationError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"identifyRegistrationError.d.ts","sourceRoot":"","sources":["../../src/helpers/identifyRegistrationError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,yBAAyB,CAAC;CACpC,GAAG,aAAa,GAAG,KAAK,CA4HxB"}
@@ -0,0 +1,126 @@
import { isValidDomain } from './isValidDomain.js';
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.create()`
*/
export function identifyRegistrationError({ error, options, }) {
const { publicKey } = options;
if (!publicKey) {
throw Error('options was missing required publicKey property');
}
if (error.name === 'AbortError') {
if (options.signal instanceof AbortSignal) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)
return new WebAuthnError({
message: 'Registration ceremony was sent an abort signal',
code: 'ERROR_CEREMONY_ABORTED',
cause: error,
});
}
}
else if (error.name === 'ConstraintError') {
if (publicKey.authenticatorSelection?.requireResidentKey === true) {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 4)
return new WebAuthnError({
message: 'Discoverable credentials were required but no available authenticator supported it',
code: 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT',
cause: error,
});
}
else if (
// @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
options.mediation === 'conditional' &&
publicKey.authenticatorSelection?.userVerification === 'required') {
// https://w3c.github.io/webauthn/#sctn-createCredential (Step 22.4)
return new WebAuthnError({
message: 'User verification was required during automatic registration but it could not be performed',
code: 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE',
cause: error,
});
}
else if (publicKey.authenticatorSelection?.userVerification === 'required') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 5)
return new WebAuthnError({
message: 'User verification was required but no available authenticator supported it',
code: 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT',
cause: error,
});
}
}
else if (error.name === 'InvalidStateError') {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 20)
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 3)
return new WebAuthnError({
message: 'The authenticator was previously registered',
code: 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED',
cause: error,
});
}
else if (error.name === 'NotAllowedError') {
/**
* Pass the error directly through. Platforms are overloading this error beyond what the spec
* defines and we don't want to overwrite potentially useful error messages.
*/
return new WebAuthnError({
message: error.message,
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
cause: error,
});
}
else if (error.name === 'NotSupportedError') {
const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === 'public-key');
if (validPubKeyCredParams.length === 0) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 10)
return new WebAuthnError({
message: 'No entry in pubKeyCredParams was of type "public-key"',
code: 'ERROR_MALFORMED_PUBKEYCREDPARAMS',
cause: error,
});
}
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 2)
return new WebAuthnError({
message: 'No available authenticator supported any of the specified pubKeyCredParams algorithms',
code: 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG',
cause: error,
});
}
else if (error.name === 'SecurityError') {
const effectiveDomain = globalThis.location.hostname;
if (!isValidDomain(effectiveDomain)) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 7)
return new WebAuthnError({
message: `${globalThis.location.hostname} is an invalid domain`,
code: 'ERROR_INVALID_DOMAIN',
cause: error,
});
}
else if (publicKey.rp.id !== effectiveDomain) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 8)
return new WebAuthnError({
message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
code: 'ERROR_INVALID_RP_ID',
cause: error,
});
}
}
else if (error.name === 'TypeError') {
if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 5)
return new WebAuthnError({
message: 'User ID was not between 1 and 64 characters',
code: 'ERROR_INVALID_USER_ID_LENGTH',
cause: error,
});
}
}
else if (error.name === 'UnknownError') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 1)
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 8)
return new WebAuthnError({
message: 'The authenticator was unable to process the specified options, or could not create a new credential',
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
cause: error,
});
}
return error;
}
@@ -0,0 +1,10 @@
/**
* A simple test to determine if a hostname is a properly-formatted domain name
*
* A "valid domain" is defined here: https://url.spec.whatwg.org/#valid-domain
*
* Regex was originally sourced from here, then remixed to add punycode support:
* https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
*/
export declare function isValidDomain(hostname: string): boolean;
//# sourceMappingURL=isValidDomain.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"isValidDomain.d.ts","sourceRoot":"","sources":["../../src/helpers/isValidDomain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOvD"}
+15
View File
@@ -0,0 +1,15 @@
/**
* A simple test to determine if a hostname is a properly-formatted domain name
*
* A "valid domain" is defined here: https://url.spec.whatwg.org/#valid-domain
*
* Regex was originally sourced from here, then remixed to add punycode support:
* https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
*/
export function isValidDomain(hostname) {
return (
// Consider localhost valid as well since it's okay wrt Secure Contexts
hostname === 'localhost' ||
// Support punycode (ACE) or ascii labels and domains
/^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(hostname));
}
@@ -0,0 +1,8 @@
/**
* Determine whether the browser can communicate with a built-in authenticator, like
* Touch ID, Android fingerprint scanner, or Windows Hello.
*
* This method will _not_ be able to tell you the name of the platform authenticator.
*/
export declare function platformAuthenticatorIsAvailable(): Promise<boolean>;
//# sourceMappingURL=platformAuthenticatorIsAvailable.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"platformAuthenticatorIsAvailable.d.ts","sourceRoot":"","sources":["../../src/helpers/platformAuthenticatorIsAvailable.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI,OAAO,CAAC,OAAO,CAAC,CAMnE"}
@@ -0,0 +1,13 @@
import { browserSupportsWebAuthn } from './browserSupportsWebAuthn.js';
/**
* Determine whether the browser can communicate with a built-in authenticator, like
* Touch ID, Android fingerprint scanner, or Windows Hello.
*
* This method will _not_ be able to tell you the name of the platform authenticator.
*/
export function platformAuthenticatorIsAvailable() {
if (!browserSupportsWebAuthn()) {
return new Promise((resolve) => resolve(false));
}
return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
}
@@ -0,0 +1,6 @@
import type { AuthenticatorAttachment } from '../types/index.js';
/**
* If possible coerce a `string` value into a known `AuthenticatorAttachment`
*/
export declare function toAuthenticatorAttachment(attachment: string | null): AuthenticatorAttachment | undefined;
//# sourceMappingURL=toAuthenticatorAttachment.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"toAuthenticatorAttachment.d.ts","sourceRoot":"","sources":["../../src/helpers/toAuthenticatorAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAIjE;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,uBAAuB,GAAG,SAAS,CAUrC"}
@@ -0,0 +1,13 @@
const attachments = ['cross-platform', 'platform'];
/**
* If possible coerce a `string` value into a known `AuthenticatorAttachment`
*/
export function toAuthenticatorAttachment(attachment) {
if (!attachment) {
return;
}
if (attachments.indexOf(attachment) < 0) {
return;
}
return attachment;
}
@@ -0,0 +1,3 @@
import type { PublicKeyCredentialDescriptor, PublicKeyCredentialDescriptorJSON } from '../types/index.js';
export declare function toPublicKeyCredentialDescriptor(descriptor: PublicKeyCredentialDescriptorJSON): PublicKeyCredentialDescriptor;
//# sourceMappingURL=toPublicKeyCredentialDescriptor.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"toPublicKeyCredentialDescriptor.d.ts","sourceRoot":"","sources":["../../src/helpers/toPublicKeyCredentialDescriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,iCAAiC,EAClC,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,iCAAiC,GAC5C,6BAA6B,CAa/B"}
@@ -0,0 +1,14 @@
import { base64URLStringToBuffer } from './base64URLStringToBuffer.js';
export function toPublicKeyCredentialDescriptor(descriptor) {
const { id } = descriptor;
return {
...descriptor,
id: base64URLStringToBuffer(id),
/**
* `descriptor.transports` is an array of our `AuthenticatorTransportFuture` that includes newer
* transports that TypeScript's DOM lib is ignorant of. Convince TS that our list of transports
* are fine to pass to WebAuthn since browsers will recognize the new value.
*/
transports: descriptor.transports,
};
}
@@ -0,0 +1,22 @@
interface WebAuthnAbortService {
/**
* Prepare an abort signal that will help support multiple auth attempts without needing to
* reload the page. This is automatically called whenever `startRegistration()` and
* `startAuthentication()` are called.
*/
createNewAbortSignal(): AbortSignal;
/**
* Manually cancel any active WebAuthn registration or authentication attempt.
*/
cancelCeremony(): void;
}
/**
* A service singleton to help ensure that only a single WebAuthn ceremony is active at a time.
*
* Users of **@simplewebauthn/browser** shouldn't typically need to use this, but it can help e.g.
* developers building projects that use client-side routing to better control the behavior of
* their UX in response to router navigation events.
*/
export declare const WebAuthnAbortService: WebAuthnAbortService;
export {};
//# sourceMappingURL=webAuthnAbortService.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"webAuthnAbortService.d.ts","sourceRoot":"","sources":["../../src/helpers/webAuthnAbortService.ts"],"names":[],"mappings":"AAAA,UAAU,oBAAoB;IAC5B;;;;OAIG;IACH,oBAAoB,IAAI,WAAW,CAAC;IACpC;;OAEG;IACH,cAAc,IAAI,IAAI,CAAC;CACxB;AAkCD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,oBAAqD,CAAC"}
@@ -0,0 +1,37 @@
class BaseWebAuthnAbortService {
constructor() {
Object.defineProperty(this, "controller", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
}
createNewAbortSignal() {
// Abort any existing calls to navigator.credentials.create() or navigator.credentials.get()
if (this.controller) {
const abortError = new Error('Cancelling existing WebAuthn API call for new one');
abortError.name = 'AbortError';
this.controller.abort(abortError);
}
const newController = new AbortController();
this.controller = newController;
return newController.signal;
}
cancelCeremony() {
if (this.controller) {
const abortError = new Error('Manually cancelling existing WebAuthn API call');
abortError.name = 'AbortError';
this.controller.abort(abortError);
this.controller = undefined;
}
}
}
/**
* A service singleton to help ensure that only a single WebAuthn ceremony is active at a time.
*
* Users of **@simplewebauthn/browser** shouldn't typically need to use this, but it can help e.g.
* developers building projects that use client-side routing to better control the behavior of
* their UX in response to router navigation events.
*/
export const WebAuthnAbortService = new BaseWebAuthnAbortService();
@@ -0,0 +1,28 @@
/**
* A custom Error used to return a more nuanced error detailing _why_ one of the eight documented
* errors in the spec was raised after calling `navigator.credentials.create()` or
* `navigator.credentials.get()`:
*
* - `AbortError`
* - `ConstraintError`
* - `InvalidStateError`
* - `NotAllowedError`
* - `NotSupportedError`
* - `SecurityError`
* - `TypeError`
* - `UnknownError`
*
* Error messages were determined through investigation of the spec to determine under which
* scenarios a given error would be raised.
*/
export declare class WebAuthnError extends Error {
code: WebAuthnErrorCode;
constructor({ message, code, cause, name, }: {
message: string;
code: WebAuthnErrorCode;
cause: Error;
name?: string;
});
}
export type WebAuthnErrorCode = 'ERROR_CEREMONY_ABORTED' | 'ERROR_INVALID_DOMAIN' | 'ERROR_INVALID_RP_ID' | 'ERROR_INVALID_USER_ID_LENGTH' | 'ERROR_MALFORMED_PUBKEYCREDPARAMS' | 'ERROR_AUTHENTICATOR_GENERAL_ERROR' | 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT' | 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT' | 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED' | 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG' | 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE' | 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY';
//# sourceMappingURL=webAuthnError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"webAuthnError.d.ts","sourceRoot":"","sources":["../../src/helpers/webAuthnError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,IAAI,EAAE,iBAAiB,CAAC;gBAEZ,EACV,OAAO,EACP,IAAI,EACJ,KAAK,EACL,IAAI,GACL,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,iBAAiB,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;CAMF;AAED,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,GACrB,8BAA8B,GAC9B,kCAAkC,GAClC,mCAAmC,GACnC,6DAA6D,GAC7D,uDAAuD,GACvD,2CAA2C,GAC3C,uDAAuD,GACvD,+CAA+C,GAC/C,sCAAsC,CAAC"}
+31
View File
@@ -0,0 +1,31 @@
/**
* A custom Error used to return a more nuanced error detailing _why_ one of the eight documented
* errors in the spec was raised after calling `navigator.credentials.create()` or
* `navigator.credentials.get()`:
*
* - `AbortError`
* - `ConstraintError`
* - `InvalidStateError`
* - `NotAllowedError`
* - `NotSupportedError`
* - `SecurityError`
* - `TypeError`
* - `UnknownError`
*
* Error messages were determined through investigation of the spec to determine under which
* scenarios a given error would be raised.
*/
export class WebAuthnError extends Error {
constructor({ message, code, cause, name, }) {
// @ts-ignore: help Rollup understand that `cause` is okay to set
super(message, { cause });
Object.defineProperty(this, "code", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = name ?? cause.name;
this.code = code;
}
}
+11
View File
@@ -0,0 +1,11 @@
export * from './methods/startRegistration.js';
export * from './methods/startAuthentication.js';
export * from './helpers/browserSupportsWebAuthn.js';
export * from './helpers/platformAuthenticatorIsAvailable.js';
export * from './helpers/browserSupportsWebAuthnAutofill.js';
export * from './helpers/base64URLStringToBuffer.js';
export * from './helpers/bufferToBase64URLString.js';
export * from './helpers/webAuthnAbortService.js';
export * from './helpers/webAuthnError.js';
export * from './types/index.js';
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC"}
+10
View File
@@ -0,0 +1,10 @@
export * from './methods/startRegistration.js';
export * from './methods/startAuthentication.js';
export * from './helpers/browserSupportsWebAuthn.js';
export * from './helpers/platformAuthenticatorIsAvailable.js';
export * from './helpers/browserSupportsWebAuthnAutofill.js';
export * from './helpers/base64URLStringToBuffer.js';
export * from './helpers/bufferToBase64URLString.js';
export * from './helpers/webAuthnAbortService.js';
export * from './helpers/webAuthnError.js';
export * from './types/index.js';
@@ -0,0 +1,15 @@
import type { AuthenticationResponseJSON, PublicKeyCredentialRequestOptionsJSON } from '../types/index.js';
export type StartAuthenticationOpts = Parameters<typeof startAuthentication>[0];
/**
* Begin authenticator "login" via WebAuthn assertion
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateAuthenticationOptions()`
* @param useBrowserAutofill (Optional) Initialize conditional UI to enable logging in via browser autofill prompts. Defaults to `false`.
* @param verifyBrowserAutofillInput (Optional) Ensure a suitable `<input>` element is present when `useBrowserAutofill` is `true`. Defaults to `true`.
*/
export declare function startAuthentication(options: {
optionsJSON: PublicKeyCredentialRequestOptionsJSON;
useBrowserAutofill?: boolean;
verifyBrowserAutofillInput?: boolean;
}): Promise<AuthenticationResponseJSON>;
//# sourceMappingURL=startAuthentication.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"startAuthentication.d.ts","sourceRoot":"","sources":["../../src/methods/startAuthentication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,qCAAqC,EACtC,MAAM,mBAAmB,CAAC;AAU3B,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE;IACP,WAAW,EAAE,qCAAqC,CAAC;IACnD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,GACA,OAAO,CAAC,0BAA0B,CAAC,CA4GrC"}
@@ -0,0 +1,95 @@
import { bufferToBase64URLString } from '../helpers/bufferToBase64URLString.js';
import { base64URLStringToBuffer } from '../helpers/base64URLStringToBuffer.js';
import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn.js';
import { browserSupportsWebAuthnAutofill } from '../helpers/browserSupportsWebAuthnAutofill.js';
import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor.js';
import { identifyAuthenticationError } from '../helpers/identifyAuthenticationError.js';
import { WebAuthnAbortService } from '../helpers/webAuthnAbortService.js';
import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment.js';
/**
* Begin authenticator "login" via WebAuthn assertion
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateAuthenticationOptions()`
* @param useBrowserAutofill (Optional) Initialize conditional UI to enable logging in via browser autofill prompts. Defaults to `false`.
* @param verifyBrowserAutofillInput (Optional) Ensure a suitable `<input>` element is present when `useBrowserAutofill` is `true`. Defaults to `true`.
*/
export async function startAuthentication(options) {
// @ts-ignore: Intentionally check for old call structure to warn about improper API call
if (!options.optionsJSON && options.challenge) {
console.warn('startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.');
// @ts-ignore: Reassign the options, passed in as a positional argument, to the expected variable
options = { optionsJSON: options };
}
const { optionsJSON, useBrowserAutofill = false, verifyBrowserAutofillInput = true, } = options;
if (!browserSupportsWebAuthn()) {
throw new Error('WebAuthn is not supported in this browser');
}
// We need to avoid passing empty array to avoid blocking retrieval
// of public key
let allowCredentials;
if (optionsJSON.allowCredentials?.length !== 0) {
allowCredentials = optionsJSON.allowCredentials?.map(toPublicKeyCredentialDescriptor);
}
// We need to convert some values to Uint8Arrays before passing the credentials to the navigator
const publicKey = {
...optionsJSON,
challenge: base64URLStringToBuffer(optionsJSON.challenge),
allowCredentials,
};
// Prepare options for `.get()`
const getOptions = {};
/**
* 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 && verifyBrowserAutofillInput) {
throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
}
// `CredentialMediationRequirement` doesn't know about "conditional" yet as of
// typescript@4.6.3
getOptions.mediation = 'conditional';
// Conditional UI requires an empty allow list
publicKey.allowCredentials = [];
}
// Finalize options
getOptions.publicKey = publicKey;
// Set up the ability to cancel this request if the user attempts another
getOptions.signal = WebAuthnAbortService.createNewAbortSignal();
// Wait for the user to complete assertion
let credential;
try {
credential = (await navigator.credentials.get(getOptions));
}
catch (err) {
throw identifyAuthenticationError({ error: err, options: getOptions });
}
if (!credential) {
throw new Error('Authentication was not completed');
}
const { id, rawId, response, type } = credential;
let userHandle = undefined;
if (response.userHandle) {
userHandle = bufferToBase64URLString(response.userHandle);
}
// Convert values to base64 to make it easier to send back to the server
return {
id,
rawId: bufferToBase64URLString(rawId),
response: {
authenticatorData: bufferToBase64URLString(response.authenticatorData),
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
signature: bufferToBase64URLString(response.signature),
userHandle,
},
type,
clientExtensionResults: credential.getClientExtensionResults(),
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
};
}
@@ -0,0 +1,13 @@
import type { PublicKeyCredentialCreationOptionsJSON, RegistrationResponseJSON } from '../types/index.js';
export type StartRegistrationOpts = Parameters<typeof startRegistration>[0];
/**
* Begin authenticator "registration" via WebAuthn attestation
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateRegistrationOptions()`
* @param useAutoRegister (Optional) Try to silently create a passkey with the password manager that the user just signed in with. Defaults to `false`.
*/
export declare function startRegistration(options: {
optionsJSON: PublicKeyCredentialCreationOptionsJSON;
useAutoRegister?: boolean;
}): Promise<RegistrationResponseJSON>;
//# sourceMappingURL=startRegistration.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"startRegistration.d.ts","sourceRoot":"","sources":["../../src/methods/startRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,sCAAsC,EAEtC,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAS3B,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5E;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE;IACP,WAAW,EAAE,sCAAsC,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GACA,OAAO,CAAC,wBAAwB,CAAC,CAuHnC"}
@@ -0,0 +1,121 @@
import { bufferToBase64URLString } from '../helpers/bufferToBase64URLString.js';
import { base64URLStringToBuffer } from '../helpers/base64URLStringToBuffer.js';
import { browserSupportsWebAuthn } from '../helpers/browserSupportsWebAuthn.js';
import { toPublicKeyCredentialDescriptor } from '../helpers/toPublicKeyCredentialDescriptor.js';
import { identifyRegistrationError } from '../helpers/identifyRegistrationError.js';
import { WebAuthnAbortService } from '../helpers/webAuthnAbortService.js';
import { toAuthenticatorAttachment } from '../helpers/toAuthenticatorAttachment.js';
/**
* Begin authenticator "registration" via WebAuthn attestation
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateRegistrationOptions()`
* @param useAutoRegister (Optional) Try to silently create a passkey with the password manager that the user just signed in with. Defaults to `false`.
*/
export async function startRegistration(options) {
// @ts-ignore: Intentionally check for old call structure to warn about improper API call
if (!options.optionsJSON && options.challenge) {
console.warn('startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.');
// @ts-ignore: Reassign the options, passed in as a positional argument, to the expected variable
options = { optionsJSON: options };
}
const { optionsJSON, useAutoRegister = false } = options;
if (!browserSupportsWebAuthn()) {
throw new Error('WebAuthn is not supported in this browser');
}
// We need to convert some values to Uint8Arrays before passing the credentials to the navigator
const publicKey = {
...optionsJSON,
challenge: base64URLStringToBuffer(optionsJSON.challenge),
user: {
...optionsJSON.user,
id: base64URLStringToBuffer(optionsJSON.user.id),
},
excludeCredentials: optionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor),
};
// Prepare options for `.create()`
const createOptions = {};
/**
* Try to use conditional create to register a passkey for the user with the password manager
* the user just used to authenticate with. The user won't be shown any prominent UI by the
* browser.
*/
if (useAutoRegister) {
// @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
createOptions.mediation = 'conditional';
}
// Finalize options
createOptions.publicKey = publicKey;
// Set up the ability to cancel this request if the user attempts another
createOptions.signal = WebAuthnAbortService.createNewAbortSignal();
// Wait for the user to complete attestation
let credential;
try {
credential = (await navigator.credentials.create(createOptions));
}
catch (err) {
throw identifyRegistrationError({ error: err, options: createOptions });
}
if (!credential) {
throw new Error('Registration was not completed');
}
const { id, rawId, response, type } = credential;
// Continue to play it safe with `getTransports()` for now, even when L3 types say it's required
let transports = undefined;
if (typeof response.getTransports === 'function') {
transports = response.getTransports();
}
// L3 says this is required, but browser and webview support are still not guaranteed.
let responsePublicKeyAlgorithm = undefined;
if (typeof response.getPublicKeyAlgorithm === 'function') {
try {
responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
}
catch (error) {
warnOnBrokenImplementation('getPublicKeyAlgorithm()', error);
}
}
let responsePublicKey = undefined;
if (typeof response.getPublicKey === 'function') {
try {
const _publicKey = response.getPublicKey();
if (_publicKey !== null) {
responsePublicKey = bufferToBase64URLString(_publicKey);
}
}
catch (error) {
warnOnBrokenImplementation('getPublicKey()', error);
}
}
// L3 says this is required, but browser and webview support are still not guaranteed.
let responseAuthenticatorData;
if (typeof response.getAuthenticatorData === 'function') {
try {
responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData());
}
catch (error) {
warnOnBrokenImplementation('getAuthenticatorData()', error);
}
}
return {
id,
rawId: bufferToBase64URLString(rawId),
response: {
attestationObject: bufferToBase64URLString(response.attestationObject),
clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
transports,
publicKeyAlgorithm: responsePublicKeyAlgorithm,
publicKey: responsePublicKey,
authenticatorData: responseAuthenticatorData,
},
type,
clientExtensionResults: credential.getClientExtensionResults(),
authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment),
};
}
/**
* Visibly warn when we detect an issue related to a passkey provider intercepting WebAuthn API
* calls
*/
function warnOnBrokenImplementation(methodName, cause) {
console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.\n`, cause);
}
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
+329
View File
@@ -0,0 +1,329 @@
/**
* DO NOT MODIFY THESE FILES!
*
* These files were copied from the **types** package. To update this file, make changes to those
* files instead and then run the following command from the monorepo root folder:
*
* deno task codegen:types
*/
/**
* Generated from typescript@5.6.3
* To regenerate, run the following command from the package root:
* deno task extract-dom-types
*/
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAssertionResponse)
*/
export interface AuthenticatorAssertionResponse extends AuthenticatorResponse {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAssertionResponse/authenticatorData) */
readonly authenticatorData: ArrayBuffer;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAssertionResponse/signature) */
readonly signature: ArrayBuffer;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAssertionResponse/userHandle) */
readonly userHandle: ArrayBuffer | null;
}
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse)
*/
export interface AuthenticatorAttestationResponse extends AuthenticatorResponse {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse/attestationObject) */
readonly attestationObject: ArrayBuffer;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse/getAuthenticatorData) */
getAuthenticatorData(): ArrayBuffer;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse/getPublicKey) */
getPublicKey(): ArrayBuffer | null;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse/getPublicKeyAlgorithm) */
getPublicKeyAlgorithm(): COSEAlgorithmIdentifier;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorAttestationResponse/getTransports) */
getTransports(): string[];
}
export interface AuthenticationExtensionsClientInputs {
appid?: string;
credProps?: boolean;
hmacCreateSecret?: boolean;
minPinLength?: boolean;
}
export interface AuthenticationExtensionsClientOutputs {
appid?: boolean;
credProps?: CredentialPropertiesOutput;
hmacCreateSecret?: boolean;
}
export interface AuthenticatorSelectionCriteria {
authenticatorAttachment?: AuthenticatorAttachment;
requireResidentKey?: boolean;
residentKey?: ResidentKeyRequirement;
userVerification?: UserVerificationRequirement;
}
/**
* Basic cryptography features available in the current context. It allows access to a cryptographically strong random number generator and to cryptographic primitives.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto)
*/
export interface Crypto {
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/subtle)
*/
readonly subtle: SubtleCrypto;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/getRandomValues) */
getRandomValues<T extends ArrayBufferView | null>(array: T): T;
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Crypto/randomUUID)
*/
randomUUID(): `${string}-${string}-${string}-${string}-${string}`;
}
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential)
*/
export interface PublicKeyCredential extends Credential {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/authenticatorAttachment) */
readonly authenticatorAttachment: string | null;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/rawId) */
readonly rawId: ArrayBuffer;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/response) */
readonly response: AuthenticatorResponse;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/PublicKeyCredential/getClientExtensionResults) */
getClientExtensionResults(): AuthenticationExtensionsClientOutputs;
}
export interface PublicKeyCredentialCreationOptions {
attestation?: AttestationConveyancePreference;
authenticatorSelection?: AuthenticatorSelectionCriteria;
challenge: BufferSource;
excludeCredentials?: PublicKeyCredentialDescriptor[];
extensions?: AuthenticationExtensionsClientInputs;
pubKeyCredParams: PublicKeyCredentialParameters[];
rp: PublicKeyCredentialRpEntity;
timeout?: number;
user: PublicKeyCredentialUserEntity;
}
export interface PublicKeyCredentialDescriptor {
id: BufferSource;
transports?: AuthenticatorTransport[];
type: PublicKeyCredentialType;
}
export interface PublicKeyCredentialParameters {
alg: COSEAlgorithmIdentifier;
type: PublicKeyCredentialType;
}
export interface PublicKeyCredentialRequestOptions {
allowCredentials?: PublicKeyCredentialDescriptor[];
challenge: BufferSource;
extensions?: AuthenticationExtensionsClientInputs;
rpId?: string;
timeout?: number;
userVerification?: UserVerificationRequirement;
}
export interface PublicKeyCredentialUserEntity extends PublicKeyCredentialEntity {
displayName: string;
id: BufferSource;
}
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorResponse)
*/
export interface AuthenticatorResponse {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/AuthenticatorResponse/clientDataJSON) */
readonly clientDataJSON: ArrayBuffer;
}
export interface CredentialPropertiesOutput {
rk?: boolean;
}
/**
* This Web Crypto API interface provides a number of low-level cryptographic functions. It is accessed via the Crypto.subtle properties available in a window context (via Window.crypto).
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto)
*/
export interface SubtleCrypto {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/decrypt) */
decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/deriveBits) */
deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/deriveKey) */
deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/digest) */
digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise<ArrayBuffer>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/encrypt) */
encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/exportKey) */
exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>;
exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>;
exportKey(format: KeyFormat, key: CryptoKey): Promise<ArrayBuffer | JsonWebKey>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/generateKey) */
generateKey(algorithm: "Ed25519", extractable: boolean, keyUsages: ReadonlyArray<"sign" | "verify">): Promise<CryptoKeyPair>;
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>;
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair | CryptoKey>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/importKey) */
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/sign) */
sign(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/unwrapKey) */
unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/verify) */
verify(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, signature: BufferSource, data: BufferSource): Promise<boolean>;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/SubtleCrypto/wrapKey) */
wrapKey(format: KeyFormat, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams): Promise<ArrayBuffer>;
}
/**
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Credential)
*/
export interface Credential {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Credential/id) */
readonly id: string;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Credential/type) */
readonly type: string;
}
export interface PublicKeyCredentialRpEntity extends PublicKeyCredentialEntity {
id?: string;
}
export interface PublicKeyCredentialEntity {
name: string;
}
export interface RsaOaepParams extends Algorithm {
label?: BufferSource;
}
export interface AesCtrParams extends Algorithm {
counter: BufferSource;
length: number;
}
export interface AesCbcParams extends Algorithm {
iv: BufferSource;
}
export interface AesGcmParams extends Algorithm {
additionalData?: BufferSource;
iv: BufferSource;
tagLength?: number;
}
/**
* The CryptoKey dictionary of the Web Crypto API represents a cryptographic key.
* Available only in secure contexts.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/CryptoKey)
*/
export interface CryptoKey {
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CryptoKey/algorithm) */
readonly algorithm: KeyAlgorithm;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CryptoKey/extractable) */
readonly extractable: boolean;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CryptoKey/type) */
readonly type: KeyType;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CryptoKey/usages) */
readonly usages: KeyUsage[];
}
export interface EcdhKeyDeriveParams extends Algorithm {
public: CryptoKey;
}
export interface HkdfParams extends Algorithm {
hash: HashAlgorithmIdentifier;
info: BufferSource;
salt: BufferSource;
}
export interface Pbkdf2Params extends Algorithm {
hash: HashAlgorithmIdentifier;
iterations: number;
salt: BufferSource;
}
export interface AesDerivedKeyParams extends Algorithm {
length: number;
}
export interface HmacImportParams extends Algorithm {
hash: HashAlgorithmIdentifier;
length?: number;
}
export interface JsonWebKey {
alg?: string;
crv?: string;
d?: string;
dp?: string;
dq?: string;
e?: string;
ext?: boolean;
k?: string;
key_ops?: string[];
kty?: string;
n?: string;
oth?: RsaOtherPrimesInfo[];
p?: string;
q?: string;
qi?: string;
use?: string;
x?: string;
y?: string;
}
export interface CryptoKeyPair {
privateKey: CryptoKey;
publicKey: CryptoKey;
}
export interface RsaHashedKeyGenParams extends RsaKeyGenParams {
hash: HashAlgorithmIdentifier;
}
export interface EcKeyGenParams extends Algorithm {
namedCurve: NamedCurve;
}
export interface AesKeyGenParams extends Algorithm {
length: number;
}
export interface HmacKeyGenParams extends Algorithm {
hash: HashAlgorithmIdentifier;
length?: number;
}
export interface RsaHashedImportParams extends Algorithm {
hash: HashAlgorithmIdentifier;
}
export interface EcKeyImportParams extends Algorithm {
namedCurve: NamedCurve;
}
export interface AesKeyAlgorithm extends KeyAlgorithm {
length: number;
}
export interface RsaPssParams extends Algorithm {
saltLength: number;
}
export interface EcdsaParams extends Algorithm {
hash: HashAlgorithmIdentifier;
}
export interface Algorithm {
name: string;
}
export interface KeyAlgorithm {
name: string;
}
export interface RsaOtherPrimesInfo {
d?: string;
r?: string;
t?: string;
}
export interface RsaKeyGenParams extends Algorithm {
modulusLength: number;
publicExponent: BigInteger;
}
export type AttestationConveyancePreference = "direct" | "enterprise" | "indirect" | "none";
export type AuthenticatorTransport = "ble" | "hybrid" | "internal" | "nfc" | "usb";
export type COSEAlgorithmIdentifier = number;
export type ResidentKeyRequirement = "discouraged" | "preferred" | "required";
export type UserVerificationRequirement = "discouraged" | "preferred" | "required";
export type AuthenticatorAttachment = "cross-platform" | "platform";
export type BufferSource = ArrayBufferView | ArrayBuffer;
export type PublicKeyCredentialType = "public-key";
export type AlgorithmIdentifier = Algorithm | string;
export type KeyUsage = "decrypt" | "deriveBits" | "deriveKey" | "encrypt" | "sign" | "unwrapKey" | "verify" | "wrapKey";
export type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki";
export type KeyType = "private" | "public" | "secret";
export type HashAlgorithmIdentifier = AlgorithmIdentifier;
export type NamedCurve = string;
export type BigInteger = Uint8Array;
//# sourceMappingURL=dom.d.ts.map
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
export {};
+220
View File
@@ -0,0 +1,220 @@
/**
* DO NOT MODIFY THESE FILES!
*
* These files were copied from the **types** package. To update this file, make changes to those
* files instead and then run the following command from the monorepo root folder:
*
* deno task codegen:types
*/
import type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponse, AuthenticatorAttachment, AuthenticatorAttestationResponse, AuthenticatorSelectionCriteria, COSEAlgorithmIdentifier, PublicKeyCredential, PublicKeyCredentialCreationOptions, PublicKeyCredentialDescriptor, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptions, PublicKeyCredentialRpEntity, PublicKeyCredentialType, UserVerificationRequirement } from './dom.js';
export type { AttestationConveyancePreference, AuthenticationExtensionsClientInputs, AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponse, AuthenticatorAttachment, AuthenticatorAttestationResponse, AuthenticatorSelectionCriteria, AuthenticatorTransport, COSEAlgorithmIdentifier, Crypto, PublicKeyCredential, PublicKeyCredentialCreationOptions, PublicKeyCredentialDescriptor, PublicKeyCredentialParameters, PublicKeyCredentialRequestOptions, PublicKeyCredentialRpEntity, PublicKeyCredentialType, PublicKeyCredentialUserEntity, ResidentKeyRequirement, UserVerificationRequirement, } from './dom.js';
/**
* A variant of PublicKeyCredentialCreationOptions suitable for JSON transmission to the browser to
* (eventually) get passed into navigator.credentials.create(...) in the browser.
*
* This should eventually get replaced with official TypeScript DOM types when WebAuthn L3 types
* eventually make it into the language:
*
* https://w3c.github.io/webauthn/#dictdef-publickeycredentialcreationoptionsjson
*/
export interface PublicKeyCredentialCreationOptionsJSON {
rp: PublicKeyCredentialRpEntity;
user: PublicKeyCredentialUserEntityJSON;
challenge: Base64URLString;
pubKeyCredParams: PublicKeyCredentialParameters[];
timeout?: number;
excludeCredentials?: PublicKeyCredentialDescriptorJSON[];
authenticatorSelection?: AuthenticatorSelectionCriteria;
hints?: PublicKeyCredentialHint[];
attestation?: AttestationConveyancePreference;
attestationFormats?: AttestationFormat[];
extensions?: AuthenticationExtensionsClientInputs;
}
/**
* A variant of PublicKeyCredentialRequestOptions suitable for JSON transmission to the browser to
* (eventually) get passed into navigator.credentials.get(...) in the browser.
*/
export interface PublicKeyCredentialRequestOptionsJSON {
challenge: Base64URLString;
timeout?: number;
rpId?: string;
allowCredentials?: PublicKeyCredentialDescriptorJSON[];
userVerification?: UserVerificationRequirement;
hints?: PublicKeyCredentialHint[];
extensions?: AuthenticationExtensionsClientInputs;
}
/**
* https://w3c.github.io/webauthn/#dictdef-publickeycredentialdescriptorjson
*/
export interface PublicKeyCredentialDescriptorJSON {
id: Base64URLString;
type: PublicKeyCredentialType;
transports?: AuthenticatorTransportFuture[];
}
/**
* https://w3c.github.io/webauthn/#dictdef-publickeycredentialuserentityjson
*/
export interface PublicKeyCredentialUserEntityJSON {
id: string;
name: string;
displayName: string;
}
/**
* The value returned from navigator.credentials.create()
*/
export interface RegistrationCredential extends PublicKeyCredentialFuture {
response: AuthenticatorAttestationResponseFuture;
}
/**
* A slightly-modified RegistrationCredential to simplify working with ArrayBuffers that
* are Base64URL-encoded in the browser so that they can be sent as JSON to the server.
*
* https://w3c.github.io/webauthn/#dictdef-registrationresponsejson
*/
export interface RegistrationResponseJSON {
id: Base64URLString;
rawId: Base64URLString;
response: AuthenticatorAttestationResponseJSON;
authenticatorAttachment?: AuthenticatorAttachment;
clientExtensionResults: AuthenticationExtensionsClientOutputs;
type: PublicKeyCredentialType;
}
/**
* The value returned from navigator.credentials.get()
*/
export interface AuthenticationCredential extends PublicKeyCredentialFuture {
response: AuthenticatorAssertionResponse;
}
/**
* A slightly-modified AuthenticationCredential to simplify working with ArrayBuffers that
* are Base64URL-encoded in the browser so that they can be sent as JSON to the server.
*
* https://w3c.github.io/webauthn/#dictdef-authenticationresponsejson
*/
export interface AuthenticationResponseJSON {
id: Base64URLString;
rawId: Base64URLString;
response: AuthenticatorAssertionResponseJSON;
authenticatorAttachment?: AuthenticatorAttachment;
clientExtensionResults: AuthenticationExtensionsClientOutputs;
type: PublicKeyCredentialType;
}
/**
* A slightly-modified AuthenticatorAttestationResponse to simplify working with ArrayBuffers that
* are Base64URL-encoded in the browser so that they can be sent as JSON to the server.
*
* https://w3c.github.io/webauthn/#dictdef-authenticatorattestationresponsejson
*/
export interface AuthenticatorAttestationResponseJSON {
clientDataJSON: Base64URLString;
attestationObject: Base64URLString;
authenticatorData?: Base64URLString;
transports?: AuthenticatorTransportFuture[];
publicKeyAlgorithm?: COSEAlgorithmIdentifier;
publicKey?: Base64URLString;
}
/**
* A slightly-modified AuthenticatorAssertionResponse to simplify working with ArrayBuffers that
* are Base64URL-encoded in the browser so that they can be sent as JSON to the server.
*
* https://w3c.github.io/webauthn/#dictdef-authenticatorassertionresponsejson
*/
export interface AuthenticatorAssertionResponseJSON {
clientDataJSON: Base64URLString;
authenticatorData: Base64URLString;
signature: Base64URLString;
userHandle?: Base64URLString;
}
/**
* Public key credential information needed to verify authentication responses
*/
export type WebAuthnCredential = {
id: Base64URLString;
publicKey: Uint8Array_;
counter: number;
transports?: AuthenticatorTransportFuture[];
};
/**
* An attempt to communicate that this isn't just any string, but a Base64URL-encoded string
*/
export type Base64URLString = string;
/**
* AuthenticatorAttestationResponse in TypeScript's DOM lib is outdated (up through v3.9.7).
* Maintain an augmented version here so we can implement additional properties as the WebAuthn
* spec evolves.
*
* See https://www.w3.org/TR/webauthn-2/#iface-authenticatorattestationresponse
*
* Properties marked optional are not supported in all browsers.
*/
export interface AuthenticatorAttestationResponseFuture extends AuthenticatorAttestationResponse {
getTransports(): AuthenticatorTransportFuture[];
}
/**
* A super class of TypeScript's `AuthenticatorTransport` that includes support for the latest
* transports. Should eventually be replaced by TypeScript's when TypeScript gets updated to
* know about it (sometime after 4.6.3)
*/
export type AuthenticatorTransportFuture = 'ble' | 'cable' | 'hybrid' | 'internal' | 'nfc' | 'smart-card' | 'usb';
/**
* A super class of TypeScript's `PublicKeyCredentialDescriptor` that knows about the latest
* transports. Should eventually be replaced by TypeScript's when TypeScript gets updated to
* know about it (sometime after 4.6.3)
*/
export interface PublicKeyCredentialDescriptorFuture extends Omit<PublicKeyCredentialDescriptor, 'transports'> {
transports?: AuthenticatorTransportFuture[];
}
/** */
export type PublicKeyCredentialJSON = RegistrationResponseJSON | AuthenticationResponseJSON;
/**
* A super class of TypeScript's `PublicKeyCredential` that knows about upcoming WebAuthn features
*/
export interface PublicKeyCredentialFuture extends PublicKeyCredential {
type: PublicKeyCredentialType;
isConditionalMediationAvailable?(): Promise<boolean>;
parseCreationOptionsFromJSON?(options: PublicKeyCredentialCreationOptionsJSON): PublicKeyCredentialCreationOptions;
parseRequestOptionsFromJSON?(options: PublicKeyCredentialRequestOptionsJSON): PublicKeyCredentialRequestOptions;
toJSON?(): PublicKeyCredentialJSON;
}
/**
* The two types of credentials as defined by bit 3 ("Backup Eligibility") in authenticator data:
* - `"singleDevice"` credentials will never be backed up
* - `"multiDevice"` credentials can be backed up
*/
export type CredentialDeviceType = 'singleDevice' | 'multiDevice';
/**
* Categories of authenticators that Relying Parties can pass along to browsers during
* registration. Browsers that understand these values can optimize their modal experience to
* start the user off in a particular registration flow:
*
* - `hybrid`: A platform authenticator on a mobile device
* - `security-key`: A portable FIDO2 authenticator capable of being used on multiple devices via a USB or NFC connection
* - `client-device`: The device that WebAuthn is being called on. Typically synonymous with platform authenticators
*
* See https://w3c.github.io/webauthn/#enumdef-publickeycredentialhint
*
* These values are less strict than `authenticatorAttachment`
*/
export type PublicKeyCredentialHint = 'hybrid' | 'security-key' | 'client-device';
/**
* Values for an attestation object's `fmt`
*
* See https://www.iana.org/assignments/webauthn/webauthn.xhtml#webauthn-attestation-statement-format-ids
*/
export type AttestationFormat = 'fido-u2f' | 'packed' | 'android-safetynet' | 'android-key' | 'tpm' | 'apple' | 'none';
/**
* Equivalent to `Uint8Array` before TypeScript 5.7, and `Uint8Array<ArrayBuffer>` in TypeScript 5.7
* and beyond.
*
* **Context**
*
* `Uint8Array` became a generic type in TypeScript 5.7, requiring types defined simply as
* `Uint8Array` to be refactored to `Uint8Array<ArrayBuffer>` starting in Deno 2.2. `Uint8Array` is
* _not_ generic in Deno 2.1.x and earlier, though, so this type helps bridge this gap.
*
* Inspired by Deno's std library:
*
* https://github.com/denoland/std/blob/b5a5fe4f96b91c1fe8dba5cc0270092dd11d3287/bytes/_types.ts#L11
*/
export type Uint8Array_ = ReturnType<Uint8Array['slice']>;
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,+BAA+B,EAC/B,oCAAoC,EACpC,qCAAqC,EACrC,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,8BAA8B,EAC9B,uBAAuB,EACvB,mBAAmB,EACnB,kCAAkC,EAClC,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,+BAA+B,EAC/B,oCAAoC,EACpC,qCAAqC,EACrC,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,8BAA8B,EAC9B,sBAAsB,EACtB,uBAAuB,EACvB,MAAM,EACN,mBAAmB,EACnB,kCAAkC,EAClC,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC7B,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,UAAU,CAAC;AAElB;;;;;;;;GAQG;AACH,MAAM,WAAW,sCAAsC;IACrD,EAAE,EAAE,2BAA2B,CAAC;IAChC,IAAI,EAAE,iCAAiC,CAAC;IACxC,SAAS,EAAE,eAAe,CAAC;IAC3B,gBAAgB,EAAE,6BAA6B,EAAE,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,iCAAiC,EAAE,CAAC;IACzD,sBAAsB,CAAC,EAAE,8BAA8B,CAAC;IACxD,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,+BAA+B,CAAC;IAC9C,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,UAAU,CAAC,EAAE,oCAAoC,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,WAAW,qCAAqC;IACpD,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,iCAAiC,EAAE,CAAC;IACvD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,oCAAoC,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,EAAE,EAAE,eAAe,CAAC;IACpB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,yBAAyB;IACvE,QAAQ,EAAE,sCAAsC,CAAC;CAClD;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,eAAe,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,oCAAoC,CAAC;IAC/C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,sBAAsB,EAAE,qCAAqC,CAAC;IAC9D,IAAI,EAAE,uBAAuB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,yBAAyB;IACzE,QAAQ,EAAE,8BAA8B,CAAC;CAC1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,eAAe,CAAC;IACpB,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,kCAAkC,CAAC;IAC7C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,sBAAsB,EAAE,qCAAqC,CAAC;IAC9D,IAAI,EAAE,uBAAuB,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oCAAoC;IACnD,cAAc,EAAE,eAAe,CAAC;IAChC,iBAAiB,EAAE,eAAe,CAAC;IAEnC,iBAAiB,CAAC,EAAE,eAAe,CAAC;IAEpC,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;IAE5C,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kCAAkC;IACjD,cAAc,EAAE,eAAe,CAAC;IAChC,iBAAiB,EAAE,eAAe,CAAC;IACnC,SAAS,EAAE,eAAe,CAAC;IAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,eAAe,CAAC;IACpB,SAAS,EAAE,WAAW,CAAC;IAEvB,OAAO,EAAE,MAAM,CAAC;IAEhB,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,WAAW,sCAAuC,SAAQ,gCAAgC;IAC9F,aAAa,IAAI,4BAA4B,EAAE,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,MAAM,4BAA4B,GACpC,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,KAAK,GACL,YAAY,GACZ,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,WAAW,mCACf,SAAQ,IAAI,CAAC,6BAA6B,EAAE,YAAY,CAAC;IACzD,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C;AAED,MAAM;AACN,MAAM,MAAM,uBAAuB,GAC/B,wBAAwB,GACxB,0BAA0B,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE,IAAI,EAAE,uBAAuB,CAAC;IAE9B,+BAA+B,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAErD,4BAA4B,CAAC,CAC3B,OAAO,EAAE,sCAAsC,GAC9C,kCAAkC,CAAC;IAEtC,2BAA2B,CAAC,CAC1B,OAAO,EAAE,qCAAqC,GAC7C,iCAAiC,CAAC;IAErC,MAAM,CAAC,IAAI,uBAAuB,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,aAAa,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,cAAc,GAAG,eAAe,CAAC;AAElF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,QAAQ,GACR,mBAAmB,GACnB,aAAa,GACb,KAAK,GACL,OAAO,GACP,MAAM,CAAC;AAEX;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC"}
+1
View File
@@ -0,0 +1 @@
export {};
+40
View File
@@ -0,0 +1,40 @@
{
"name": "@simplewebauthn/browser",
"version": "13.3.0",
"description": "SimpleWebAuthn for Browsers",
"keywords": [
"typescript",
"webauthn",
"passkeys",
"fido",
"umd"
],
"author": "Matthew Miller <matthew@millerti.me>",
"homepage": "https://github.com/MasterKale/SimpleWebAuthn/tree/master/packages/browser#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/MasterKale/SimpleWebAuthn.git",
"directory": "packages/browser"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/MasterKale/SimpleWebAuthn/issues"
},
"main": "./script/index.js",
"module": "./esm/index.js",
"exports": {
".": {
"import": "./esm/index.js",
"require": "./script/index.js"
}
},
"publishConfig": {
"access": "public"
},
"unpkg": "dist/bundle/index.umd.min.js",
"dependencies": {},
"devDependencies": {
"@types/node": "^20.9.0"
},
"_generatedBy": "dnt@dev"
}
@@ -0,0 +1,9 @@
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
export declare function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;
//# sourceMappingURL=base64URLStringToBuffer.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"base64URLStringToBuffer.d.ts","sourceRoot":"","sources":["../../src/helpers/base64URLStringToBuffer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAyB5E"}
@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.base64URLStringToBuffer = base64URLStringToBuffer;
/**
* Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
* excludeCredentials
*
* Helper method to compliment `bufferToBase64URLString`
*/
function base64URLStringToBuffer(base64URLString) {
// Convert from Base64URL to Base64
const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/');
/**
* Pad with '=' until it's a multiple of four
* (4 - (85 % 4 = 1) = 3) % 4 = 3 padding
* (4 - (86 % 4 = 2) = 2) % 4 = 2 padding
* (4 - (87 % 4 = 3) = 1) % 4 = 1 padding
* (4 - (88 % 4 = 0) = 4) % 4 = 0 padding
*/
const padLength = (4 - (base64.length % 4)) % 4;
const padded = base64.padEnd(base64.length + padLength, '=');
// Convert to a binary string
const binary = atob(padded);
// Convert binary string to buffer
const buffer = new ArrayBuffer(binary.length);
const bytes = new Uint8Array(buffer);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return buffer;
}
@@ -0,0 +1,12 @@
/**
* Determine if the browser is capable of Webauthn
*/
export declare function browserSupportsWebAuthn(): boolean;
/**
* Make it possible to stub the return value during testing
* @ignore Don't include this in docs output
*/
export declare const _browserSupportsWebAuthnInternals: {
stubThis: (value: boolean) => boolean;
};
//# sourceMappingURL=browserSupportsWebAuthn.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"browserSupportsWebAuthn.d.ts","sourceRoot":"","sources":["../../src/helpers/browserSupportsWebAuthn.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAKjD;AAED;;;GAGG;AACH,eAAO,MAAM,iCAAiC;sBAC1B,OAAO;CAC1B,CAAC"}
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports._browserSupportsWebAuthnInternals = void 0;
exports.browserSupportsWebAuthn = browserSupportsWebAuthn;
/**
* Determine if the browser is capable of Webauthn
*/
function browserSupportsWebAuthn() {
return exports._browserSupportsWebAuthnInternals.stubThis(globalThis?.PublicKeyCredential !== undefined &&
typeof globalThis.PublicKeyCredential === 'function');
}
/**
* Make it possible to stub the return value during testing
* @ignore Don't include this in docs output
*/
exports._browserSupportsWebAuthnInternals = {
stubThis: (value) => value,
};
@@ -0,0 +1,9 @@
/**
* Determine if the browser supports conditional UI, so that WebAuthn credentials can
* be shown to the user in the browser's typical password autofill popup.
*/
export declare function browserSupportsWebAuthnAutofill(): Promise<boolean>;
export declare const _browserSupportsWebAuthnAutofillInternals: {
stubThis: (value: Promise<boolean>) => Promise<boolean>;
};
//# sourceMappingURL=browserSupportsWebAuthnAutofill.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"browserSupportsWebAuthnAutofill.d.ts","sourceRoot":"","sources":["../../src/helpers/browserSupportsWebAuthnAutofill.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CAAC,OAAO,CAAC,CAyBlE;AAGD,eAAO,MAAM,yCAAyC;sBAClC,OAAO,CAAC,OAAO,CAAC;CACnC,CAAC"}
@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports._browserSupportsWebAuthnAutofillInternals = void 0;
exports.browserSupportsWebAuthnAutofill = browserSupportsWebAuthnAutofill;
const browserSupportsWebAuthn_js_1 = require("./browserSupportsWebAuthn.js");
/**
* Determine if the browser supports conditional UI, so that WebAuthn credentials can
* be shown to the user in the browser's typical password autofill popup.
*/
function browserSupportsWebAuthnAutofill() {
if (!(0, browserSupportsWebAuthn_js_1.browserSupportsWebAuthn)()) {
return exports._browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
}
/**
* I don't like the `as unknown` here but there's a `declare var PublicKeyCredential` in
* TS' DOM lib that's making it difficult for me to just go `as PublicKeyCredentialFuture` as I
* want. I think I'm fine with this for now since it's _supposed_ to be temporary, until TS types
* have a chance to catch up.
*/
const globalPublicKeyCredential = globalThis
.PublicKeyCredential;
if (globalPublicKeyCredential?.isConditionalMediationAvailable === undefined) {
return exports._browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
}
return exports._browserSupportsWebAuthnAutofillInternals.stubThis(globalPublicKeyCredential.isConditionalMediationAvailable());
}
// Make it possible to stub the return value during testing
exports._browserSupportsWebAuthnAutofillInternals = {
stubThis: (value) => value,
};
@@ -0,0 +1,8 @@
/**
* Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
* credential response ArrayBuffers to string for sending back to the server as JSON.
*
* Helper method to compliment `base64URLStringToBuffer`
*/
export declare function bufferToBase64URLString(buffer: ArrayBuffer): string;
//# sourceMappingURL=bufferToBase64URLString.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"bufferToBase64URLString.d.ts","sourceRoot":"","sources":["../../src/helpers/bufferToBase64URLString.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAWnE"}
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bufferToBase64URLString = bufferToBase64URLString;
/**
* Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
* credential response ArrayBuffers to string for sending back to the server as JSON.
*
* Helper method to compliment `base64URLStringToBuffer`
*/
function bufferToBase64URLString(buffer) {
const bytes = new Uint8Array(buffer);
let str = '';
for (const charCode of bytes) {
str += String.fromCharCode(charCode);
}
const base64String = btoa(str);
return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
@@ -0,0 +1,9 @@
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.get()`
*/
export declare function identifyAuthenticationError({ error, options, }: {
error: Error;
options: CredentialRequestOptions;
}): WebAuthnError | Error;
//# sourceMappingURL=identifyAuthenticationError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"identifyAuthenticationError.d.ts","sourceRoot":"","sources":["../../src/helpers/identifyAuthenticationError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,wBAAwB,CAAC;CACnC,GAAG,aAAa,GAAG,KAAK,CAuDxB"}
@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.identifyAuthenticationError = identifyAuthenticationError;
const isValidDomain_js_1 = require("./isValidDomain.js");
const webAuthnError_js_1 = require("./webAuthnError.js");
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.get()`
*/
function identifyAuthenticationError({ error, options, }) {
const { publicKey } = options;
if (!publicKey) {
throw Error('options was missing required publicKey property');
}
if (error.name === 'AbortError') {
if (options.signal instanceof AbortSignal) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)
return new webAuthnError_js_1.WebAuthnError({
message: 'Authentication ceremony was sent an abort signal',
code: 'ERROR_CEREMONY_ABORTED',
cause: error,
});
}
}
else if (error.name === 'NotAllowedError') {
/**
* Pass the error directly through. Platforms are overloading this error beyond what the spec
* defines and we don't want to overwrite potentially useful error messages.
*/
return new webAuthnError_js_1.WebAuthnError({
message: error.message,
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
cause: error,
});
}
else if (error.name === 'SecurityError') {
const effectiveDomain = globalThis.location.hostname;
if (!(0, isValidDomain_js_1.isValidDomain)(effectiveDomain)) {
// https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 5)
return new webAuthnError_js_1.WebAuthnError({
message: `${globalThis.location.hostname} is an invalid domain`,
code: 'ERROR_INVALID_DOMAIN',
cause: error,
});
}
else if (publicKey.rpId !== effectiveDomain) {
// https://www.w3.org/TR/webauthn-2/#sctn-discover-from-external-source (Step 6)
return new webAuthnError_js_1.WebAuthnError({
message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
code: 'ERROR_INVALID_RP_ID',
cause: error,
});
}
}
else if (error.name === 'UnknownError') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 1)
// https://www.w3.org/TR/webauthn-2/#sctn-op-get-assertion (Step 12)
return new webAuthnError_js_1.WebAuthnError({
message: 'The authenticator was unable to process the specified options, or could not create a new assertion signature',
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
cause: error,
});
}
return error;
}
@@ -0,0 +1,9 @@
import { WebAuthnError } from './webAuthnError.js';
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.create()`
*/
export declare function identifyRegistrationError({ error, options, }: {
error: Error;
options: CredentialCreationOptions;
}): WebAuthnError | Error;
//# sourceMappingURL=identifyRegistrationError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"identifyRegistrationError.d.ts","sourceRoot":"","sources":["../../src/helpers/identifyRegistrationError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,yBAAyB,CAAC;CACpC,GAAG,aAAa,GAAG,KAAK,CA4HxB"}
@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.identifyRegistrationError = identifyRegistrationError;
const isValidDomain_js_1 = require("./isValidDomain.js");
const webAuthnError_js_1 = require("./webAuthnError.js");
/**
* Attempt to intuit _why_ an error was raised after calling `navigator.credentials.create()`
*/
function identifyRegistrationError({ error, options, }) {
const { publicKey } = options;
if (!publicKey) {
throw Error('options was missing required publicKey property');
}
if (error.name === 'AbortError') {
if (options.signal instanceof AbortSignal) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 16)
return new webAuthnError_js_1.WebAuthnError({
message: 'Registration ceremony was sent an abort signal',
code: 'ERROR_CEREMONY_ABORTED',
cause: error,
});
}
}
else if (error.name === 'ConstraintError') {
if (publicKey.authenticatorSelection?.requireResidentKey === true) {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 4)
return new webAuthnError_js_1.WebAuthnError({
message: 'Discoverable credentials were required but no available authenticator supported it',
code: 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT',
cause: error,
});
}
else if (
// @ts-ignore: `mediation` doesn't yet exist on CredentialCreationOptions but it's possible as of Sept 2024
options.mediation === 'conditional' &&
publicKey.authenticatorSelection?.userVerification === 'required') {
// https://w3c.github.io/webauthn/#sctn-createCredential (Step 22.4)
return new webAuthnError_js_1.WebAuthnError({
message: 'User verification was required during automatic registration but it could not be performed',
code: 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE',
cause: error,
});
}
else if (publicKey.authenticatorSelection?.userVerification === 'required') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 5)
return new webAuthnError_js_1.WebAuthnError({
message: 'User verification was required but no available authenticator supported it',
code: 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT',
cause: error,
});
}
}
else if (error.name === 'InvalidStateError') {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 20)
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 3)
return new webAuthnError_js_1.WebAuthnError({
message: 'The authenticator was previously registered',
code: 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED',
cause: error,
});
}
else if (error.name === 'NotAllowedError') {
/**
* Pass the error directly through. Platforms are overloading this error beyond what the spec
* defines and we don't want to overwrite potentially useful error messages.
*/
return new webAuthnError_js_1.WebAuthnError({
message: error.message,
code: 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY',
cause: error,
});
}
else if (error.name === 'NotSupportedError') {
const validPubKeyCredParams = publicKey.pubKeyCredParams.filter((param) => param.type === 'public-key');
if (validPubKeyCredParams.length === 0) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 10)
return new webAuthnError_js_1.WebAuthnError({
message: 'No entry in pubKeyCredParams was of type "public-key"',
code: 'ERROR_MALFORMED_PUBKEYCREDPARAMS',
cause: error,
});
}
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 2)
return new webAuthnError_js_1.WebAuthnError({
message: 'No available authenticator supported any of the specified pubKeyCredParams algorithms',
code: 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG',
cause: error,
});
}
else if (error.name === 'SecurityError') {
const effectiveDomain = globalThis.location.hostname;
if (!(0, isValidDomain_js_1.isValidDomain)(effectiveDomain)) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 7)
return new webAuthnError_js_1.WebAuthnError({
message: `${globalThis.location.hostname} is an invalid domain`,
code: 'ERROR_INVALID_DOMAIN',
cause: error,
});
}
else if (publicKey.rp.id !== effectiveDomain) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 8)
return new webAuthnError_js_1.WebAuthnError({
message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
code: 'ERROR_INVALID_RP_ID',
cause: error,
});
}
}
else if (error.name === 'TypeError') {
if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) {
// https://www.w3.org/TR/webauthn-2/#sctn-createCredential (Step 5)
return new webAuthnError_js_1.WebAuthnError({
message: 'User ID was not between 1 and 64 characters',
code: 'ERROR_INVALID_USER_ID_LENGTH',
cause: error,
});
}
}
else if (error.name === 'UnknownError') {
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 1)
// https://www.w3.org/TR/webauthn-2/#sctn-op-make-cred (Step 8)
return new webAuthnError_js_1.WebAuthnError({
message: 'The authenticator was unable to process the specified options, or could not create a new credential',
code: 'ERROR_AUTHENTICATOR_GENERAL_ERROR',
cause: error,
});
}
return error;
}
@@ -0,0 +1,10 @@
/**
* A simple test to determine if a hostname is a properly-formatted domain name
*
* A "valid domain" is defined here: https://url.spec.whatwg.org/#valid-domain
*
* Regex was originally sourced from here, then remixed to add punycode support:
* https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
*/
export declare function isValidDomain(hostname: string): boolean;
//# sourceMappingURL=isValidDomain.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"isValidDomain.d.ts","sourceRoot":"","sources":["../../src/helpers/isValidDomain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOvD"}
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isValidDomain = isValidDomain;
/**
* A simple test to determine if a hostname is a properly-formatted domain name
*
* A "valid domain" is defined here: https://url.spec.whatwg.org/#valid-domain
*
* Regex was originally sourced from here, then remixed to add punycode support:
* https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
*/
function isValidDomain(hostname) {
return (
// Consider localhost valid as well since it's okay wrt Secure Contexts
hostname === 'localhost' ||
// Support punycode (ACE) or ascii labels and domains
/^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(hostname));
}
@@ -0,0 +1,8 @@
/**
* Determine whether the browser can communicate with a built-in authenticator, like
* Touch ID, Android fingerprint scanner, or Windows Hello.
*
* This method will _not_ be able to tell you the name of the platform authenticator.
*/
export declare function platformAuthenticatorIsAvailable(): Promise<boolean>;
//# sourceMappingURL=platformAuthenticatorIsAvailable.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"platformAuthenticatorIsAvailable.d.ts","sourceRoot":"","sources":["../../src/helpers/platformAuthenticatorIsAvailable.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI,OAAO,CAAC,OAAO,CAAC,CAMnE"}
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.platformAuthenticatorIsAvailable = platformAuthenticatorIsAvailable;
const browserSupportsWebAuthn_js_1 = require("./browserSupportsWebAuthn.js");
/**
* Determine whether the browser can communicate with a built-in authenticator, like
* Touch ID, Android fingerprint scanner, or Windows Hello.
*
* This method will _not_ be able to tell you the name of the platform authenticator.
*/
function platformAuthenticatorIsAvailable() {
if (!(0, browserSupportsWebAuthn_js_1.browserSupportsWebAuthn)()) {
return new Promise((resolve) => resolve(false));
}
return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
}
@@ -0,0 +1,6 @@
import type { AuthenticatorAttachment } from '../types/index.js';
/**
* If possible coerce a `string` value into a known `AuthenticatorAttachment`
*/
export declare function toAuthenticatorAttachment(attachment: string | null): AuthenticatorAttachment | undefined;
//# sourceMappingURL=toAuthenticatorAttachment.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"toAuthenticatorAttachment.d.ts","sourceRoot":"","sources":["../../src/helpers/toAuthenticatorAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAIjE;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,uBAAuB,GAAG,SAAS,CAUrC"}
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toAuthenticatorAttachment = toAuthenticatorAttachment;
const attachments = ['cross-platform', 'platform'];
/**
* If possible coerce a `string` value into a known `AuthenticatorAttachment`
*/
function toAuthenticatorAttachment(attachment) {
if (!attachment) {
return;
}
if (attachments.indexOf(attachment) < 0) {
return;
}
return attachment;
}
@@ -0,0 +1,3 @@
import type { PublicKeyCredentialDescriptor, PublicKeyCredentialDescriptorJSON } from '../types/index.js';
export declare function toPublicKeyCredentialDescriptor(descriptor: PublicKeyCredentialDescriptorJSON): PublicKeyCredentialDescriptor;
//# sourceMappingURL=toPublicKeyCredentialDescriptor.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"toPublicKeyCredentialDescriptor.d.ts","sourceRoot":"","sources":["../../src/helpers/toPublicKeyCredentialDescriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,iCAAiC,EAClC,MAAM,mBAAmB,CAAC;AAG3B,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,iCAAiC,GAC5C,6BAA6B,CAa/B"}
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toPublicKeyCredentialDescriptor = toPublicKeyCredentialDescriptor;
const base64URLStringToBuffer_js_1 = require("./base64URLStringToBuffer.js");
function toPublicKeyCredentialDescriptor(descriptor) {
const { id } = descriptor;
return {
...descriptor,
id: (0, base64URLStringToBuffer_js_1.base64URLStringToBuffer)(id),
/**
* `descriptor.transports` is an array of our `AuthenticatorTransportFuture` that includes newer
* transports that TypeScript's DOM lib is ignorant of. Convince TS that our list of transports
* are fine to pass to WebAuthn since browsers will recognize the new value.
*/
transports: descriptor.transports,
};
}
@@ -0,0 +1,22 @@
interface WebAuthnAbortService {
/**
* Prepare an abort signal that will help support multiple auth attempts without needing to
* reload the page. This is automatically called whenever `startRegistration()` and
* `startAuthentication()` are called.
*/
createNewAbortSignal(): AbortSignal;
/**
* Manually cancel any active WebAuthn registration or authentication attempt.
*/
cancelCeremony(): void;
}
/**
* A service singleton to help ensure that only a single WebAuthn ceremony is active at a time.
*
* Users of **@simplewebauthn/browser** shouldn't typically need to use this, but it can help e.g.
* developers building projects that use client-side routing to better control the behavior of
* their UX in response to router navigation events.
*/
export declare const WebAuthnAbortService: WebAuthnAbortService;
export {};
//# sourceMappingURL=webAuthnAbortService.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"webAuthnAbortService.d.ts","sourceRoot":"","sources":["../../src/helpers/webAuthnAbortService.ts"],"names":[],"mappings":"AAAA,UAAU,oBAAoB;IAC5B;;;;OAIG;IACH,oBAAoB,IAAI,WAAW,CAAC;IACpC;;OAEG;IACH,cAAc,IAAI,IAAI,CAAC;CACxB;AAkCD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,oBAAqD,CAAC"}
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebAuthnAbortService = void 0;
class BaseWebAuthnAbortService {
constructor() {
Object.defineProperty(this, "controller", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
}
createNewAbortSignal() {
// Abort any existing calls to navigator.credentials.create() or navigator.credentials.get()
if (this.controller) {
const abortError = new Error('Cancelling existing WebAuthn API call for new one');
abortError.name = 'AbortError';
this.controller.abort(abortError);
}
const newController = new AbortController();
this.controller = newController;
return newController.signal;
}
cancelCeremony() {
if (this.controller) {
const abortError = new Error('Manually cancelling existing WebAuthn API call');
abortError.name = 'AbortError';
this.controller.abort(abortError);
this.controller = undefined;
}
}
}
/**
* A service singleton to help ensure that only a single WebAuthn ceremony is active at a time.
*
* Users of **@simplewebauthn/browser** shouldn't typically need to use this, but it can help e.g.
* developers building projects that use client-side routing to better control the behavior of
* their UX in response to router navigation events.
*/
exports.WebAuthnAbortService = new BaseWebAuthnAbortService();
@@ -0,0 +1,28 @@
/**
* A custom Error used to return a more nuanced error detailing _why_ one of the eight documented
* errors in the spec was raised after calling `navigator.credentials.create()` or
* `navigator.credentials.get()`:
*
* - `AbortError`
* - `ConstraintError`
* - `InvalidStateError`
* - `NotAllowedError`
* - `NotSupportedError`
* - `SecurityError`
* - `TypeError`
* - `UnknownError`
*
* Error messages were determined through investigation of the spec to determine under which
* scenarios a given error would be raised.
*/
export declare class WebAuthnError extends Error {
code: WebAuthnErrorCode;
constructor({ message, code, cause, name, }: {
message: string;
code: WebAuthnErrorCode;
cause: Error;
name?: string;
});
}
export type WebAuthnErrorCode = 'ERROR_CEREMONY_ABORTED' | 'ERROR_INVALID_DOMAIN' | 'ERROR_INVALID_RP_ID' | 'ERROR_INVALID_USER_ID_LENGTH' | 'ERROR_MALFORMED_PUBKEYCREDPARAMS' | 'ERROR_AUTHENTICATOR_GENERAL_ERROR' | 'ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT' | 'ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT' | 'ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED' | 'ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG' | 'ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE' | 'ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY';
//# sourceMappingURL=webAuthnError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"webAuthnError.d.ts","sourceRoot":"","sources":["../../src/helpers/webAuthnError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,IAAI,EAAE,iBAAiB,CAAC;gBAEZ,EACV,OAAO,EACP,IAAI,EACJ,KAAK,EACL,IAAI,GACL,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,iBAAiB,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;CAMF;AAED,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,sBAAsB,GACtB,qBAAqB,GACrB,8BAA8B,GAC9B,kCAAkC,GAClC,mCAAmC,GACnC,6DAA6D,GAC7D,uDAAuD,GACvD,2CAA2C,GAC3C,uDAAuD,GACvD,+CAA+C,GAC/C,sCAAsC,CAAC"}
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebAuthnError = void 0;
/**
* A custom Error used to return a more nuanced error detailing _why_ one of the eight documented
* errors in the spec was raised after calling `navigator.credentials.create()` or
* `navigator.credentials.get()`:
*
* - `AbortError`
* - `ConstraintError`
* - `InvalidStateError`
* - `NotAllowedError`
* - `NotSupportedError`
* - `SecurityError`
* - `TypeError`
* - `UnknownError`
*
* Error messages were determined through investigation of the spec to determine under which
* scenarios a given error would be raised.
*/
class WebAuthnError extends Error {
constructor({ message, code, cause, name, }) {
// @ts-ignore: help Rollup understand that `cause` is okay to set
super(message, { cause });
Object.defineProperty(this, "code", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = name ?? cause.name;
this.code = code;
}
}
exports.WebAuthnError = WebAuthnError;
+11
View File
@@ -0,0 +1,11 @@
export * from './methods/startRegistration.js';
export * from './methods/startAuthentication.js';
export * from './helpers/browserSupportsWebAuthn.js';
export * from './helpers/platformAuthenticatorIsAvailable.js';
export * from './helpers/browserSupportsWebAuthnAutofill.js';
export * from './helpers/base64URLStringToBuffer.js';
export * from './helpers/bufferToBase64URLString.js';
export * from './helpers/webAuthnAbortService.js';
export * from './helpers/webAuthnError.js';
export * from './types/index.js';
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC"}
+26
View File
@@ -0,0 +1,26 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./methods/startRegistration.js"), exports);
__exportStar(require("./methods/startAuthentication.js"), exports);
__exportStar(require("./helpers/browserSupportsWebAuthn.js"), exports);
__exportStar(require("./helpers/platformAuthenticatorIsAvailable.js"), exports);
__exportStar(require("./helpers/browserSupportsWebAuthnAutofill.js"), exports);
__exportStar(require("./helpers/base64URLStringToBuffer.js"), exports);
__exportStar(require("./helpers/bufferToBase64URLString.js"), exports);
__exportStar(require("./helpers/webAuthnAbortService.js"), exports);
__exportStar(require("./helpers/webAuthnError.js"), exports);
__exportStar(require("./types/index.js"), exports);
@@ -0,0 +1,15 @@
import type { AuthenticationResponseJSON, PublicKeyCredentialRequestOptionsJSON } from '../types/index.js';
export type StartAuthenticationOpts = Parameters<typeof startAuthentication>[0];
/**
* Begin authenticator "login" via WebAuthn assertion
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateAuthenticationOptions()`
* @param useBrowserAutofill (Optional) Initialize conditional UI to enable logging in via browser autofill prompts. Defaults to `false`.
* @param verifyBrowserAutofillInput (Optional) Ensure a suitable `<input>` element is present when `useBrowserAutofill` is `true`. Defaults to `true`.
*/
export declare function startAuthentication(options: {
optionsJSON: PublicKeyCredentialRequestOptionsJSON;
useBrowserAutofill?: boolean;
verifyBrowserAutofillInput?: boolean;
}): Promise<AuthenticationResponseJSON>;
//# sourceMappingURL=startAuthentication.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"startAuthentication.d.ts","sourceRoot":"","sources":["../../src/methods/startAuthentication.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,qCAAqC,EACtC,MAAM,mBAAmB,CAAC;AAU3B,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE;IACP,WAAW,EAAE,qCAAqC,CAAC;IACnD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,GACA,OAAO,CAAC,0BAA0B,CAAC,CA4GrC"}
@@ -0,0 +1,98 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.startAuthentication = startAuthentication;
const bufferToBase64URLString_js_1 = require("../helpers/bufferToBase64URLString.js");
const base64URLStringToBuffer_js_1 = require("../helpers/base64URLStringToBuffer.js");
const browserSupportsWebAuthn_js_1 = require("../helpers/browserSupportsWebAuthn.js");
const browserSupportsWebAuthnAutofill_js_1 = require("../helpers/browserSupportsWebAuthnAutofill.js");
const toPublicKeyCredentialDescriptor_js_1 = require("../helpers/toPublicKeyCredentialDescriptor.js");
const identifyAuthenticationError_js_1 = require("../helpers/identifyAuthenticationError.js");
const webAuthnAbortService_js_1 = require("../helpers/webAuthnAbortService.js");
const toAuthenticatorAttachment_js_1 = require("../helpers/toAuthenticatorAttachment.js");
/**
* Begin authenticator "login" via WebAuthn assertion
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateAuthenticationOptions()`
* @param useBrowserAutofill (Optional) Initialize conditional UI to enable logging in via browser autofill prompts. Defaults to `false`.
* @param verifyBrowserAutofillInput (Optional) Ensure a suitable `<input>` element is present when `useBrowserAutofill` is `true`. Defaults to `true`.
*/
async function startAuthentication(options) {
// @ts-ignore: Intentionally check for old call structure to warn about improper API call
if (!options.optionsJSON && options.challenge) {
console.warn('startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.');
// @ts-ignore: Reassign the options, passed in as a positional argument, to the expected variable
options = { optionsJSON: options };
}
const { optionsJSON, useBrowserAutofill = false, verifyBrowserAutofillInput = true, } = options;
if (!(0, browserSupportsWebAuthn_js_1.browserSupportsWebAuthn)()) {
throw new Error('WebAuthn is not supported in this browser');
}
// We need to avoid passing empty array to avoid blocking retrieval
// of public key
let allowCredentials;
if (optionsJSON.allowCredentials?.length !== 0) {
allowCredentials = optionsJSON.allowCredentials?.map(toPublicKeyCredentialDescriptor_js_1.toPublicKeyCredentialDescriptor);
}
// We need to convert some values to Uint8Arrays before passing the credentials to the navigator
const publicKey = {
...optionsJSON,
challenge: (0, base64URLStringToBuffer_js_1.base64URLStringToBuffer)(optionsJSON.challenge),
allowCredentials,
};
// Prepare options for `.get()`
const getOptions = {};
/**
* 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 (0, browserSupportsWebAuthnAutofill_js_1.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 && verifyBrowserAutofillInput) {
throw Error('No <input> with "webauthn" as the only or last value in its `autocomplete` attribute was detected');
}
// `CredentialMediationRequirement` doesn't know about "conditional" yet as of
// typescript@4.6.3
getOptions.mediation = 'conditional';
// Conditional UI requires an empty allow list
publicKey.allowCredentials = [];
}
// Finalize options
getOptions.publicKey = publicKey;
// Set up the ability to cancel this request if the user attempts another
getOptions.signal = webAuthnAbortService_js_1.WebAuthnAbortService.createNewAbortSignal();
// Wait for the user to complete assertion
let credential;
try {
credential = (await navigator.credentials.get(getOptions));
}
catch (err) {
throw (0, identifyAuthenticationError_js_1.identifyAuthenticationError)({ error: err, options: getOptions });
}
if (!credential) {
throw new Error('Authentication was not completed');
}
const { id, rawId, response, type } = credential;
let userHandle = undefined;
if (response.userHandle) {
userHandle = (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.userHandle);
}
// Convert values to base64 to make it easier to send back to the server
return {
id,
rawId: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(rawId),
response: {
authenticatorData: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.authenticatorData),
clientDataJSON: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.clientDataJSON),
signature: (0, bufferToBase64URLString_js_1.bufferToBase64URLString)(response.signature),
userHandle,
},
type,
clientExtensionResults: credential.getClientExtensionResults(),
authenticatorAttachment: (0, toAuthenticatorAttachment_js_1.toAuthenticatorAttachment)(credential.authenticatorAttachment),
};
}
@@ -0,0 +1,13 @@
import type { PublicKeyCredentialCreationOptionsJSON, RegistrationResponseJSON } from '../types/index.js';
export type StartRegistrationOpts = Parameters<typeof startRegistration>[0];
/**
* Begin authenticator "registration" via WebAuthn attestation
*
* @param optionsJSON Output from **@simplewebauthn/server**'s `generateRegistrationOptions()`
* @param useAutoRegister (Optional) Try to silently create a passkey with the password manager that the user just signed in with. Defaults to `false`.
*/
export declare function startRegistration(options: {
optionsJSON: PublicKeyCredentialCreationOptionsJSON;
useAutoRegister?: boolean;
}): Promise<RegistrationResponseJSON>;
//# sourceMappingURL=startRegistration.d.ts.map

Some files were not shown because too many files have changed in this diff Show More