本文へスキップ
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"

引用符で囲まれた最初の値はブラウザーが報告したオリジン、2 番目は設定した値です。ログイン時には、文言が「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",
    });

関連するエラー

署名エラーデータベースをすべて見る