Authentication Yubico/凭证ID长度在证明和断言之间不匹配
我正在使用AAGUID为ff8a011f3-8c0a-4d15-8006-17111f9edc7d(Yubico v5.1提供的安全密钥)的Yubico安全密钥为我的web应用程序执行无密码身份验证。创建/注册新凭据时,我使用创建凭据选项的Authenticator Selection部分中的属性“requireResidentKey=true:Authentication Yubico/凭证ID长度在证明和断言之间不匹配,authentication,webauthn,yubico,fido,password-less,Authentication,Webauthn,Yubico,Fido,Password Less,我正在使用AAGUID为ff8a011f3-8c0a-4d15-8006-17111f9edc7d(Yubico v5.1提供的安全密钥)的Yubico安全密钥为我的web应用程序执行无密码身份验证。创建/注册新凭据时,我使用创建凭据选项的Authenticator Selection部分中的属性“requireResidentKey=true: ... authenticatorSelection: { requireResidentKey: true, // note
...
authenticatorSelection: {
requireResidentKey: true, // note the use of this attribute set to true
userVerification: options.userVerification,
authenticatorAttachment: options.authenticatorAttachment,
},
...
返回的认证数据包含16字节的凭证id:
return navigator.credentials.create({
publicKey: credentialCreateOptions,
signal: authAbortSignal,
}).then(rawAttestation => {
const attestation = {
id: rawAttestation.id, // returned 16 byte credential id
type: rawAttestation.type,
clientDataJSON: arrayBufferToString(rawAttestation.response.clientDataJSON),
attestationObject: base64encode(rawAttestation.response.attestationObject),
extensionData: base64encode(rawAttestation.getClientExtensionResults()),
}
return attestation
}).catch((error) => {
console.log(error)
if (error === 'AbortError') {
throw new Error('the operation was aborted')
} else {
throw new Error('the operation was cancelled')
}
})
例如,我将收到一个16字节的base64url id,看起来像:AUpf0KmNJrRluGG-65D54Q
然后,我使用这个16字节的id作为密钥保存生成的凭证。当我使用Yubico密钥登录时,返回的断言数据包含相同的16字节凭证id:
return navigator.credentials.get({
publicKey: credentialRequestOptions,
}).then(rawAssertion => {
const assertion = {
id: rawAssertion.id, // same 16 byte credential id as returned from create credential
type: rawAssertion.type,
clientDataJSON: arrayBufferToString(rawAssertion.response.clientDataJSON),
authenticatorData: base64encode(rawAssertion.response.authenticatorData),
signature: base64encode(rawAssertion.response.signature),
userHandle: base64encode(rawAssertion.response.userHandle),
}
return assertion
}).catch((error) => {
throw new Error(error.message)
})
然后,我可以使用此凭证id检索存储的凭证数据并验证断言。到目前为止一切都很好
当时我正在阅读W3C编辑关于Web身份验证:访问公钥凭证级别2的API的草稿,并注意到“requireResidentKey”已被弃用,取而代之的是采用枚举值的“residentKey”属性:
requireResidentKey,布尔类型,默认为false
注意:保留此成员是为了向后兼容WebAuthn级别1,但不推荐使用residentKey。如果调用者提供residentKey并且客户端可以理解后者,则将忽略requireResidentKey。否则,将使用requireResidentKey的值。请注意,requireResidentKey的值默认为false
如果在没有residentKey的情况下使用,则说明依赖方对居民凭证的要求。如果requireResidentKey设置为true,则在创建公钥凭据时,验证器必须创建客户端驻留公钥凭据源
residentKey,属于ResidentKeyRequirement类型
注意:此成员将取代requireResidentKey。如果两者都存在并且客户端理解residentKey,则使用residentKey并忽略requireResidentKey
有关residentKey值和语义的描述,请参见ResidentKeyRequirement
因此,我将requireResidentKey更改为residentKey,枚举值为“required,如下所示:
authenticatorSelection: {
residentKey: 'required', // now using residentKey attribute
requireResidentKey: true,
userVerification: options.userVerification,
authenticatorAttachment: options.authenticatorAttachment,
},
现在,当我创建一个新凭证时,我得到一个64字节的凭证ID返回。这本来可以,但当我使用Yubico安全密钥登录时,我会返回一个16字节的凭证ID,它显然与我在创建凭证阶段保存的64字节凭证ID不匹配
有趣的是,当我尝试同时使用requireResidentKey=true和residentKey='required'时,我得到了为认证和断言返回的16字节凭证ID
这可能是因为不支持新的residentKey属性吗?如果是,为什么我会得到一个64字节的凭证id?这可能是非居民凭证id的长度吗
我的代码正在使用旧的requireResidentKey属性重新工作,但我想知道这里发生了什么,以及新的Yubikey是否支持residentKey属性?有趣的是,我的非常驻密钥(仅适用于2FA)它们都有64字节的凭证ID,使用预FIDO2 Yubikey和新的Yubikey安全密钥(只有FIDO2一个)。常驻参数有一个16字节的ID。这确实表明,当您同时提供两个参数时,发生了意外情况。实际上有人支持2级吗?MDN文档不包括新的
residentKey
属性。感谢@mackie证实了我的怀疑。因此,我认为新属性还不受支持,因此它使用了requireResidentKey
的默认值,即false
。这就解释了为什么我会得到一个64字节的凭证id。有趣的是,我的非常驻密钥(仅适用于2FA)都有64字节的凭证id,使用预FIDO2 Yubikey和新的Yubikey安全密钥(仅适用于FIDO2)。常驻参数有一个16字节的ID。这确实表明,当您同时提供两个参数时,发生了意外情况。实际上有人支持2级吗?MDN文档不包括新的residentKey
属性。感谢@mackie证实了我的怀疑。因此,我认为新属性还不受支持,因此它使用了requireResidentKey
的默认值,即false
。这就解释了为什么我会得到一个64字节的凭证id。