pwshub.com

Introducing hints, Related Origin Requests and JSON serialization for WebAuthn in Chrome

Stay organized with collections Save and categorize content based on your preferences.

Chrome 128 and 129 introduces exciting new features for WebAuthn—the underlying API to build passkey-based authentication systems.

Eiji Kitamura

  • Hints: Hints give relying parties (RPs) better control over WebAuthn UI in the browser. They are especially helpful for enterprise users who want to use security keys.
  • Related origin requests: With related origin requests, RPs can make passkeys valid on multiple domains. If you own multiple sites, you can now enable your users to reuse their passkey across your sites, eliminating login friction.
  • JSON serialization: JSON serialization APIs let you simplify an RP's frontend code by encoding and decoding options and credentials passed to and from WebAuthn API.

Hints

With hints, relying parties (RP) can now specify UI preferences for creating a passkey or authenticating with a passkey.

Previously, when an RP wanted to restrict the authenticator the user can use to create a passkey or to authenticate with, they could use authenticatorSelection.authenticatorAttachment to specify "platform" or "cross-platform". They respectively limit the authenticator to a platform authenticator or a roaming authenticator. With hints, this specification can be more flexible.

The RP can use optional hints in the PublicKeyCredentialCreationOptions or PublicKeyCredentialRequestOptions to specify "security-key", "client-device" and "hybrid" in a preference order in an array.

The following is an example credential creation request that prefers "cross-platform" authenticators with "security-key" as a hint. This tells Chrome to show a security key focused UI for enterprise users.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    hints: ['security-key'],
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
By specifying 'security-key' as a hint, the browser shows a security key focused dialog.
By specifying 'security-key' as a hint, the browser shows a security key focused dialog.

When an RP wants to prioritize a cross-device verification scenario, they can send an authentication request that prefers "cross-platform" authenticators with "hybrid" as a hint.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    residentKey: true,
    hints: ['hybrid']
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
By specifying 'hybrid' as a hint, the browser shows a cross-device login focused dialog.
By specifying 'hybrid' as a hint, the browser shows a cross-device login focused dialog.

With Related Origin Requests, RPs can make passkeys usable from multiple domains. Building a centralized login experience and using federation protocols remains the recommended solution for most sites. But if you own multiple domains and federation isn't possible, related origins may be a solution.

All WebAuthn requests must specify a relying party ID (RP ID), and all passkeys are associated with a single RP ID. Traditionally, an origin could only specify an RP ID based on its domain, so in that case www.example.co.uk could specify an RP ID of example.co.uk, but not example.com. With Related Origin Requests, a claimed RP ID can be validated by fetching a well-known JSON file located at /.well-known/webauthn from the target domain. So example.co.uk (and example.in, example.de, and so on) could all use an RP ID of example.com if example.com specifies them in the following format:

URL: https://example.com/.well-known/webauthn

{
  "origins": [
    "https://example.co.uk",
    "https://example.de",
    "https://example.sg",
    "https://example.net",
    "https://exampledelivery.com",
    "https://exampledelivery.co.uk",
    "https://exampledelivery.de",
    "https://exampledelivery.sg",
    "https://myexamplerewards.com",
    "https://examplecars.com"
  ]
}

Learn how to set up Related Origin Requests at Allow passkey reuse across your sites with Related Origin Requests.

JSON serialization

WebAuthn request and response objects have multiple fields that contain raw binary data in an ArrayBuffer, such as the credential ID, user ID, or challenge. If a website wants to use JSON to exchange this data with its server, the binary data must first be encoded, for example with Base64URL. This adds unnecessary complexity for developers that want to start using passkeys on their websites.

WebAuthn now offers APIs to parse PublicKeyCredentialCreationOptions and PublicKeyCredentialRequestOptions WebAuthn request objects directly from JSON, and serialize the PublicKeyCredential response directly into JSON. All ArrayBuffer-valued fields that carry raw binary data are automatically converted from or to their Base64URL-encoded values. These APIs are available from Chrome 129.

