跳到主要内容
ecdsa.com
SimpleWebAuthn (@simplewebauthn/server)WebAuthn 与通行密钥

错误信息

Unexpected registration response origin "http://localhost:3000", expected "https://app.example.com"

也可能输出为

  • Unexpected authentication response origin "http://localhost:3000", expected "https://app.example.com"
  • Unexpected registration response challenge "b3RoZXI", expected "c2VydmVyLWNoYWxsZW5nZS0xMjM"

第一个带引号的值是浏览器报告的源,第二个是你的配置。登录时,文本中写的是“authentication response”;挑战值不匹配时,同一个库会报出“Unexpected registration response challenge …”。

SimpleWebAuthn (@simplewebauthn/server) — verifyRegistrationResponse / verifyAuthenticationResponse

含义

浏览器在 `clientDataJSON`(认证器签名的数据)中记录了页面的源,它与你的服务器传给 SimpleWebAuthn 的 `expectedOrigin` 不一致。这项检查是为了防止在一个站点上执行的凭证流程(例如在仿冒的钓鱼网站上)被另一个站点接受。认证器本身没有问题;问题在于服务器认为自己的页面所在的位置,与流程实际运行的位置不一致。

原因

修复方法

  1. 1.

    显式列出每一个合法的源

    `expectedOrigin` 接受数组。只列出你控制的源;切勿直接采用请求本身携带的源。

    js
    const verification = await verifyRegistrationResponse({
      response: body,
      expectedChallenge: session.currentChallenge,
      // Every origin that legitimately hosts your sign-up page, exactly as browsers report it:
      expectedOrigin: ["https://app.example.com", "https://www.example.com"],
      expectedRPID: "example.com",
    });
  2. 2.

    添加 Android 应用的源

    计算该应用签名证书的 SHA-256,以 base64url 编码,然后按 `android:apk-key-hash:` 的格式添加进去。

    js
    // Android apps report "android:apk-key-hash:<base64url SHA-256 of the app signing certificate>".
    // SHA-256 fingerprint from Play Console or: keytool -list -v -keystore release.jks | grep SHA256
    const fingerprintHex = process.env.ANDROID_SIGNING_CERT_SHA256.replaceAll(":", "");
    const androidOrigin = "android:apk-key-hash:" + Buffer.from(fingerprintHex, "hex").toString("base64url");
    
    const verification = await verifyRegistrationResponse({
      response: body,
      expectedChallenge: session.currentChallenge,
      expectedOrigin: ["https://example.com", androidOrigin],
      expectedRPID: "example.com",
    });

相关错误

浏览完整的签名错误库