Bläddra i källkod

Merge pull request #2858 from quisse/patch-1

Attempting to make recaptcha v3 work
Akinori MUSHA 4 år sedan
förälder
incheckning
a61924f903
2 ändrade filer med 68 tillägg och 3 borttagningar
  1. 11 3
      app/models/agents/webhook_agent.rb
  2. 57 0
      spec/models/agents/webhook_agent_spec.rb

+ 11 - 3
app/models/agents/webhook_agent.rb

@@ -33,6 +33,7 @@ module Agents
         * `code` - The response code to the request. Defaults to '201'. If the code is '301' or '302' the request will automatically be redirected to the url defined in "response".
         * `recaptcha_secret` - Setting this to a reCAPTCHA "secret" key makes your agent verify incoming requests with reCAPTCHA.  Don't forget to embed a reCAPTCHA snippet including your "site" key in the originating form(s).
         * `recaptcha_send_remote_addr` - Set this to true if your server is properly configured to set REMOTE_ADDR to the IP address of each visitor (instead of that of a proxy server).
+        * `score_threshold` - Setting this when using reCAPTCHA v3 to define the treshold when a submission is verified. Defaults to 0.5
       MD
     end
 
@@ -48,7 +49,8 @@ module Agents
         "expected_receive_period_in_days" => 1,
         "payload_path" => "some_key",
         "event_headers" => "",
-        "event_headers_key" => "headers"
+        "event_headers_key" => "headers",
+        "score_threshold" => 0.5
       }
     end
 
@@ -100,8 +102,14 @@ module Agents
           return ["Not Authorized", 401]
         end
 
-        JSON.parse(response.body)['success'] or
-          return ["Not Authorized", 401]
+        body = JSON.parse(response.body)
+        if interpolated['score_threshold'].present? && body['score'].present?
+          body['score'] > interpolated['score_threshold'].to_f or
+            return ["Not Authorized", 401]
+        else
+          body['success'] or
+            return ["Not Authorized", 401]
+        end
       end
 
       [payload_for(params)].flatten.each do |payload|

+ 57 - 0
spec/models/agents/webhook_agent_spec.rb

@@ -560,6 +560,63 @@ describe Agents::WebhookAgent do
           expect(out).to eq(["Event Created", 201])
           expect(Event.last.payload).to eq(payload)
         end
+
+        it "should accept a request if recaptcha_secret is set and g-recaptcha-response given is verified and
+        reCAPTCHA v3 score is above score_treshold" do
+          agent.options['payload_path'] = '.'
+          agent.options['recaptcha_secret'] = 'supersupersecret'
+          agent.options['score_threshold'] = 0.5
+          webpayload = ActionDispatch::Request.new({
+              'action_dispatch.request.request_parameters' => payload.merge({ 'g-recaptcha-response' => 'somevalue' }),
+              'action_dispatch.request.path_parameters' => { secret: 'foobar' },
+              'REQUEST_METHOD' => "POST",
+              'HTTP_ACCEPT' => 'application/xml',
+              'HTTP_X_HELLO_WORLD' => "Hello Huginn"
+            })
+
+          checked = false
+          out = nil
+
+          stub_request(:any, /verify/).to_return { |request|
+            checked = true
+            { status: 200, body: '{"success":true, "score":0.9}' }
+          }
+
+          expect {
+            out = agent.receive_web_request(webpayload)
+          }.to change { checked }
+
+          expect(out).to eq(["Event Created", 201])
+          expect(Event.last.payload).to eq(payload)
+        end
+
+        it "should reject a request if recaptcha_secret is set and g-recaptcha-response given is verified and
+        reCAPTCHA v3 score is below score_treshold" do
+          agent.options['payload_path'] = '.'
+          agent.options['recaptcha_secret'] = 'supersupersecret'
+          agent.options['score_threshold'] = 0.5
+          webpayload = ActionDispatch::Request.new({
+              'action_dispatch.request.request_parameters' => payload.merge({ 'g-recaptcha-response' => 'somevalue' }),
+              'action_dispatch.request.path_parameters' => { secret: 'foobar' },
+              'REQUEST_METHOD' => "POST",
+              'HTTP_ACCEPT' => 'application/xml',
+              'HTTP_X_HELLO_WORLD' => "Hello Huginn"
+            })
+
+          checked = false
+          out = nil
+
+          stub_request(:any, /verify/).to_return { |request|
+            checked = true
+            { status: 200, body: '{"success":true, "score":0.1}' }
+          }
+
+          expect {
+            out = agent.receive_web_request(webpayload)
+          }.to change { checked }
+
+          expect(out).to eq(["Not Authorized", 401])
+        end
       end
     end
     context "with headers" do