0

我想问一个关于id和的问题rawId

在实施 webauthn 时,在身份验证器证明响应中,我看到我们同时拥有idrawId. 阅读规范(https://www.w3.org/TR/webauthn-1/#dom-publickeycredential-rawid),idbase64url(rawId)

{
  "type": "public-key",
  "id": "AV1--2gCLXLF9_5bGWDwZn6FP_OqAWfKY74mckatWMgN65o5OW8q2k9XVbYl8kAqPtpEoBlM0opKEjwDqYRBDIYbAl058O8ZQWS-r0M0L-9ikcu3tKuMxfFnRZ9gU6tnDH6QqzYwUg",
  "rawId": "AV1--2gCLXLF9_5bGWDwZn6FP_OqAWfKY74mckatWMgN65o5OW8q2k9XVbYl8kAqPtpEoBlM0opKEjwDqYRBDIYbAl058O8ZQWS-r0M0L-9ikcu3tKuMxfFnRZ9gU6tnDH6QqzYwUg",
  "response": {
    ...
  }
  ...
}

所以这是我的问题:

  • 为什么我们需要id
  • 为什么在上面的例子中,我id的完全一样rawId
    • 它总是一样吗?id如果是这样,我们可以在响应中摆脱吗?
  • 如果我将公钥保存id到数据库(稍后使用该公钥id创建allowCredentials列表),我应该遵循以下哪一个?
    1. 保存id在数据库中,用于id创建allowCredentials列表
    2. 保存base64url(rawId)在数据库中,然后使用该 base64 url​​ 编码值创建allowCredentials列表
4

2 回答 2

0

Q1。为什么我们需要 id

为什么我们同时拥有 id 和 rawId的答案是因为它是规范中的设计:

id 是从 Credential 继承的,尽管 PublicKeyCredential 会覆盖 Credential 的 getter,而是返回对象标识符内部插槽中包含的数据的 base64url 编码。
https://www.w3.org/TR/webauthn-2/#iface-pkcredential

Q2。为什么在上面的例子中,我的 id 和 rawId 完全一样?它总是一样吗?如果是这样,我们可以摆脱响应中的 id 吗?

我们返回 rawId 的原始字节,作为注册响应初始验证的一部分,必须将其与 id 中编码的字节进行比较,因此从技术上讲,我们不能放弃它。

此外,无论出于何种原因,如果 base64url 编码不合适,RP 可能会使用未编码的原始值,因此也会返回 rawId。

Q3。如果我将公钥 ID 保存到数据库中(稍后使用该公钥 ID 创建allowCredentials列表),我应该遵循以下哪一个?

如上所述,这取决于 RP 实现,无论出于何种原因,如果 base64url 编码不合适,RP 可能会使用未编码的原始值并将其编码为 RP 喜欢的任何格式。

我存储 id 是因为它已经被编码成一种格式,便于在故障排除时在日志中复制/粘贴和比较。稍后我们将使用该 id 创建allowCredentials并将其发送回身份验证器。不需要做额外的工作base64url(rawId),使用id就完全没问题了。

于 2021-09-21T10:39:04.650 回答
0

在这种情况下,包含的 ArrayBuffer 很可能rawId已转换为 base64 以进行序列化,因此它们在您的示例中看起来相同。

至于使用哪个,我认为只要值在需要时以正确的编码或结构呈现,我认为这并不重要。

我正在使用的库提供并期望一个 byte[] 但我将它作为 base64 存储在数据库中。然后在序列化时将其再次转换为 base64 以将值发送到客户端,然后在传递给navigator.credentials.get().

至于为什么会这样,我怀疑有一个用例id不希望从 base64 字符串转换,所以 PublicKeyCredential 类型添加了它自己的[[identifier]]插槽的 ArrayBuffer 表示,但这只是我的猜想。

于 2021-07-29T08:27:22.237 回答