0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NodejsでreCAPTCHA実装

Last updated at Posted at 2024-06-02

環境

OS: Ubuntu Server 22.04(SSHでローカルコンピュータから接続)
作ったProject名称: MIRAI
Nodejs: Nodejs v20.14.0

reCAPTCHAのAPI keyの取得

GoogleCloudPlatformにアクセスして、API keyを取得します。

ラベルという項目に認証を実行するドメインを入力します。
v2かv3かというラジオボタンがありますが、私は厳密に人間のみを通したかったのでv2を選択しました。
プロジェクト名を入力したら送信して完了です。

フロントエンドの作成

まずは、フロントエンドを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>reCAPTCHA</title>
    <script src="https://www.google.com/recaptcha/enterprise.js" async defer></script>
</head>
<body>
    <form action="/submit" method="POST">
        <input type="text" name="name" placeholder="名前">
        <input type="email" name="email" placeholder="メールアドレス">
        <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY" action="auth"></div>
        <button type="submit">送信</button>
    </form>
</body>
</html>

YOUR_SITE_KEYの部分に取得したAPI keyを入力します。
たったこれだけのコードでreCAPTCHAをページに表示することができます。

バックエンドの作成

さて、ここからが本題です。
まずは、Nodejsのプロジェクトを作成します。

$ mkdir MIRAI
$ cd MIRAI
$ npm init -y
$ npm install http @google-cloud/recaptcha-enterprise

次に、http moduleを使ってサーバーを立ち上げます。

const http = require('http');
const fs = require('fs');
const { RecaptchaEnterpriseServiceClient } = require('@google-cloud/recaptcha-enterprise');

const server = http.createServer((req, res) => {
    if (req.url === '/submit' && req.method === 'POST') {
        let body = '';
        req.on('data', (chunk) => {
            body += chunk.toString();
        });
        req.on('end', () => {
            const token = body.split('=')[1];
            createAssessment(token).then((result) => {
                res.writeHead(200, {'Content-Type': 'text/html'});
                res.end('Success');
            }).catch((err) => {
                res.writeHead(500, {'Content-Type': 'text/html'});
                res.end('Internal Server Error');
            });
        });
    } else {
        res.writeHead(404, {'Content-Type': 'text/html'});
        res.end('404 Not Found');
    }
});

ベースのサーバープログラムはいつも通りに書きます。
createAssessment関数はreCAPTCHAのAPIを使って認証を行う関数です。
次に、createAssessment関数を作成します。これはほとんどGoogleCloudConsoleに載っていたコードをそのまま使います。

async function createAssessment(token) {
    const projectID = "YOUR_PROJECT_ID";// ここにプロジェクトIDを入力
    const recaptchaKey = "YOUR_SITE_KEY";// ここにAPI keyを入力
    const recaptchaAction = "auth";
    // reCAPTCHA クライアントを作成する。
    // TODO: クライアント生成コードをキャッシュに保存するか(推奨)、メソッドを終了する前に client.close() を呼び出す。
    const client = new RecaptchaEnterpriseServiceClient();
    const projectPath = client.projectPath(projectID);

    // 評価リクエストを作成する。
    const request = ({
        assessment: {
            event: {
                token: token,
                siteKey: recaptchaKey,
            },
        },
        parent: projectPath,
    });

    const [response] = await client.createAssessment(request);

    // トークンが有効かどうかを確認する。
    if (!response.tokenProperties.valid) {
        console.log(`The CreateAssessment call failed because the token was: ${response.tokenProperties.invalidReason}`);
        return null;
    }

    // 想定どおりのアクションが実行されたかどうかを確認する。
    // The `action` property is set by user client in the grecaptcha.enterprise.execute() method.
    if (response.tokenProperties.action === recaptchaAction) {
        // リスクスコアと理由を取得する。
        // 評価の解釈の詳細については、以下を参照:
        // https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
        console.log(`The reCAPTCHA score is: ${response.riskAnalysis.score}`);
        response.riskAnalysis.reasons.forEach((reason) => {
            console.log(reason);
        });

        return response.riskAnalysis.score;
    } else {
        console.log("The action attribute in your reCAPTCHA tag does not match the action you are expecting to score");
        return null;
    }
}

YOUR_PROJECT_IDYOUR_SITE_KEYの部分にそれぞれプロジェクトIDとAPI keyを入力します。
これで、reCAPTCHAを使って認証を行うことができます。
と思いきや、エラーが出ました。

Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
    at GoogleAuth.getApplicationDefaultAsync (/home/ubuntu/MIRAI/node_modules/@google-cloud/recaptcha-enterprise/node_modules/google-auth-library/build/src/auth/googleauth.js:160:19)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async GoogleAuth.getClient (/home/ubuntu/MIRAI/node_modules/@google-cloud/recaptcha-enterprise/node_modules/google-auth-library/build/src/auth/googleauth.js:496:17)
    at async GrpcClient._getCredentials (/home/ubuntu/MIRAI/node_modules/@google-cloud/recaptcha-enterprise/build/src/v1/recaptcha_enterprise_client.js:107:23)
    at async GrpcClient.createAssessment (/home/ubuntu/MIRAI/node_modules/@google-cloud/recaptcha-enterprise/build/src/v1/recaptcha_enterprise_client.js:116:23)
    at async createAssessment (/home/ubuntu/MIRAI/index.js:23:23)

これは、GoogleCloudPlatformにアクセスするための認証情報がないために出るエラーです。
いわゆるADC(Application Default Credentials)がないということです。
これを解決していきます。

ADC(Application Default Credentials)の取得

gcloud CLIのインストール

まずは、gcloud CLIをインストールします。
以下のページを参考にしています。

sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates gnupg curl sudo
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-cli

次にgcloud CLIの初期設定を行います。

gcloud init

以下の情報を求められますので、入力していきます。

  1. ログインを行うかの回答
  2. 認証用URLを開き、使用するアカウントの選択
  3. アクセスリクエストの許可
  4. 認証コードのコピー
  5. 認証コードの入力
  6. デフォルトのプロジェクトの選択

これで、ADC(Application Default Credentials)が取得できました。
わかりにくい点は先ほどのページに書いてあります。

Google アカウントのユーザー認証情報を ADC に提供する

以下のコマンドを実行します。

gcloud auth application-default login

先ほどの手順と同じようにログインを行います。
これで、ADC(Application Default Credentials)が取得できました。

再度、reCAPTCHAを使って認証を行う

再度、サーバーを立ち上げて、reCAPTCHAを使って認証を行います。

$ node index.js

ブラウザでhttp://localhost:3000にアクセスして、reCAPTCHAを使って認証を行います。
あなたがロボットでなければ、良い感じに認証が通るはずです。

お疲れさまでした。これで無事にreCAPTCHAを使って認証を行うことができました。
GoogleCloudPlatformの説明には、ADC(Application Default Credentials)が必要であることが書いてなかったので、しばらくハマりました。
ADC(Application Default Credentials)が必要であることを覚えておいてください。(従来の方法ではsecretKeyを使っていましたが、現在はADC(Application Default Credentials)を使うことで、よりセキュアに認証を行うことができます。)

参考記事

最後に

この記事のコード引用元になったプロジェクト

Discordサーバーを運営している方は是非導入を検討してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?