1 
2 module vibeauth.challenges.recaptcha;
3 
4 import vibe.http.client;
5 import vibe.stream.operations;
6 import vibe.data.json;
7 
8 import std.conv;
9 
10 import vibeauth.challenges.base;
11 
12 /// Class that implements the google recaptcha challenge
13 class ReCaptcha : IChallenge {
14 
15   private immutable {
16     string siteKey;
17     string secretKey;
18   }
19 
20   this(string siteKey, string secretKey) {
21     this.siteKey = siteKey;
22     this.secretKey = secretKey;
23   }
24 
25   /// Generate a challenge. The request must be initiated from the challenge template
26   string generate(HTTPServerRequest req, HTTPServerResponse res) {
27     return "";
28   }
29 
30   /// Get a template for the current challenge
31   string getTemplate(string challangeLocation) {
32     auto tpl = `<script src="https://www.google.com/recaptcha/api.js?render=` ~ siteKey ~ `"></script>
33       <script>
34       grecaptcha.ready(function() {
35           grecaptcha.execute('` ~ siteKey ~ `', {action: 'login'}).then(function(token) {
36             document.querySelector("#recaptchaValue").value = token;
37           });
38       });
39       </script>
40       <input id="recaptchaValue" name="response" type="hidden" value="">`;
41 
42     return tpl;
43   }
44 
45   /// Returns the site key
46   Json getConfig() {
47     auto result = Json.emptyObject;
48 
49     result["siteKey"] = siteKey;
50 
51     return result;
52   }
53 
54   /// Validate the challenge
55   bool validate(HTTPServerRequest req, HTTPServerResponse res, string response) {
56     Json result;
57 
58     requestHTTP("https://www.google.com/recaptcha/api/siteverify?secret=" ~ secretKey ~ "&response=" ~ response,
59       (scope req) {
60         req.method = HTTPMethod.POST;
61         req.headers["Content-length"] = "0";
62       },
63       (scope res) {
64         result = res.bodyReader.readAllUTF8().parseJsonString;
65       }
66     );
67 
68     if("success" !in result) {
69       return false;
70     }
71 
72     return result["success"].to!bool == true;
73   }
74 }