SimpleWebAuthn

WebAuthn, Simplified. A collection of TypeScript-first libraries for simpler WebAuthn integration. Supports modern browsers, Node, Deno, and more.

MIT License

Downloads
2.4M
Stars
1.3K
Committers
23

Bot releases are hidden (Show)

SimpleWebAuthn -

Published by MasterKale over 2 years ago

Packages:

Changes:

  • [browser, typescript-types] The new "cable" transport is now recognized as a potential value of the AuthenticatorTransport type (#198)
  • [server] verifyRegistrationResponse() and verifyAuthenticationResponse() now return credentialDeviceType and credentialBackedUp within authenticatorInfo as parsed values of two new flags being added to authenticator data. These response verification methods will also now throw an error when the invalid combination of these two flags (credentialDeviceType: "singleDevice", credentialBackedUp: true) is detected (#195)
SimpleWebAuthn -

Published by MasterKale over 2 years ago

Packages:

Changes:

  • [browser] Custom errors raised when calling startRegistration() and startAuthentication() will now have the same name property as the original error (#191)
  • [server] Cleaned up code and added tests (#192, #193)
SimpleWebAuthn - v5.0.0 - The one with more insights

Published by MasterKale over 2 years ago

Packages:

Changes:

  • [browser] Most common WebAuthn errors that can occur when calling startRegistration() and startAuthentication() will now return descriptions with more specific insights into what went wrong (#184)
  • [testing] Version sync
  • [typescript-types] Version sync

Breaking Changes

  • [server] The fidoUserVerification argument to verifyAuthenticationResponse() has been replaced with the simpler requireUserVerification boolean (#181)

Previous values of "required" should specify true for this new argument; previous values of "preferred" or "discouraged" should specify false:

Before:

const verification = verifyAuthenticationResponse({
  // ...snip...
  fidoUserVerification: 'required',
});

After:

const verification = verifyAuthenticationResponse({
  // ...snip...
  requireUserVerification: true,
});
SimpleWebAuthn -

Published by MasterKale over 2 years ago

Packages:

Changes:

  • [server] Attestation statement verification involving FIDO metadata now correctly validates the credential public keypair algorithm against possible algorithms defined in the metadata statement.
  • [server] The expired GlobalSign R2 root certificate for "android-safetynet" responses has been removed
  • [server] Certificate path validation errors will now identify which part of the chain and which certificate has an issue
  • [server] verifyAuthenticationResponse()'s expectedChallenge argument also accepts a function that accepts a Base64URL string and returns a boolean to run custom logic against the clientDataJSON.challenge returned by the authenticator (see v4.3.0 release notes for more info).
SimpleWebAuthn -

Published by MasterKale over 2 years ago

Packages:

Changes:

  • [server] The expectedChallenge argument passed to verifyRegistrationResponse() can now be a function that accepts a Base64URL string and returns a boolean to run custom logic against the clientDataJSON.challenge returned by the authenticator. This allows for arbitrary data to be included in the challenge so it can be signed by the authenticator.

After generating registration options, the challenge can be augmented with additional data:

const options = generateRegistrationOptions(opts);

// Remember the plain challenge
inMemoryUserDeviceDB[loggedInUserId].currentChallenge = options.challenge;

// Add data to be signed
options.challenge = base64url(JSON.stringify({
  actualChallenge: options.challenge,
  arbitraryData: 'arbitraryDataForSigning',
}));

Then, when invoking verifyRegistrationResponse(), pass in a method for expectedChallenge to parse the challenge and return a boolean:

const expectedChallenge = inMemoryUserDeviceDB[loggedInUserId].currentChallenge;

const verification = await verifyRegistrationResponse({
  expectedChallenge: (challenge: string) => {
    const parsedChallenge = JSON.parse(base64url.decode(challenge));
    return parsedChallenge.actualChallenge === expectedChallenge;
  },
  // ...
});

To retrieve the arbitrary data afterwards, use decodeClientDataJSON() afterwards to get it out:

import { decodeClientDataJSON } from '@simplewebauthn/server/helpers';

const { challenge } = decodeClientDataJSON(response.clientDataJSON);
const parsedChallenge = JSON.parse(base64url.decode(challenge));
console.log(parsedChallenge.arbitraryData); // 'arbitraryDataForSigning'
SimpleWebAuthn -

Published by MasterKale about 3 years ago

Packages:

Changes:

  • [server] The debug library has been incorporated to support logging output from the library's internal operations. Add the following environment variable to your application to view this output when using this library:
DEBUG=SimpleWebAuthn:*

The following logging scopes are defined in this release:

SimpleWebAuthn:MetadataService

See PR #159 for a preview of logging output.

SimpleWebAuthn -

Published by MasterKale about 3 years ago

Packages:

Changes:

  • [browser] platformAuthenticatorIsAvailable() now checks that WebAuthn is supported at all before attempting to query for the status of an available platform authenticator.
  • [server] MetadataService.initialize() gained a new verificationMode option that can be set to "permissive" to allow registration response verification to continue when an unregistered AAGUID is encountered. Default behavior, that fails registration response verification, is represented by the alternative value "strict"; MetadataService continues to default to this more restrictive behavior.
SimpleWebAuthn - v4.0.0 - The one with some new names

Published by MasterKale about 3 years ago

A lot has happened to me since I first launched SimpleWebAuthn back in May 2020. My understanding of WebAuthn has grown by leaps and bounds thanks in part to my representing Duo/Cisco in the W3C's WebAuth Adoption Working Group. I'm now in a point in my life in which it's no longer sufficient to think, "what's in SimpleWebAuthn's best interests?" Now, I have an opportunity to think bigger - "what's in the WebAuthn API's best interests?"

While early on I thought "attestation" and "assertion" were important names to WebAuthn, I've since come to better appreciate the spec's efforts to encourage the use of "registration" and "authentication" instead. To that end I decided it was time to rename all of the project's various public methods and types to get as much as possible to use "registration" and "authentication" instead.

This release is one of the more disruptive because it affects everyone who's used SimpleWebAuthn to date. The good news is that, while method and type names have changed, their capabilities remain the same. Updating your code to this version of SimpleWebAuthn should only involve renaming existing method calls and type annotations.

Please take the time to read the entire changelog for this release! There are a handful of new features also included that users with advanced use cases will find helpful. The simple use cases of the library remain unchanged - most new features are for power users who require extra scrutiny of authenticators that interact with their website and are otherwise opt-in as needed.

Packages:

Changes:

  • [browser] A new (asynchronous) helper method platformAuthenticatorIsAvailable() has been added for detecting when hardware-bound authenticators like Touch ID, Windows Hello, etc... are available for use. More info is available here.
  • [server] The new SettingsService can be used to configure aspects of SimpleWebAuthn like root certs for enhanced registration response verification or for validating FIDO MDS BLOBs with MetadataService. More info is available here.
  • [server] Known root certificates for the following attestation formats have been updated: 'android-key', 'android-safetynet', 'apple'
  • [server] A wide range of internal helper methods are now exported from '@simplewebauthn/server/helpers' (not a new package, but a subpath.) These methods can be used, for example, to process non-standard responses that are not officially part of the WebAuthn spec and thus unlikely to ever be supported by SimpleWebAuthn.
  • [server] MetadataService now supports FIDO Alliance Metadata Service version 3.0.

Breaking Changes

  • [browser, server, typescript-types] All methods and types that included "attestation" in the name have been renamed to use "registration" instead
  • [browser, server, typescript-types] All methods and types that included "assertion" in the name have been renamed to use "authentication" instead.

The quickest way to update your code is to try changing "attestation" to "registration" and "assertion" to "authentication" in the name of whatever method or type is no longer working and see if that fixes it (exceptions to this rule are called out with asterisks below.) If it doesn't, check out PR #147 to see all of the renamed methods and types and try to cross-reference the original to see what it was renamed to.

Examples:

  • generateAttestationOptions() -> generateRegistrationOptions()
  • GenerateAttestationOptionsOpts -> GenerateRegistrationOptionsOpts
  • verifyAssertionResponse() -> verifyAuthenticationResponse()
  • VerifiedAttestation -> VerifiedRegistrationResponse (*)
  • VerifiedAssertion -> VerifiedAuthenticationResponse (*)
  • startAttestation() -> startRegistration()
  • startAssertion() -> startAuthentication()

These examples are not a comprehensive list of all the renamed methods! Rather these are examples of how method names were changed to try and eliminate "attestation" and "assertion" from the public API of both @simplewebauthn/browser and @simplewebauthn/server.

  • [server] The opts argument for MetadataService.initialize() is now optional.
  • [server] The opts.mdsServers argument for MetadataService.initialize(opts) is now a simple array of URL strings to FIDO Alliance MDSv3-compatible servers. If no value is specified then MetadataService will query the official FIDO Alliance Metadata Service version 3.0.

See here for more information about the updated MetadataService.

  • [browser] supportsWebAuthn() has been renamed to browserSupportsWebAuthn() in an effort to make the method convey a clearer idea of what supports WebAuthn.
SimpleWebAuthn -

Published by MasterKale over 3 years ago

Packages:

Changes:

  • [browser] The ES2018 bundle is now "main" in package.json. The tslib dependency for production is no longer necessary as transpilation to ES5 is now fully the responsibility of the framework implementing @simplewebauthn/browser.
    • The ES5 UMD build remains available for websites not leveraging a build pipeline.
  • [browser] Linking to this package via unpkg now defaults to the ES2018 build. See browser's README.md for information on how to link to the ES5 build instead.
SimpleWebAuthn - v3.0.0 - The one with a legacy

Published by MasterKale over 3 years ago

This release is focused on updating @simplewebauthn/browser for better browser support out of the box. Most projects will now pull in its (slightly larger) ES5 bundle to ensure maximum browser compatibility, including older browsers in which WebAuthn will never be available. The ES2018 build is still available for projects that only need to target newer browsers, but bundler configuration changes must now be made to include it instead of the ES5 build.

Packages:

Changes:

  • [browser] Set default bundle to ES5 to support IE10+ and Edge Legacy
  • [browser] startAssertion() no longer Base64URL-encodes userHandle string
  • [server] Fix issue with Chrome (< v90) WebAuthn virtual authenticators
  • [server] Update jsrsasign to 10.2.0 (see GHSA-27fj-mc8w-j9wg)
  • [typescript-types] Update assertion JSON declarations as per startAssertion() fix

Breaking Changes

  • [browser] Projects targeting modern browsers may not wish to bundle the ES5 version due to its inclusion of various polyfills. See the updated "Building for Production" section of the README.md for more info on how to pull in the ES2018 version instead.
  • [browser] RPs with usernameless flows will no longer need to Base64URL-decode response.userHandle as returned from startAssertion().
SimpleWebAuthn -

Published by MasterKale over 3 years ago

Packges:

Changes:

  • [browser] Adds support for older browsers (IE10/IE11, Edge Legacy, etc...) with additional build artifacts targeting ES5
    • See updated "Installation" and "Building for Production" sections of the README.md
  • [server] Internal code cleanup
SimpleWebAuthn -

Published by MasterKale over 3 years ago

Packages:

Changes:

  • [server] Export more TypeScript types for options and verification method inputs and outputs:
// Newly exported types
import type {
  GenerateAttestationOptionsOpts,
  GenerateAssertionOptionsOpts,
  VerifyAttestationResponseOpts,
  VerifyAssertionResponseOpts,
  VerifiedAttestation,
  VerifiedAssertion,
} from '@simplewebauthn/server';
SimpleWebAuthn -

Published by MasterKale over 3 years ago

Packages:

Changes:

  • [browser] startAttestation() and startAssertion() now include extension results as clientExtensionResults in their return value
  • [typescript-types] Updated PublicKeyCredentialCreationOptionsJSON and PublicKeyCredentialRequestOptionsJSON types with new optional extensions property to support specifying WebAuthn extensions when calling generateAttestationOptions() and generateAssertionOptions()
  • [typescript-types] Updated AttestationCredentialJSON and AssertionCredentialJSON types with new clientExtensionResults properties to contain output from WebAuthn's credential.getClientExtensionResults()
  • [server] Version sync
SimpleWebAuthn - v2.0.0 - The one with -less and more Buffers

Published by MasterKale over 3 years ago

This major release includes improvements intended to make it easier to support passwordless and usernameless WebAuthn flows. Additional information returned from attestation verification can be used by RP's to further scrutinize the attestation now or in the future.

I also made the decision to reduce the amount of encoding from Buffer to Base64URL and decoding from Base64URL to Buffer throughout the library. Verification methods now return raw Buffers so that RP's are free to store and retrieve these values as they see fit without the library imposing any kind of encoding overhead that may complicate storage in a database, etc...

Packages:

Changes:

  • [server] See Breaking Changes below.
  • [typescript-types] See Breaking Changes below
  • [browser] Version sync
  • [testing] Version sync

Breaking Changes

  • [server] The method verifyAttestationResponse() now returns a different data structure with additional information that RP's can use to more easily support passwordless and usernameless WebAuthn flows.
    • Additionally, Buffer values are now returned in place of previously-base64url-encoded values. This is intended to offer more flexibility in how these values are persisted without imposing an encoding scheme that may introduce undesirable overhead.

Before:

type VerifiedAttestation = {
  verified: boolean;
  userVerified: boolean;
  authenticatorInfo?: {
    fmt: ATTESTATION_FORMAT;
    counter: number;
    base64PublicKey: string;
    base64CredentialID: string;
  };
};

After:

type VerifiedAttestation = {
  verified: boolean;
  attestationInfo?: {
    fmt: ATTESTATION_FORMAT;
    counter: number;
    aaguid: string;
    credentialPublicKey: Buffer;
    credentialID: Buffer;
    credentialType: string;
    userVerified: boolean;
    attestationObject: Buffer;
  };
};
  • [server] The method verifyAssertionResponse() now returns a different data structure to align with changes made to verifyAttestationResponse().

Before:

type VerifiedAssertion = {
  verified: boolean;
  authenticatorInfo: {
    counter: number;
    base64CredentialID: string;
  };
};

After:

type VerifiedAssertion = {
  verified: boolean;
  assertionInfo: {
    credentialID: Buffer;
    newCounter: number;
  };
};
  • [server] The excludeCredentials argument in generateAttestationOptions() now expects a Buffer type for a credential's id property. Previously id needed to be a string. Existing credential IDs stored in base64url encoding can be easily converted to Buffer with a library like base64url:

Before:

const options = generateAttestationOptions({
  // ...
  excludeCredentials: [{
    id: 'PPa1spYTB680cQq5q6qBtFuPLLdG1FQ73EastkT8n0o',
    // ...
  }],
  // ...
})

After:

const options = generateAttestationOptions({
  // ...
  excludeCredentials: [{
    id: base64url.toBuffer('PPa1spYTB680cQq5q6qBtFuPLLdG1FQ73EastkT8n0o'),
    // ...
  }],
  // ...
})
  • [server] The allowCredentials argument in generateAssertionOptions() now expects a Buffer type for a credential's id property. Previously id needed to be a string. Existing credential IDs stored in base64url encoding can be easily converted to Buffer with a library like base64url:

Before:

const options = generateAssertionOptions({
  // ...
  allowCredentials: [{
    id: 'PPa1spYTB680cQq5q6qBtFuPLLdG1FQ73EastkT8n0o',
    // ...
  }],
  // ...
})

After:

const options = generateAssertionOptions({
  // ...
  allowCredentials: [{
    id: base64url.toBuffer('PPa1spYTB680cQq5q6qBtFuPLLdG1FQ73EastkT8n0o'),
    // ...
  }],
  // ...
})
  • [typescript-types] The AuthenticatorDevice type has been updated to expect Buffer's for credential data. Naming of its properties have also been updated to help maintain consistency with naming in the WebAuthn spec:

Before:

type AuthenticatorDevice = {
  publicKey: Base64URLString;
  credentialID: Base64URLString;
  counter: number;
  transports?: AuthenticatorTransport[];
}

After:

type AuthenticatorDevice = {
  credentialPublicKey: Buffer;
  credentialID: Buffer;
  counter: number;
  transports?: AuthenticatorTransport[];
}
SimpleWebAuthn - v1.0.0 - The one that gets things out of "Beta"

Published by MasterKale over 3 years ago

Packages:

Changes:

  • [server] Add support for multiple expected origins and RP IDs in verifyAttestationResponse() and verifyAssertionResponse()
  • [server] Update generateAttestationOptions() to force legacy authenticatorSelection.requireResidentKey to true when authenticatorSelection.residentKey is "required" (as per L2 of the WebAuthn spec)
  • [typescript-types] Update AuthenticatorDevice type with optional transports property
  • [browser] Version sync
  • [testing] Version sync

Breaking Changes

There are no breaking changes in this release. Several recent minor changes presented an opportunity to release a "v1.0". I'd received enough positive feedback about SimpleWebAuthn and noticed growing usage which granted me the confidence to take advantage of this opportunity.

And perhaps this will give the project more legitimacy in the eyes of larger organizations wishing to use it but waiting for the libraries to "get out of beta"...

SimpleWebAuthn -

Published by MasterKale almost 4 years ago

Packages:

Changes:

  • [server] Unpin dependency versions
  • [server] Upgrade dependencies and devDependencies
  • [typescript-types] Pull in TypeScript DOM lib types on build
  • [docs] Upgrade TypeDoc for better API docs
SimpleWebAuthn -

Published by MasterKale almost 4 years ago

Packages:

Changes:

  • [server] Add optional rpID argument to generateAssertionOptions()
SimpleWebAuthn -

Published by MasterKale about 4 years ago

Packages:

Changes:

  • [server] Update ASN.1 parsing libraries to latest releases
SimpleWebAuthn -

Published by MasterKale about 4 years ago

Packages:

Changes:

  • [server] Pin third-party package versions
SimpleWebAuthn - v0.10.0 - The one you can use your face with

Published by MasterKale about 4 years ago

Packages:

Changes:

  • [server] Add support for "apple" attestations to support iOS Face ID and Touch ID
  • [server] [browser] Enable specifying transports per credential for allowCredentials and excludeCredentials
  • [browser] Return authenticator's transports (when available) as transports in response from startAttestation()
  • [typescript-types] Add new AuthenticatorAttestationResponseFuture type for better typing of credential response methods (getTransports(), getAuthenticatorData(), etc...)

Breaking Changes

  • [server] Existing implementations of generateAttestationOptions() and generateAssertionOptions() must be updated to specify credentials with their own transports:

generateAttestationOptions()

// OLD
const options = generateAttestationOptions({
  excludedCredentialIDs: devices.map(dev => dev.credentialID),
  suggestedTransports: ['usb', 'ble', 'nfc', 'internal'],
});

// NEW
const options = generateAttestationOptions({
  excludeCredentials: devices.map(dev => ({
    id: dev.credentialID,
    type: 'public-key',
    transports: dev.transports,
  })),
});

generateAssertionOptions()

// OLD
const options = generateAssertionOptions({
  allowedCredentialIDs: user.devices.map(dev => dev.credentialID),
  suggestedTransports: ['usb', 'ble', 'nfc', 'internal'],
});

// NEW
const options = generateAssertionOptions({
  allowCredentials: devices.map(dev => ({
    id: dev.credentialID,
    type: 'public-key',
    transports: dev.transports,
  })),
});
Package Rankings
Top 1.5% on Npmjs.org
Top 5.88% on Deno.land
Badges
Extracted from project README
npm (scoped)
Related Projects