reCAPTCHA v3の認証エラー(timeout-or-duplicate)対応

reCAPTCHA v3 で、エラーにならなくてもいいのに発生していたエラー( timeout-or-duplicate )に対応したメモです。

    reCAPTCHA v3 とは

    reCAPTCHAはbotを判別してフォームをスパムから守る仕組みです。

    最新バージョンの reCAPTCHA v3 ではユーザーの行動から算出したスコアでbotを識別しており、いままでのように「私はロボットではありません」にチェックを入れたり、読みにくい文字を読んだり画像をしたり…というユーザーの手間がなくなりました。

    エラーの種類

    Error code Description
    missing-input-secret シークレットパラメータなし
    invalid-input-secret シークレットパラメータが無効または不正な形式
    missing-input-response 応答パラメータなし
    invalid-input-response 応答パラメータが無効または不正な形式
    bad-request リクエストが無効または不正な形式
    timeout-or-duplicate 応答は無効になりました : 古すぎるか、以前に使用されたことがある

    timeout-or-duplicate エラー

    いくつかあるエラーのうち、特にクセモノなのがtimeout-or-duplicate(タイムアウトまたは既に使われた値)のエラーです。

    特にタイムアウトは5分に設定されているらしく、フォーム画面を開いてトークンを取得してからページを開いたまま5分経つと認証エラーになる模様です。入力する分量が多かったり、なにか資料などを確認する必要があったりすると割と簡単に経過しそうな時間なので、特に不正ではなくとも普通にエラーが発生しそうです(しました)。また、設定時間の変更はできないようです。

    timeout-or-duplicate エラーを処理する

    今回はtimeout-or-duplicate エラーが発生しても通常通りの処理をするように対応しました。

    エラー内容の取得

    PHP
    $response = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . $recaptcha_secret_key . '&response=' . $recaptcha_token);
    $verify = json_decode($response);
    
    if($verify->success) {
    	// 成功
    } else {
    	// 失敗
    	$error = $verify->{'error-codes'};
    }
    

    レスポンスの中身

    $verifyをログに出すと以下のようなレスポンスが返ってきていました。successの値はboolが入るけどなんか出力時に1と空になってる。

    成功時

    stdClass Object
    (
    	[success] => 1
    	[challenge_ts] => 2020-07-13T03:36:27Z
    	[hostname] => memdx.com
    	[score] => 0.9
    	[action] => submit
    )
    

    エラー時

    stdClass Object
    (
    	[success] => 
    	[error-codes] => Array
    		(
    			[0] => timeout-or-duplicate
    		)
    )
    

    エラー時の判定

    複数のエラーが発生していた場合(発生しうるのか?)はちゃんとエラー扱いにしたいので、ここではエラーコードの個数もカウントしています。

    PHP
    if( count($error) == 1 && $error[0] == 'timeout-or-duplicate' ){
    	//timeout-or-duplicateエラーを無視する処理
    }else{
    	// 失敗処理
    }
    

    注意点

    上記はPHPでの処理例ですが、レスポンスのerror-codesがハイフンを含むため、{}で囲う必要があります。

    PHP
    // エラー
    $error = $verify->error-codes;
    
    // OK
    $error = $verify->{'error-codes'};
    

    あとどうでもいいけどテストする時にいちいち5分待つのが地味にめんどくさいですね。

    参考

    シェア
    野良人 代表
    新免祥太
    1988年岡山生まれ。外食企業のWEB・EC担当を経験したのち、2013年12月より「野良人(のらんど)」の屋号で独立しWEBデザイン・プログラミングなどWEBサイト制作の工程全般を請け負っています。お気軽にご相談ください。
    広告
    <次の記事(2020/12/31)
    【Stripe】ダッシュボードで作成した商品のCheckout決済を実装する
    前の記事>(2020/12/05)
    Local(local by flywheel)がDockerのTLS証明書エラーで起動できずにループする現象に対応
    記事一覧