You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebAuthn获取公钥与Credential ID问题求助:YubiKey NFC注册数据处理

Fixing WebAuthn Credential ID & Auth Data Handling with Yubico NFC Keys

Hey there! Let's work through your WebAuthn registration issues step by step. I see a key mistake in your code that's causing garbage data, plus I'll clarify exactly what credentialId and the public key are used for.

First: Fix the Credential ID Extraction

Your code has an error in how you slice the authData buffer to grab the credential ID. Right now you're using:

const credentialId = authData.slice( 55, credentialIdLength);

This is wrong— the credential ID starts at index 55 and spans credentialIdLength bytes, so the end index should be 55 + credentialIdLength, not just credentialIdLength. That's why you're getting unrecognizable data!

Second: Correctly Parse the Public Key

Your public key decoding logic is almost there, but let's make sure we're handling the buffer properly. WebAuthn public keys are CBOR-encoded, so using your CBOR decoder is the right move once you have the correct byte slice.

Corrected Code Snippet

Here's the fixed section with clear comments explaining each step:

.then((cred) => {
  console.log("NEW CREDENTIAL", cred);
  const utf8Decoder = new TextDecoder('utf-8');
  const decodedClientData = utf8Decoder.decode(cred.response.clientDataJSON);
  const clientDataObj = JSON.parse(decodedClientData);
  
  // Decode the CBOR-formatted attestation object (this part was correct)
  const decodedAttestationObj = CBOR.decode(cred.response.attestationObject);
  const { authData } = decodedAttestationObj;

  // Extract credential ID length (first 2 bytes after the fixed authData header)
  const dataView = new DataView(authData.buffer.slice(53, 55));
  const credentialIdLength = dataView.getUint16(0, false); // false = big-endian (WebAuthn standard)

  // Extract the actual credential ID bytes
  const credentialIdBytes = authData.slice(55, 55 + credentialIdLength);
  // Convert to base64url for easy storage (industry standard for WebAuthn)
  const credentialId = btoa(String.fromCharCode(...new Uint8Array(credentialIdBytes)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');

  // Extract and decode the public key bytes
  const publicKeyBytes = authData.slice(55 + credentialIdLength);
  const publicKeyObject = CBOR.decode(publicKeyBytes.buffer);

  console.log("Valid Credential ID:", credentialId);
  console.log("Valid Public Key:", publicKeyObject);
})

What Are Credential ID and Public Key Used For?

Let's break down their core purposes:

  • Credential ID: This is a unique identifier for the specific Yubico key credential you just created for the user. You must store this in your database, linked directly to the user's account. When the user tries to log in later, you'll send this ID back to their browser so it can locate the correct key to use for authentication.
  • Public Key: This is the public half of the asymmetric key pair generated securely on the Yubico device. Store this alongside the credential ID. During login, the client will sign a server-generated challenge with the private key (locked to the Yubico device), and your server will use this public key to verify the signature—proving the user has physical access to the correct key.

Quick Production Tips

  • Always store credential IDs as base64url (not raw bytes) in your database—it avoids encoding headaches in APIs and storage systems.
  • For production systems, you should also validate the attestation object (to confirm the key comes from a trusted manufacturer like Yubico) and verify that the client data challenge matches exactly what your server sent.

内容的提问来源于stack exchange,提问作者Alexi Coard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:58:52