環境
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_ID
とYOUR_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
以下の情報を求められますので、入力していきます。
- ログインを行うかの回答
- 認証用URLを開き、使用するアカウントの選択
- アクセスリクエストの許可
- 認証コードのコピー
- 認証コードの入力
- デフォルトのプロジェクトの選択
これで、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サーバーを運営している方は是非導入を検討してみてください。