web-dev-qa-db-ja.com

Nodeで正しいヘッダーとSHA512ハッシュトークンを使用して正しいTOTPを生成するにはどうすればよいですか?

私が割り当てられた最近の学校プロジェクトには、完了する必要があるコーディングの課題があります。チャレンジには複数の部分があり、最後の部分はプライベートGitHubリポジトリにアップロードし、特定の条件下でPOSTリクエストを実行して完了リクエストを送信します。

私はチャレンジの他の部分を無事に完了し、リクエストの提出で立ち往生しています。提出はこれらのルールに従う必要があります:

ソリューションリクエストの作成

まず、以下のようなJSON文字列を作成します。

{

"github_url": "https://github.com/YOUR_ACCOUNT/GITHUB_REPOSITORY",

"contact_email": "YOUR_EMAIL"

}

YOUR_EMAILのメールアドレスを入力し、YOUR_ACCOUNT/GITHUB_REPOSITORYのソリューションをプライベートGithubリポジトリに入力します。次に、ボディパーツとしてJSON文字列を使用して、次のURLにHTTP POSTリクエストを送信します。

CHALLENGE_URL

コンテンツタイプ

リクエストのContent-Type:はapplication/jsonである必要があります。

認証

URLは、RFC2617の第2章で説明されているHTTP基本認証によって保護されているため、POSTリクエストでAuthorization:ヘッダーフィールドを指定する必要があります。

  • HTTP基本認証のユーザーIDには、JSON文字列に入力したのと同じメールアドレスを使用します。
  • パスワードには、RFC6238 TOTPに準拠した10桁の時間ベースのワンタイムパスワードを入力します。

認証パスワード

TOTPパスワードを生成するには、次の設定を使用する必要があります。

  • RFC6238に従って正しいTOTPパスワードを生成する必要があります
  • TOTPのTime Step Xは30秒です。 T0は0です。
  • デフォルトのHMAC-SHA-512の代わりに、ハッシュ関数にHMAC-SHA-1を使用します。
  • トークン共有シークレットは、ユーザーIDの後にASCII文字列値"APICHALLENGE"が続きます(二重引用符は含みません)。

共有秘密の例

たとえば、ユーザーIDが"[email protected]"の場合、トークン共有シークレットは"[email protected]"(引用符なし)です。

POSTリクエストが成功した場合、サーバーはHTTPステータスコード200を返します。

私はこのアウトラインveryを慎重にたどって、さまざまな方法で自分の作品をテストしました。しかし、私はそれを正しく理解できないようです。 Nodeサーバーバックエンドからリクエストを行うことになっています。これは私がこれまでに行ったことです。npm initで新しいnpmプロジェクトを作成し、表示される依存関係をインストールしました以下のコードで:

const axios = require('axios');
const base64 = require('base-64');
const utf8 = require('utf8');

const { totp } = require('otplib');


const reqJSON = 
{
    github_url: GITHUB_URL,
    contact_email: MY_EMAIL
}
const stringData = JSON.stringify(reqJSON);

const URL = CHALLENGE_URL;
const sharedSecret = reqJSON.contact_email + "APICHALLENGE";

totp.options = { digits: 10, algorithm: "sha512" }

const myTotp = totp.generate(sharedSecret);
const isValid = totp.check(myTotp, sharedSecret);

console.log("Token Info:", {myTotp, isValid});




const authStringUTF = reqJSON.contact_email + ":" + myTotp;
const bytes = utf8.encode(authStringUTF);
const encoded = base64.encode(bytes);



const createReq = async () =>
{

    try 
    {

        // set the headers
        const config = {
            headers: {
                'Content-Type': 'application/json',
                "Authorization": "Basic " + encoded
            }
        };

        console.log("Making req", {URL, reqJSON, config});

        const res = await axios.post(URL, stringData, config);
        console.log(res.data);
    }
    catch (err)
    {
        console.error(err.response.data);
    }
};

createReq();

私が理解している限り、どこで間違いを犯しているかはわかりません。要件の理解に非常に注意を払いました。課題の概要を示すすべてのドキュメントを簡単に調べ、特定の条件下でTOTPを正しく生成するために必要な要件を収集しました。

Npmパッケージotplibは、渡したオプションでこれらの要件を満たすことができることがわかりました。

しかし、私の解決策は正しくありません。ソリューションを送信しようとすると、エラーメッセージ"Invalid token, wrong code"が表示されます。誰かが私が間違っていることを確認するのを手伝ってくれませんか?

これは長いプロジェクトだったので、私のすべての努力が無駄になりたくないのです。

お手数をおかけしますが、よろしくお願いいたします。私は非常に感謝しています。

2
ThisIsNotAnId

パッケージotplibのReadmeには、次のように記載されています。

_// TOTP defaults
{
  // ...includes all HOTP defaults
  createHmacKey: totpCreateHmacKey,
  Epoch: Date.now(),
  step: 30,
  window: 0,
}
_

したがって、Epoch (T0)のデフォルト値はRFC標準であるDate.now()です。タスクの説明では、_T0_が_0_であることを定義しています。

Epochのデフォルト値を_0_に変更する必要があります。

_totp.options = { digits: 10, algorithm: "sha512", Epoch: 0 }
_
3
doingitraith