axios で reCAPTCHA のレスポンストークンの検証を行う方法

JavaScriptreCAPTCHA

JavaScript のライブラリ axios で reCAPTCHA のレスポンストークンの検証を行う方法をかんたんにまとめます。

reCAPTCHA は一般に次の 3 ステップで利用するものですが、今回はこのうちの 3 ステップめのサーバーサイドにおける処理が対象です。

  1. (クライアントサイド)トークンを取得する
  2. (クライアントサイド)取得したトークンを他のデータといっしょにサーバーサイドに送る
  3. (サーバーサイド)クライアントから送られたトークンを検証する

動作確認に使った axios のバージョンは 0.20.0 です(バージョンが変わるとあてはまらなくなることもあると思います、参考にされる際は注意してください)。

動作確認は reCAPTCHA v3 だけで行いましたが、検証に利用する API のエンドポイントは v3 も v2 も共通のようなので v2 でも同じだと思います。

axios で reCAPTCHA のレスポンストークンの検証を行う方法

reCAPTCHA のトークンを検証するには、次の 3 つのパラメータを付けて所定の URL に POST リクエストを送ります。

パラメータ:

  • secret: シークレットキー
  • response: クライアントサイドから送られたトークン
  • remoteip: (非必須)ユーザーの IP アドレス

URL:

https://developers.google.com/recaptcha/docs/verify

secret は reCAPTCHA のコンソールの設定ページで取得できるシークレットキーです。 response はクライアントサイドで取得したトークンです。 remoteip はクライアントの IP アドレスです。 remoteip は非必須です。

これを axios で行うには次のようにします。

const axios = require(`axios`)
const RECAPTCHA_VERIFY_URL = `https://www.google.com/recaptcha/api/siteverify`


let params = {
  secret: `シークレット`,
  response: `トークン`,
  remoteip: `クライアント IP アドレス`,
}
recaptchaRes = await axios.post(RECAPTCHA_VERIFY_URL, undefined, {
  params: params,
})

axios.post() の第 2 引数が undefined で、データは第 3 引数の params キーを使って渡しているところがポイントです。 こうやっている理由は、 reCAPTCHA のエンドポイントには application/x-www-form-urlencoded フォーマットでデータを送信する必要があるようなのですが、 axios.post() を普通のやり方↓で使うと JSON リクエストになってしまうからです。

const axios = require(`axios`)
const RECAPTCHA_VERIFY_URL = `https://www.google.com/recaptcha/api/siteverify`

// このやり方は失敗します
let params = {
  secret: `シークレット`,
  response: `トークン`,
  remoteip: `クライアント IP アドレス`,
}
recaptchaRes = await axios.post(RECAPTCHA_VERIFY_URL, params)

axios.post(url, params) という形でデータを送ると、正しいデータを添えても「 secretresponse が送られていませんよ」という旨のエラー↓が返ってきます。 原因がわからないとハマります。

'error-codes': [ 'missing-input-response', 'missing-input-secret' ]

ということで、まとめです。

  • reCAPTCHA の検証のエンドポイントには application/x-www-form-urlencoded フォーマットでデータを送る必要がある( JSON だとパラメータを認識してくれず検証が失敗する)
  • axios はデフォルトでは JSON フォーマットでリクエストデータを送る( application/x-www-form-urlencoded フォーマットで送るには少し工夫が必要)

ちなみに、上の方法とは違いますが、 axios の公式 REAMDE でも application/x-www-form-urlencoded フォーマットで POST リクエストを行う方法が紹介されているので、詳しく知りたい方はそちらもご覧ください。

参考


アバター
後藤隼人 ( ごとうはやと )

Python や PHP を使ってソフトウェア開発やウェブ制作をしています。詳しくはこちら