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 - v10.0.0 - The one that goes up to 20 Latest Release

Published by MasterKale 6 months ago

Thanks for everything, Node 16 and Node 18, but it's time to move on! The headlining change of this
release is the targeting of Node LTS v20+ as the minimum Node runtime. Additional developer-centric
quality-of-life changes have also been made in the name of streamlining use of SimpleWebAuthn on
both the back end and front end.

This release is packed with updates, so buckle up! Refactor advice for breaking changes is, as
always, offered below.

Packages

Changes

  • [server] The minimum supported Node version has been raised to Node v20
    (#531)
  • [server] user.displayName now defaults to an empty string if a value is not specified for
    userDisplayName when calling generateRegistrationOptions()
    (#538)
  • [browser] The browserSupportsWebAuthnAutofill() helper will no longer break in environments
    in which PublicKeyCredential is not present
    (#557, with thanks to @clarafitzgerald)

Breaking Changes

  • [server] The following breaking changes were made in PR
    #529:
    • generateRegistrationOptions() now expects Base64URLString for excluded credential IDs
    • generateAuthenticationOptions() now expects Base64URLString for allowed credential IDs
    • credentialID returned from response verification methods is now a Base64URLString
    • AuthenticatorDevice.credentialID is now a Base64URLString
    • isoBase64URL.isBase64url() is now called isoBase64URL.isBase64URL()
  • [browser, server] The following breaking changes were made in PR
    #552:
    • generateRegistrationOptions() now accepts an optional Uint8Array instead of a string for
      userID
    • isoBase64URL.toString() and isoBase64URL.fromString() have been renamed
    • generateRegistrationOptions() will now generate random user IDs
    • user.id is now treated like a base64url string in startRegistration()
    • userHandle is now treated like a base64url string in startAuthentication()
  • [server] rpID is now a required argument when calling generateAuthenticationOptions()
    (#555)

[server] generateRegistrationOptions() now expects Base64URLString for excluded credential IDs

The isoBase64URL helper can be used to massage Uint8Array credential IDs into base64url strings:

Before

const opts = await generateRegistrationOptions({
  // ...
  excludeCredentials: devices.map((dev) => ({
    id: dev.credentialID, // type: Uint8Array
    type: 'public-key',
    transports: dev.transports,
  })),
});

After

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

const opts = await generateRegistrationOptions({
  // ...
  excludeCredentials: devices.map((dev) => ({
    id: isoBase64URL.fromBuffer(dev.credentialID), // type: string
    transports: dev.transports,
  })),
});

The type argument is no longer needed either.


[server] generateAuthenticationOptions() now expects Base64URLString for allowed credential IDs

Similarly, the isoBase64URL helper can also be used during auth to massage Uint8Array credential
IDs into base64url strings:

Before

const opts = await generateAuthenticationOptions({
  // ...
  allowCredentials: devices.map((dev) => ({
    id: dev.credentialID, // type: Uint8Array
    type: 'public-key',
    transports: dev.transports,
  })),
});

After

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

const opts = await generateAuthenticationOptions({
  // ...
  allowCredentials: devices.map((dev) => ({
    id: isoBase64URL.fromBuffer(dev.credentialID), // type: Base64URLString (a.k.a string)
    transports: dev.transports,
  })),
});

The type argument is no longer needed either.


[server] credentialID returned from response verification methods is now a Base64URLString

It is no longer necessary to manually stringify credentialID out of response verification methods:

Before

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

// Registration
const { verified, registrationInfo } = await verifyRegistrationResponse({ ... });
if (verified && registrationInfo) {
  const { credentialID } = registrationInfo;
  await storeInDatabase({ credIDString: isoBase64URL.fromBuffer(credentialID), ... });
}

// Authentication
const { verified, authenticationInfo } = await verifyAuthenticationResponse({ ... });
if (verified && authenticationInfo) {
  const { newCounter, credentialID } = authenticationInfo;
  dbAuthenticator.counter = authenticationInfo.newCounter;
  await updateCounterInDatabase({
    credIDString: isoBase64URL.fromBuffer(credentialID),
    newCounter,
  });
}

After

// Registration
const { verified, registrationInfo } = await verifyRegistrationResponse({ ... });
if (verified && registrationInfo) {
  const { credentialID } = registrationInfo;
  await storeInDatabase({ credIDString: credentialID, ... });
}

// Authentication
const { verified, authenticationInfo } = await verifyAuthenticationResponse({ ... });
if (verified && authenticationInfo) {
  const { newCounter, credentialID } = authenticationInfo;
  dbAuthenticator.counter = authenticationInfo.newCounter;
  await updateCounterInDatabase({ credIDString: credentialID, newCounter });
}

[server] AuthenticatorDevice.credentialID is now a Base64URLString

Calls to verifyAuthenticationResponse() will need to be updated to encode the credential ID to a
base64url string:

Before

const verification = await verifyAuthenticationResponse({
  // ...
  authenticator: {
    // ...
    credentialID: credIDBytes,
  },
});

After

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

const verification = await verifyAuthenticationResponse({
  // ...
  authenticator: {
    // ...
    credentialID: isoBase64URL.fromBuffer(credIDBytes),
  },
});

[server] isoBase64URL.isBase64url() is now called isoBase64URL.isBase64URL()

Note the capitalization change from "url" to "URL" in the method name. Update calls to this method
accordingly.


[server] generateRegistrationOptions() will now generate random user IDs

[browser] user.id is now treated like a base64url string in startRegistration()

[browser] userHandle is now treated like a base64url string in startAuthentication()

A random identifier will now be generated when a value is not provided for the now-optional userID
argument when calling generateRegistrationOptions(). This identifier will be base64url-encoded
string of 32 random bytes
. RPs that wish to take advantage of this can simply omit this
argument
.

Additionally, startRegistration() will base64url-decode user.id before calling WebAuthn. During
auth startAuthentication() will base64url-encode userHandle in the returned credential. This
should be a transparent change for RP's that simply feed @simplewebauthn/server options output
into the corresponding @simplewebauthn/browser methods.

However, RP's that wish to continue generating their own user identifiers will need to take
additional steps to ensure they get back user IDs in the expected format after authentication.

Before (SimpleWebAuthn v9)

// @simplewebauthn/server v9.x
const opts = generateRegistrationOptions({
  // ...
  userID: 'randomUserID',
});
// @simplewebauthn/browser v9.x
const credential = await startAuthentication(...);
sendToServer(credential);
// @simplewebauthn/server v9.x
const credential = await receiveFromBrowser();
console.log(
  credential.response.userhandle, // 'randomUserID'
);

After (SimpleWebAuthn v10)

// @simplewebauthn/server v10.x
import { isoUint8Array } from '@simplewebauthn/server/helpers';

const opts = generateRegistrationOptions({
  // ...
  userID: isoUint8Array.fromUTF8String('randomUserID'),
});
// @simplewebauthn/browser v10.x
const credential = await startAuthentication(...);
sendToServer(credential);
// @simplewebauthn/server v10.x
import { isoBase64URL } from '@simplewebauthn/server/helpers';

const credential = await receiveFromBrowser();
console.log(
  isoBase64URL.toUTF8String(credential.response.userhandle), // 'randomUserID'
);

[server] isoBase64URL.toString() and isoBase64URL.fromString() have been renamed

The method names have been updated to reflect the use of UTF-8 string encoding:

Before:

const foo = isoBase64URL.toString('...');
const bar = isoBase64URL.fromString('...');

After:

const foo = isoBase64URL.toUTF8String('...');
const bar = isoBase64URL.fromUTF8String('...');

[server] rpID is now a required argument when calling generateAuthenticationOptions()

Update calls to this method to specify the same rpID as passed into
generateRegistrationOptions():

Before

  generateRegistrationOptions({ rpID: 'example.com', ... });
generateAuthenticationOptions();

After

  generateRegistrationOptions({ rpID: 'example.com', ... });
generateAuthenticationOptions({ rpID: 'example.com' });
SimpleWebAuthn -

Published by MasterKale 8 months ago

Packages

Changes

  • [server] Fixed "Cannot find module 'cbor-x/index-no-eval' or its corresponding type declarations" build errors when transpiling TypeScript projects using @simplewebauthn/server (#521)
SimpleWebAuthn -

Published by MasterKale 8 months ago

Packages

Changes

  • [server] Improved support for Next.js Edge runtime
    (#518, with thanks to @balazsorban44)
SimpleWebAuthn -

Published by MasterKale 9 months ago

Packages

Changes

  • [server] Fixed an issue with use with CBOR handling in runtime environments that restrict use of eval() (#511, with thanks to @Maronato)
  • [browser, types] Monorepo version sync
SimpleWebAuthn - v9.0.0 - The one in which 11 characters were saved

Published by MasterKale 9 months ago

Packages

Changes

  • [types] The @simplewebauthn/typescript-types package has been renamed to
    @simplewebauthn/types (#508)

Breaking Changes

  • Any reference to @simplwebauthn/typescript-types will need to be replaced with the new package name @simplewebauthn/types:

Before:

import { ... } from '@simplwebauthn/typescript-types';

After:

$> npm uninstall @simplewebauthn/typescript-types
$> npm install -D @simplewebauthn/types
import { ... } from '@simplwebauthn/types';
SimpleWebAuthn -

Published by MasterKale 9 months ago

Packages

Changes

  • [browser] The WebAuthnError class can now be imported from @simplewebauthn/browser for simpler error detection and handling when calling startRegistration() and startAuthentication() (#505, with thanks to @zoontek)
  • [server] The COSEPublicKeyEC2, COSEPublicKeyOKP, and COSEPublicKeyRSA types can now be imported from @simplwebauthn/server/helpers to help type possible return values from decodeCredentialPublicKey() (#504, with thanks to @mmv08)
  • [server] Custom challenge strings passed to generateRegistrationOptions() will now be treated as UTF-8 strings to align with the existing behavior of generateAuthenticationOptions() (#507)
SimpleWebAuthn -

Published by MasterKale 10 months ago

Packages

Changes

  • [server] Updated dependencies to fix an issue with ASN.1 parsing when calling
    verifyAuthenticationResponse() (#499)
SimpleWebAuthn -

Published by MasterKale 12 months ago

Packages

Changes

  • [server] Use of the Web Crypto API in edge runtimes has been improved
    (#472)
SimpleWebAuthn -

Published by MasterKale 12 months ago

Packages

Changes

  • [server] The library will now try to use globalThis.crypto first before trying to import
    Node's node:crypto as a fallback (#468)
  • [browser, types] Version sync
SimpleWebAuthn -

Published by MasterKale 12 months ago

Packages

Changes

  • [server, types] deno vendor will no longer error out because typescript-types/src/dom.ts
    is missing (#466)
  • [server] Authenticator data will now be preserved after bad CBOR encoding is detected and
    temporarily fixed when handling security key responses from Firefox
    (#465)
  • [browser] Version sync due to changes in typescript-types
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [server] The cbor-x dependency is now used without pulling in the Node-specific stream API
    for better Web API environment compatibility
    (#455, with thanks to @Maronato)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [browser] Calling startAuthentication(..., true) to set up conditional UI will now require
    the "webauthn" value in an input's autocomplete="..." be either the only value or the last
    value (#451)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [browser] The WebAuthnAbortService singleton can now be imported, with a cancelCeremony()
    method that can be called to manually cancel any active WebAuthn ceremonies. This can be used by
    developers building projects that use client-side routing to better control the behavior of their
    UX in response to router navigation events.
    (#449)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [browser] startRegistration() will visibly warn in the browser console when a WebAuthn API method call errors out in a way that is likely due to a browser extension intercepting the API. The original error is exposed as the cause property on the error. (#447)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [browser] startRegistration() will no longer error out on registration responses generated
    by the 1Password browser extension (#443, with thanks to @unix)
  • [browser] Helper methods base64URLStringToBuffer() and bufferToBase64URLString() are now
    exported from @simplewebauthn/browser (#444)
  • [server] verifyRegistrationResponse() and verifyAuthenticationResponse() now accept a new
    expectedType argument that can be used to, for example, verify Secure Payment Confirmation
    responses (#436, with thanks to @fabiancook)
  • [server] Responses containing malformed authenticator data returned from Firefox 117 will no
    longer raise an error (#441)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [server] Debug logger output from MetadataService has been disabled
    (#434)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [server] The expectedChallenge argument for verifyRegistrationResponse() and
    verifyAuthenticationResponse() methods now also accept asynchronous methods
    (#432, with thanks to @jordanbtucker)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [browser] The NPM package now targets ES2021 for support in older browsers like Safari 13.1
    (#429)
SimpleWebAuthn -

Published by MasterKale about 1 year ago

Packages

Changes

  • [server] Node projects with "type": "module" in their package.json will no longer error
    out when trying to use methods that leverage the Crypto APIs
    (#428)
SimpleWebAuthn - v8.0.0 - Around the (ESM) World

Published by MasterKale about 1 year ago

This major release marks the completion of a long journey that started with the release of v7.0.0:
SimpleWebAuthn is now available for use in non-Node projects! 🎉

SimpleWebAuthn debuted in mid-2020 as a combination of libraries aiming to make WebAuthn simpler to
use across browsers and "NodeJS + CommonJS" applications. Since then NodeJS has evolved to gain ESM
support, and additional JavaScript and TypeScript runtimes have debuted that offer ESM-centric,
TypeScript-first alternatives while also implementing Web APIs to offer a more consistent and
capable execution environment for developers.

I've wanted to make this project available to developers using these Node alternatives to help them
get past some of WebAuthn's rough spots. Today I'm happy to announce that this goal has been
achieved! 😌

See the Changes below for more information, as well as additional information on breaking
changes made in this release.

Packages

Changes

  • [server] [typescript-types] SimpleWebAuthn can now also be used in runtimes other than Node.
    Deno is now a first-class runtime for this project alongside Node.
    • The following list of runtimes are officially supported:
    • The following list of runtimes are periodically tested but unofficially supported:
      • (New) CloudFlare Workers
      • (New) Bun
  • [browser] Version sync

Breaking Changes

  • [server] generateRegistrationOptions() and generateAuthenticationOptions() are now
    asynchronous methods. Refactor calls to these methods to handle the Promise that's now returned
    in whatever way is appropriate for your project.
  • [server] generateChallenge() (in @simplewebauthn/server/helpers) is now an asynchronous
    method. Refactor calls to this method to handle the Promise that's now returned in whatever way
    is appropriate for your project.
Package Rankings
Top 1.5% on Npmjs.org
Top 5.88% on Deno.land
Badges
Extracted from project README
npm (scoped)
Related Projects