Before creating a passkey, fetch a JSON encoded PublicKeyCredentialCreationOptions object from the server and decode it using PublicKeyCredential.parseCreationOptionsFromJSON().

export async function registerCredential() {
  // Fetch encoded `PublicKeyCredentialCreationOptions`
  // and JSON decode it.
  const options = await fetch('/auth/registerRequest').json();
  // Decode `PublicKeyCredentialCreationOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseCreationOptionsFromJSON(options);  
  // Invoke the WebAuthn create() function.
  const cred = await navigator.credentials.create({
    publicKey: decodedOptions,
  });
  ...

After creating a passkey, encode the resulting credential using toJSON() so that it can be sent to the server.

  ...
  const cred = await navigator.credentials.create({
    publicKey: options,
  });
  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());
  // Send the encoded credential to the server
  await fetch('/auth/registerResponse', credential);
  ...

Before authenticating with a passkey, fetch a JSON encoded PublicKeyRequestCreationOptions from the server and decode it using PublicKeyCredential.parseRequestOptionsFromJSON().

export async function authenticate() {
  // Fetch encoded `PublicKeyCredentialRequestOptions`
  // and JSON decode it.
  const options = await fetch('/auth/signinRequest').json();
  // Decode `PublicKeyCredentialRequestOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseRequestOptionsFromJSON(options);
  // Invoke the WebAuthn get() function.
  const cred = await navigator.credentials.get({
    publicKey: options
  });
  ...

After authenticating with a passkey, encode the resulting credential using toJSON() method so that it can be sent to the server.

  ...
  const cred = await navigator.credentials.get({
    publicKey: options
  });
  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());
  // Send the encoded credential to the server
  await fetch(`/auth/signinResponse`, credential);
  ...

Learn more

To learn more about WebAuthn and passkeys, check out the following resources:

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2024-08-30 UTC.

[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Missing the information I need" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Too complicated / too many steps" },{ "type": "thumb-down", "id": "outOfDate", "label":"Out of date" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Samples / code issue" },{ "type": "thumb-down", "id": "otherDown", "label":"Other" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Easy to understand" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Solved my problem" },{ "type": "thumb-up", "id": "otherUp", "label":"Other" }] { "lastModified": "Last updated 2024-08-30 UTC.", "confidential": False }

Source: developer.chrome.com

Related stories
1 month ago - In this tutorial, you'll learn how to create and use full-featured classes in your Python code. Classes provide a great way to solve complex programming problems by approaching them through models that represent real-world objects.
1 month ago - In this tutorial, you'll learn about assignment expressions and the walrus operator. The biggest change back in Python 3.8 was the inclusion of the := operator, which you can use to assign variables in the middle of expressions. You'll...
3 weeks ago - Follow this 7-step checklist to maximize your chances at running a successful product launch. The post Creating a successful product launch plan: A step-by-step guide appeared first on LogRocket Blog.
2 weeks ago - The Web Cache API offers sub-millisecond read latency, multi-Gbps write throughput, and unbounded storage. Here’s how you can use it.
5 days ago - Benefit from the latest in messaging with RCS on Twilio Messaging, now in public beta. Improve customer trust and deliverability with verified branding – no code changes required.
Other stories
1 hour ago - Hello, everyone! It’s been an interesting week full of AWS news as usual, but also full of vibrant faces filling up the rooms in a variety of events happening this month. Let’s start by covering some of the releases that have caught my...
2 hours ago - Nitro.js is a solution in the server-side JavaScript landscape that offers features like universal deployment, auto-imports, and file-based routing. The post Nitro.js: Revolutionizing server-side JavaScript appeared first on LogRocket Blog.
2 hours ago - Information architecture isn’t just organizing content. It's about reducing clicks, creating intuitive pathways, and never making your users search for what they need. The post Information architecture: A guide for UX designers appeared...
2 hours ago - Enablement refers to the process of providing others with the means to do something that they otherwise weren’t able to do. The post The importance of enablement for business success appeared first on LogRocket Blog.
3 hours ago - Learn how to detect when a Bluetooth RFCOMM serial port is available with Web Serial.