网络身份验证扩展
The Web Authentication API has a system of extensions — extra functionality that can be requested during credential creation (navigator.credentials.create()
) or authentication (navigator.credentials.get()
) operations. This article explains how to request WebAuthn extensions, retrieve information about the responses from those requests, and the available extensions — including browser support and expected inputs and outputs.
如何使用 WebAuthn 扩展
When invoking navigator.credentials.create()
or navigator.credentials.get()
, the publicKey
object parameter required to initiate a WebAuthn flow can include an extensions
property. The value of extensions
is itself an object, the properties of which are the input values for any extensions the relying party wishes to request the use of in the method you call.
Behind the scenes, the inputs are processed by the user agent and/or the authenticator.
For example, in a publicKey
object for a create()
call, we might want to request the use of two extensions
- The
credProps
extension. Relying parties setcredProps
to request that the browser tells the relying party whether the credential is resident/discoverable after registration. This is useful when callingcreate()
withpublicKey.authenticatorSelection.residentKey = "preferred"
. To request it, you also need to setpublicKey.extensions.credProps = true
when the browser makes a credential and, depending on the type of authenticator used, it will be discoverable (for example, the FIDO2 authenticator would typically make it discoverable; FIDO1/U2F security key would be non-discoverable).credProps
is processed by the user agent only. - The
minPinLength
extension allows relying parties to request the authenticator's minimum PIN length. This requiresextensions.minPinLength
to be set totrue
.minPinLength
is processed by the authenticator, with the user agent only serving to pass the input data along to it.
const publicKey = {
challenge: new Uint8Array([117, 61, 252, 231, 191, 241, ...]),
rp: { id: "acme.com", name: "ACME Corporation" },
user: {
id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
name: "jamiedoe",
displayName: "Jamie Doe"
},
pubKeyCredParams: [ {type: "public-key", alg: -7} ],
authenticatorSelection: {
residentKey: "preferred"
},
extensions: {
credProps: true,
minPinLength: true
}
}
We can then pass the publicKey
object into a create()
call to initiate the credential creation flow
navigator.credentials.create({ publicKey });
检索扩展请求结果
If successful, the create()
call will return a Promise
that resolves with a PublicKeyCredential
object. Once extension processing has completed, the results of the processing are communicated in the response (although not in all cases — it is possible for extensions to have no output).
navigator.credentials
.create({ publicKey })
.then((publicKeyCred) => {
const myClientExtResults = publicKeyCred.getClientExtensionResults();
// myClientExtResults will contain the output of processing
// the "credProps" extension
const authData = publicKeyCred.response.getAuthenticatorData();
// authData will contain authenticator data, which will include
// authenticator extension processing results, i.e., minPinLength
})
.catch((err) => {
console.error(err);
});
As demonstrated by the above code snippet, there are two different places to find your output extension results
- You can find the results of client (user agent) extension processing by calling the
PublicKeyCredential.getClientExtensionResults()
method. This returns amap
, with each entry being an extensions' identifier string as the key, and the output from the processing of the extension by the client as the value. In the example above, if the browser supported thecredProps
extension and it was processed correctly, themyClientExtResults
map object would contain one entry,"credProps"
, with a value of{ rk: true }
. This would verify that the created credential is indeed discoverable. - You can find the results of authenticator extension processing in the authenticator data for the operation
- In the case of
PublicKeyCredential
s returned from successfulcreate()
calls, this can be returned via a call topublicKeyCredential.response.getAuthenticatorData()
. - In the case of
PublicKeyCredential
s returned from successfulget()
calls, this can be found in thepublicKeyCredential.response.authenticatorData
property.
ArrayBuffer
with a consistent structure — see authenticator data. The authenticator extension results data is always found in a section at the end, as a CBOR map representing the results. SeeAuthenticatorAssertionResponse.authenticatorData
for a detailed description of the complete authenticator data structure. Back to our example, if the relying party is authorized to receive theminPinLength
value, the authenticator data would contain a representation of it in the following form:"minPinLength": uint
. - In the case of
可用扩展
The extensions below do not represent an exhaustive list of all the extensions available. We have elected to document extensions that we know to be standardized and supported by at least one rendering engine.
appid
- Usable in: Authentication (
get()
) - Processed by: User agent
- Specification: FIDO AppID Extension (appid)
Allows a relying party to request an assertion for a credential previously registered using the legacy FIDO U2F JavaScript API, avoiding the hassle of re-registering the credential. The appid
is that API's equivalent to the rpId
in WebAuthn (although bear in mind that appid
s are in the form of URLs, whereas rpId
s are in the form of domains).
Input
The publicKey
's extensions
property must contain an appid
property, the value of which is the application identifier used in the legacy API. For example
extensions: {
appid: "https://accounts.example.com";
}
You must also list the FIDO U2F credential IDs in the publicKey
's allowCredentials
property, for example
allowCredentials: {
[
id: arrayBuffer, // needs to contain decoded binary form of id
transports: ["nfc", "usb"]
type: "public-key"
]
}
Output
Outputs appid: true
if the appid
was successfully used for the assertion, or appid: false
otherwise.
appidExclude
- Usable in: Registration (
create()
) - Processed by: User agent
- Specification: FIDO AppID Exclusion Extension (appidExclude)
Allows a relying party to exclude authenticators containing specified credentials previously registered using the legacy FIDO U2F JavaScript API during registration. This is required because by default the contents of the excludeCredentials
field are assumed to be WebAuthn credentials. When using this extension, you can include legacy FIDO U2F credentials inside excludeCredentials
, and they will be recognized as such.
Input
The publicKey
's extensions
property must contain an appidExclude
property, the value of which is the identifier of the relying party requesting to exclude authenticators by legacy FIDO U2F credentials. For example
extensions: {
appidExclude: "https://accounts.example.com";
}
You can then list FIDO U2F credentials in the publicKey
's excludeCredentials
property, for example
excludeCredentials: {
[
id: arrayBuffer, // needs to contain decoded binary form of id
transports: ["nfc", "usb"]
type: "public-key"
]
}
Output
Outputs appidExclude: true
if the extension was acted upon, or appidExclude: false
otherwise.
credProps
- Usable in: Registration (
create()
) - Processed by: User agent
- Specification: Credential Properties Extension (credProps)
Allows a relying party to request additional information/properties about the credential that was created. This is currently only useful when calling create()
with publicKey.authenticatorSelection.residentKey = "preferred"
; it requests information on whether the created credential is discoverable.
Input
The publicKey
's extensions
property must contain a credProps
property with a value of true
extensions: {
credProps: true;
}
You must also set authenticatorSelection.requireResidentKey
to true
, which indicates that a resident key is required.
authenticatorSelection: {
requireResidentKey: true;
}
Output
Outputs the following if the registered PublicKeyCredential
is a client-side discoverable credential
credProps: {
rk: true;
}
If rk
is set to false
in the output, the credential is a server-side credential. If rk
is not present in the output, then it is not known whether the credential is client-side discoverable or server-side.
credProtect
- Usable in: Registration (
create()
) - Processed by: Authenticator
- Specification: Credential Protection (credProtect)
Allows a relying party to specify a minimum credential protection policy when creating a credential.
Input
The publicKey
's extensions
property must contain a credentialProtectionPolicy
property specifying the protection level of the credential to be created, and a boolean enforceCredentialProtectionPolicy
property specifying whether the create()
call should fail rather than creating a credential that does not conform to the specified policy
extensions: {
credentialProtectionPolicy: "userVerificationOptional",
enforceCredentialProtectionPolicy: true
}
The available credentialProtectionPolicy
values are as follows
"userVerificationOptional"
Experimental-
User verification is optional. The equivalent
credProtect
value sent to the authenticator for processing is0x01
. "userVerificationOptionalWithCredentialIDList"
-
User verification is optional only if the credential is discoverable (i.e., it is client-side discoverable). The equivalent
credProtect
value sent to the authenticator for processing is0x02
. "userVerificationRequired"
-
用户验证始终是必需的。发送到身份验证器以进行处理的等效
credProtect
值为0x03
。
注意:Chromium 将默认使用userVerificationOptionalWithCredentialIDList
或userVerificationRequired
,具体取决于请求类型。
- 如果将
residentKey
设置为preferred
或required
,Chromium 在创建凭据时将请求userVerificationOptionalWithCredentialIDList
的保护级别。(将requireResidentKey
设置为required
与将residentKey
设置为required
相同。)这确保了简单的安全密钥的物理占有不会允许查询给定rpId
的可发现凭据的存在。 - 此外,如果
residentKey
为required
并且userVerification
为preferred
,则保护级别将提升至userVerificationRequired
。这确保了安全密钥的物理占有不会允许登录到不需要用户验证的网站。(这不是完全保护;网站仍应仔细考虑其用户的安全。) - 如果网站请求显式的
credProtect
级别,则将覆盖这些默认值。这些默认值永远不会导致保护级别低于安全密钥的默认值(如果安全密钥的默认值更高)。
假设enforceCredentialProtectionPolicy
值为true
。在这种情况下,如果无法遵守策略(例如,它需要用户验证,但身份验证器不支持用户验证),则create()
调用将失败。如果它为false
,系统将尽力创建符合策略的凭据,但如果无法实现,它仍然会创建一个尽可能符合策略的凭据。
Output
如果create()
调用成功,则身份验证器数据将包含一个表示credProtect
值的表示形式,该值以以下形式表示设置的策略。
{ "credProtect": 0x01 }
largeBlob
- 可用在:注册(
create()
)和身份验证(get()
) - Processed by: User agent
- 规范:大型 Blob 存储扩展(largeBlob)
允许依赖方在身份验证器上存储与凭据关联的 Blob——例如,它可能希望直接存储证书而不是运行集中的身份验证服务。
Input
在create()
调用期间,publicKey
的extensions
属性必须包含一个largeBlob
属性,该属性具有以下对象结构
extensions: {
largeBlob: {
support: "required";
}
}
support
属性的值是一个字符串,可以是以下之一
"preferred"
:如果可能,凭据将使用能够存储 Blob 的身份验证器创建,但如果不可能,它仍然会创建凭据。输出的support
属性报告了身份验证器存储 Blob 的能力。"required"
:凭据将使用能够存储 Blob 的身份验证器创建。如果不可能,create()
调用将失败。
在get()
调用期间,publicKey
的extensions
属性必须包含一个largeBlob
属性,该属性具有两个子属性之一——read
或write
(如果两者都存在,则get()
失败)。
read
属性是一个布尔值。值为true
表示依赖方希望获取与断言的凭据关联的先前写入的 Blob。
extensions: {
largeBlob: {
read: true;
}
}
write
属性的值为一个ArrayBuffer
、TypedArray
或DataView
,它表示依赖方希望与现有凭据一起存储的 Blob。
extensions: {
largeBlob: {
write: arrayBuffer;
}
}
注意:要使写入身份验证操作成功,publicKey.allowCredentials
必须只包含一个元素,表示您希望 Blob 与其一起存储的凭据。
Output
如果注册的凭据能够存储 Blob,则成功的create()
调用将提供以下扩展输出
largeBlob: {
supported: true; // false if it cannot store blobs
}
如果成功,则get()
读取调用会使 Blob 作为ArrayBuffer
在扩展输出中可用。
largeBlob: {
blob: arrayBuffer;
}
注意:如果失败,将返回largeBlob
对象,但blob
将不存在。
get()
写入调用将在扩展输出中使用written
布尔值指示写入操作是否成功。值为true
表示它已成功写入关联的身份验证器,值为false
表示它未成功写入。
largeBlob: {
written: true;
}
minPinLength
- Usable in: Registration (
create()
) - Processed by: Authenticator
- 规范:最小 PIN 长度扩展 (minPinLength)
允许依赖方请求身份验证器的最小 PIN 长度。
Input
publicKey
的extensions
属性必须包含一个minPinLength
属性,其值为true
。
extensions: {
minPinLength: true;
}
Output
如果依赖方有权接收minPinLength
值(如果其rpId
存在于身份验证器的授权依赖方列表中),则身份验证器数据将包含以下形式的表示形式
{"minPinLength": uint}
如果依赖方未经授权,则会忽略该扩展,并且不会提供"minPinLength"
输出值。
payment
允许依赖方请求创建 WebAuthn 凭据,该凭据可由依赖方和其他方使用——使用安全支付确认;请参阅使用安全支付确认。
Input
payment
扩展的输入在AuthenticationExtensionsPaymentInputs 字典中定义
isPayment
-
一个布尔值,表示该扩展处于活动状态。
rpID
-
正在使用的凭据的依赖方 ID。仅在身份验证时使用;不在注册时使用。
topOrigin
-
顶级框架的来源。仅在身份验证时使用;不在注册时使用。
payeeName
-
收款人姓名(如果存在),显示给用户。仅在身份验证时使用;不在注册时使用。
payeeOrigin
-
收款人来源(如果存在),显示给用户。仅在身份验证时使用;不在注册时使用。
total
-
显示给用户的交易金额。仅在身份验证时使用;不在注册时使用。总金额的类型为PaymentCurrencyAmount。
instrument
-
显示给用户的工具详细信息。仅在身份验证时使用;不在注册时使用。工具的类型为PaymentCredentialInstrument。
Output
无
规范
WebAuthn 扩展的规范位置有很多。IANA 的WebAuthn 扩展标识符提供所有扩展的注册表,但请注意,一些扩展可能已弃用。
指定扩展的位置
浏览器兼容性
api.CredentialsContainer.create.publicKey_option.extensions
BCD 表格仅在浏览器中加载
api.CredentialsContainer.get.publicKey_option.extensions
BCD 表格仅在浏览器中加载