Skip to content

Commit 83561d0

Browse files
authored
PublicKeyCredential.getClientCapabilities - add (#37734)
1 parent b13d9d6 commit 83561d0

File tree

5 files changed

+274
-11
lines changed

5 files changed

+274
-11
lines changed

files/en-us/web/api/authenticatorattestationresponse/gettransports/index.md

+13-7
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,19 @@ None.
2424

2525
### Return value
2626

27-
An {{jsxref("Array")}} of strings representing the different transports supported by the authenticator, in lexicographical order. Values may include:
28-
29-
- `"ble"`: The authenticator may be used over [BLE (Bluetooth Low Energy)](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy).
30-
- `"hybrid"`: The authenticator can be used over a combination of (often separate) data transport and proximity mechanisms. This supports, for example, authentication on a desktop computer using a smartphone.
31-
- `"internal"`: The authenticator is specifically bound to the client device (cannot be removed).
32-
- `"nfc"`: The authenticator may be used over [NFC (Near Field Communication)](https://en.wikipedia.org/wiki/Near-field_communication).
33-
- `"usb"`: The authenticator can be contacted over USB.
27+
An {{jsxref("Array")}} of strings representing the different transports supported by the authenticator, in lexicographical order.
28+
Values may include:
29+
30+
- `ble`
31+
- : The authenticator may be used over [BLE (Bluetooth Low Energy)](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy).
32+
- `"hybrid"`
33+
- : The authenticator can be used over a combination of (often separate) data transport and proximity mechanisms. This supports, for example, authentication on a desktop computer using a smartphone.
34+
- `"internal"`
35+
- : The authenticator is specifically bound to the client device (cannot be removed).
36+
- `"nfc"`
37+
- : The authenticator may be used over [NFC (Near Field Communication)](https://en.wikipedia.org/wiki/Near-field_communication).
38+
- `"usb"`
39+
- : The authenticator can be contacted over USB.
3440

3541
## Examples
3642

files/en-us/web/api/credentialscontainer/get/index.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,20 @@ get(options)
3636

3737
- : A string indicating whether the user will be required to login for every visit to a client app. The value can be one of the following:
3838

39-
- `"conditional"`: Discovered credentials are presented to the user in a non-modal dialog box along with an indication of the origin requesting credentials. In practice, this means autofilling available credentials; see [Sign in with a passkey through form autofill](https://web.dev/articles/passkey-form-autofill) for more details of how this is used; {{domxref("PublicKeyCredential.isConditionalMediationAvailable_static", "PublicKeyCredential.isConditionalMediationAvailable()")}} also provides some useful information.
39+
- `"conditional"`
4040

41-
- `"optional"`: If credentials can be handed over for a given operation without user mediation, they will be, enabling automatic reauthentication without user mediation. If user mediation is required, then the user agent will ask the user to authenticate. This value is intended for situations where you have reasonable confidence that a user won't be surprised or confused at seeing a login dialog box — for example on a site that doesn't automatically log users in, when a user has just clicked a "Login/Signup" button.
41+
- : Discovered credentials are presented to the user in a non-modal dialog box along with an indication of the origin requesting credentials. In practice, this means autofilling available credentials; see [Sign in with a passkey through form autofill](https://web.dev/articles/passkey-form-autofill) for more details of how this is used; {{domxref("PublicKeyCredential.isConditionalMediationAvailable_static", "PublicKeyCredential.isConditionalMediationAvailable()")}} also provides some useful information.
4242

43-
- `"required"`: The user will always be asked to authenticate, even if prevent silent access (see {{domxref("CredentialsContainer.preventSilentAccess()")}}) is set to `false`. This value is intended for situations where you want to force user authentication — for example if you want a user to reauthenticate when a sensitive operation is being performed (like confirming a credit card payment), or when switching users.
43+
- `"optional"`
4444

45-
- `"silent"`: The user will not be asked to authenticate. The user agent will automatically reauthenticate the user and log them in if possible. If consent is required, the promise will fulfill with `null`. This value is intended for situations where you would want to automatically sign a user in upon visiting a web app if possible, but if not, you don't want to present them with a confusing login dialog box. Instead, you'd want to wait for them to explicitly click a "Login/Signup" button.
45+
- : If credentials can be handed over for a given operation without user mediation, they will be, enabling automatic reauthentication without user mediation. If user mediation is required, then the user agent will ask the user to authenticate. This value is intended for situations where you have reasonable confidence that a user won't be surprised or confused at seeing a login dialog box — for example on a site that doesn't automatically log users in, when a user has just clicked a "Login/Signup" button.
46+
47+
- `"required"`
48+
49+
- : The user will always be asked to authenticate, even if prevent silent access (see {{domxref("CredentialsContainer.preventSilentAccess()")}}) is set to `false`. This value is intended for situations where you want to force user authentication — for example if you want a user to reauthenticate when a sensitive operation is being performed (like confirming a credit card payment), or when switching users.
50+
51+
- `"silent"`
52+
- : The user will not be asked to authenticate. The user agent will automatically reauthenticate the user and log them in if possible. If consent is required, the promise will fulfill with `null`. This value is intended for situations where you would want to automatically sign a user in upon visiting a web app if possible, but if not, you don't want to present them with a confusing login dialog box. Instead, you'd want to wait for them to explicitly click a "Login/Signup" button.
4653

4754
The default value is `"optional"`.
4855

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
---
2+
title: "PublicKeyCredential: getClientCapabilities() static method"
3+
short-title: getClientCapabilities()
4+
slug: Web/API/PublicKeyCredential/getClientCapabilities_static
5+
page-type: web-api-static-method
6+
browser-compat: api.PublicKeyCredential.getClientCapabilities_static
7+
---
8+
9+
{{APIRef("Web Authentication API")}}{{securecontext_header}}
10+
11+
The **`getClientCapabilities()`** static method of the {{domxref("PublicKeyCredential")}} interface returns a {{jsxref("Promise")}} that resolves with an object that can be used to check whether or not particular WebAuthn client capabilities and [extensions](/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions) are supported.
12+
13+
A relying party (RP) can use this information to appropriately customize its sign-in and sign-up user interfaces and workflows.
14+
15+
## Syntax
16+
17+
```js-nolint
18+
PublicKeyCredential.getClientCapabilities()
19+
```
20+
21+
### Parameters
22+
23+
None.
24+
25+
### Return value
26+
27+
A {{jsxref("Promise")}} that resolves to an object where the property names are the client capability strings, and the values are boolean values that indicate whether or not the corresponding capability or extension is supported.
28+
29+
The WebAuthn client capability strings are:
30+
31+
- `"conditionalCreate"`
32+
- : The client is capable of creating [discoverable credentials](/en-US/docs/Web/API/Web_Authentication_API#discoverable_credentials_and_conditional_mediation).
33+
- `"conditionalGet"`
34+
- : The client is capable of authenticating using [discoverable credentials](/en-US/docs/Web/API/Web_Authentication_API#discoverable_credentials_and_conditional_mediation).
35+
This capability is equivalent to [`isConditionalMediationAvailable()`](/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable_static) resolving to `true`.
36+
- `"hybridTransport"`
37+
- : The client supports usage of the [hybrid](/en-US/docs/Web/API/AuthenticatorAttestationResponse/getTransports#hybrid) transport.
38+
This means that the client can use authenticators that rely on Bluetooth, NFC, or USB.
39+
- `"passkeyPlatformAuthenticator"`
40+
- : The client allows usage of a passkey authenticator that supports multi-factor authentication mechanisms such as a PIN or biometric check.
41+
The authenticator can be part of the same platform (device) as the client, or connected via a hybrid transport such as Bluetooth or USB.
42+
The credentials are stored on the authenticator.
43+
See [Passkeys developer guide for relying parties](https://developers.google.com/identity/passkeys/developer-guides).
44+
- `userVerifyingPlatformAuthenticator`
45+
- : The client has a platform authenticator (part of the same device) that supports multi-factor authentication mechanisms, such as a PIN or biometric check.
46+
The credentials may be stored on either the RP or the authenticator.
47+
- `relatedOrigins`
48+
- : The client supports [Related Origin Requests](https://web.dev/articles/webauthn-related-origin-requests).
49+
These clients allow a passkey to be used across multiple sites that have the same origin.
50+
- `signalAllAcceptedCredentials`
51+
- : The client supports the [`PublicKeyCredential.signalAllAcceptedCredentials()`](/en-US/docs/Web/API/PublicKeyCredential/signalAllAcceptedCredentials_static) static method.
52+
If not supported, RP workflows will need to prompt the user to manually delete credentials on the authenticator.
53+
- `signalCurrentUserDetails`
54+
- : The client supports the [`PublicKeyCredential.signalCurrentUserDetails()`](/en-US/docs/Web/API/PublicKeyCredential/signalCurrentUserDetails_static) static method.
55+
If not supported, RP workflows will need to prompt the user to manually update user details on the authenticator.
56+
- `signalUnknownCredential`
57+
- : The client supports the [`PublicKeyCredential.signalUnknownCredential()`](/en-US/docs/Web/API/PublicKeyCredential/signalUnknownCredential_static) static method.
58+
If not supported, RP workflows will need to prompt the user to manually delete credentials from the authenticator.
59+
60+
The [web extension](/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions) strings are formatted by prefixing the [extension identifier](/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions#available_extensions) with the prefix `extension:`.
61+
For example, the key `extension:appid` can be used to check if the [`appid` extension](/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions#appid) is supported.
62+
63+
### Exceptions
64+
65+
The returned {{jsxref("Promise")}} may be rejected with the following values:
66+
67+
- `NotAllowedError` {{domxref("DOMException")}}
68+
- : The Web Authentication API is not allowed in the current browsing context.
69+
For example, it might be blocked by a permission policy.
70+
71+
## Description
72+
73+
`getClientCapabilities()` allows you to check if a given capability or extension is supported, and use the information to offer an appropriate user experience.
74+
75+
For example, support for the `userVerifyingPlatformAuthenticator` capability indicates that biometrics such as a fingerprint sensor are allowed.
76+
A web application could use this to display a fingerprint icon if the capability is supported, or a password input if it is not.
77+
If biometric login is required, then it could instead provide notification that the site cannot authenticate using this browser or device.
78+
Similarly, `conditionalGet` indicates that the client supports conditional mediation when signing in a user, which means the browser can provide auto-filled discoverable credentials in a login form (for example an autocompleting text field or a drop-down list), along with a sign-in button.
79+
80+
If the value of a given capability is present in the returned object, then `true` indicates that the capability is currently supported, and `false` indicates that it is not.
81+
However, if a key is not present for a particular capability, no assumptions can be made about the availability of the associated feature.
82+
83+
For an extension the assumptions are the same.
84+
Note though, that even if the extension is supported by the client a particular authenticator may not support that extension, so RPs must not assume that this is a guarantee that the authenticator processing steps for that extension will be performed.
85+
If the key is not present for an extension, an RP can't assume that the client processing steps for that extension will be carried out by this client, or that the extension will be forwarded to the authenticator.
86+
87+
## Examples
88+
89+
### Check all capabilities
90+
91+
This example shows how to get the capabilities object and iterate its values.
92+
93+
```html hidden
94+
<pre id="log"></pre>
95+
```
96+
97+
```js hidden
98+
const logElement = document.querySelector("#log");
99+
function log(text) {
100+
logElement.innerText = `${logElement.innerText}${text}\n`;
101+
logElement.scrollTop = logElement.scrollHeight;
102+
}
103+
```
104+
105+
```css hidden
106+
#log {
107+
height: 230px;
108+
overflow: scroll;
109+
padding: 0.5rem;
110+
border: 1px solid black;
111+
}
112+
```
113+
114+
#### JavaScript
115+
116+
First we await `getClientCapabilities()` to get an object containing the capabilities.
117+
We then iterate the object and log the result (logging code not shown):
118+
119+
```js
120+
async function checkClientCapabilities() {
121+
const capabilities = await PublicKeyCredential.getClientCapabilities();
122+
123+
if (capabilities) {
124+
log("Client Capabilities:");
125+
126+
for (const [key, value] of Object.entries(capabilities)) {
127+
log(` ${key}: ${value}`);
128+
}
129+
}
130+
}
131+
```
132+
133+
Before calling the function we check that it is defined, and log the result.
134+
135+
```js
136+
// Call the function to check capabilities.
137+
if (PublicKeyCredential.getClientCapabilities) {
138+
checkClientCapabilities();
139+
} else {
140+
log(
141+
"PublicKeyCredential.getClientCapabilities() is not supported on this browser.",
142+
);
143+
}
144+
```
145+
146+
#### Result
147+
148+
{{EmbedLiveSample("Check all capabilities", "", "280")}}
149+
150+
### Test for user verifying platform authenticator
151+
152+
This example checks a single capability, `userVerifyingPlatformAuthenticator`. A real application might use the result to configure the user interface.
153+
154+
```html hidden
155+
<pre id="log"></pre>
156+
```
157+
158+
```js hidden
159+
const logElement = document.querySelector("#log");
160+
function log(text) {
161+
logElement.innerText = `${logElement.innerText}${text}\n`;
162+
logElement.scrollTop = logElement.scrollHeight;
163+
}
164+
```
165+
166+
```css hidden
167+
#log {
168+
height: 40px;
169+
overflow: scroll;
170+
padding: 0.5rem;
171+
border: 1px solid black;
172+
}
173+
```
174+
175+
#### JavaScript
176+
177+
The code is similar to the previous example, except that we check a particular returned capability, and we use `try...catch` to catch the case where `getClientCapabilities()` is not supported.
178+
179+
```js
180+
checkisUserVerifyingPlatformAuthenticatorAvailable();
181+
182+
async function checkisUserVerifyingPlatformAuthenticatorAvailable() {
183+
try {
184+
const capabilities = await PublicKeyCredential.getClientCapabilities();
185+
186+
if (capabilities.userVerifyingPlatformAuthenticator) {
187+
log("Biometric login supported");
188+
} else {
189+
log("Biometric login not supported. Do password.");
190+
}
191+
} catch (error) {
192+
if (error instanceof TypeError) {
193+
log(
194+
"PublicKeyCredential.getClientCapabilities() is not supported on this browser.",
195+
);
196+
} else {
197+
log(`Unexpected error: ${error}`);
198+
}
199+
}
200+
}
201+
```
202+
203+
Note that here we log the result of a check.
204+
In a real application we might update the user interface to show appropriate options for verifying the user.
205+
206+
#### Result
207+
208+
The log below displays either a string indicating the method is not supported, or one that indicates whether biometric or password login is supported.
209+
210+
{{EmbedLiveSample("Test for user verifying platform authenticator", "", "90")}}
211+
212+
## Specifications
213+
214+
{{Specifications}}
215+
216+
## Browser compatibility
217+
218+
{{Compat}}
219+
220+
## See also
221+
222+
- [Web Authentication API](/en-US/docs/Web/API/Web_Authentication_API)

files/en-us/web/api/publickeycredential/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ The **`PublicKeyCredential`** interface provides information about a public key
3333

3434
## Static methods
3535

36+
- {{domxref("PublicKeyCredential.getClientCapabilities_static", "PublicKeyCredential.getClientCapabilities()")}}
37+
- : Returns a {{jsxref("Promise")}} that resolves with an object that can be used to check whether or not particular WebAuthn capabilities and [extensions](/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions) are supported.
3638
- {{domxref("PublicKeyCredential.isConditionalMediationAvailable_static", "PublicKeyCredential.isConditionalMediationAvailable()")}}
3739
- : Returns a {{jsxref("Promise")}} which resolves to `true` if conditional mediation is available.
3840
- {{domxref("PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable_static", "PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()")}}

files/en-us/web/api/web_authentication_api/index.md

+26
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,32 @@ A typical authentication flow is as follows:
117117

118118
5. Once verified by the server, the authentication flow is considered successful.
119119

120+
### Customizing workflows based on client capabilities
121+
122+
The signup and login workflows can be customized based on the capabilities of the WebAuthn client (browser). The {{domxref("PublicKeyCredential.getClientCapabilities_static", "PublicKeyCredential.getClientCapabilities()")}} static method can be used to query those capabilities; it returns an object where each key refers to a WebAuthn capability or extension, and each value is a boolean indicating support for that feature.
123+
124+
This can be used, for example, to check:
125+
126+
- Client support for various authenticators such as passkeys or biometric user verification.
127+
- Whether the client [supports methods to keep relying party and authenticator credentials in sync](/en-US/docs/Web/API/Web_Authentication_API#discoverable_credential_synchronization_methods).
128+
- Whether the client allows a single passkey to be used on different websites with the same origin.
129+
130+
The code below shows how you might use `getClientCapabilities()` to check if the client supports authenticators that offer biometric user verification.
131+
Note that the actual actions performed depend on your site.
132+
For sites that _require_ biometric authentication, you might replace the login UI with a message indicating that biometric authentication is needed, and the user should try a different browser or device.
133+
134+
```js
135+
async function checkisUserVerifyingPlatformAuthenticatorAvailable() {
136+
const capabilities = await PublicKeyCredential.getClientCapabilities();
137+
// Check the capability: userVerifyingPlatformAuthenticator
138+
if (capabilities.userVerifyingPlatformAuthenticator) {
139+
// Perform actions if biometric support is available
140+
} else {
141+
// Perform actions if biometric support is not available.
142+
}
143+
}
144+
```
145+
120146
## Controlling access to the API
121147

122148
The availability of WebAuthn can be controlled using a [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy), specifying two directives in particular:

0 commit comments

Comments
 (0)